David van Moolenbroek 27852ebe53 UDS: full rewrite
This new implementation of the UDS service is built on top of the
libsockevent library.  It thereby inherits all the advantages that
libsockevent brings.  However, the fundamental restructuring
required for that change also paved the way for resolution of a
number of other important open issues with the old UDS code.  Most
importantly, the rewrite brings the behavior of the service much
closer to POSIX compliance and NetBSD compatibility.  These are the
most important changes:

- due to the use of libsockevent, UDS now supports multiple suspending
  calls per socket and a large number of standard socket flags and
  options;
- socket address matching is now based on <device,inode> lookups
  instead of canonized path names, and socket addresses are no longer
  altered either due to canonization or at connect time;
- the socket state machine is now well defined, most importantly
  resolving the erroneous reset-on-EOF semantics of the old UDS, but
  also allowing socket reuse;
- sockets are now connected before being accepted instead of being
  held in connecting state, unless the LOCAL_CONNWAIT option is set
  on either the connecting or the listening socket;
- connect(2) on datagram sockets is now supported (needed by syslog),
  and proper datagram socket disconnect notification is provided;
- the receive queue now supports segmentation, associating ancillary
  data (in-flight file descriptors and credentials) with each segment
  instead of being kept fully separately; this is a POSIX requirement
  (and needed by tmux);
- as part of the segmentation support, the receive queue can now hold
  as many packets as can fit, instead of one;
- in addition to the flags supported by libsockevent, the MSG_PEEK,
  MSG_WAITALL, MSG_CMSG_CLOEXEC, MSG_TRUNC, and MSG_CTRUNC send and
  receive flags are now supported;
- the SO_PASSCRED and SO_PEERCRED socket options are replaced by
  LOCAL_CREDS and LOCAL_PEEREID respectively, now following NetBSD
  semantics and allowing use of NetBSD libc's getpeereid(3);
- memory usage is reduced by about 250 KB due to centralized in-flight
  file descriptor tracking, with a limit of OPEN_MAX total rather than
  of OPEN_MAX per socket;
- memory usage is reduced by another ~50 KB due to removal of state
  redundancy, despite the fact that socket path names may now be up to
  253 bytes rather than the previous 104 bytes;
- compared to the old UDS, there is now very little direct indexing on
  the static array of sockets, thus allowing dynamic allocation of
  sockets more easily in the future;
- the UDS service now has RMIB support for the net.local sysctl tree,
  implementing preliminary support for NetBSD netstat(1).

Change-Id: I4a9b6fe4aaeef0edf2547eee894e6c14403fcb32
2017-03-09 23:39:56 +00:00

420 lines
9.9 KiB
Plaintext

# /usr/etc/rc - continued system initialization.
RANDOM_FILE=/usr/adm/random.dat
LOCAL_FILE=/usr/etc/rc.local
ARCH="`sysenv arch`"
if [ ! "$ARCH" ]
then # Older kernels do not provide an arch sysenv variable.
# We assume we are on x86 then, as existing systems with
# kernel and userland (i.e. this script) unsynchronized
# will be x86.
ARCH=i386
fi
# Get $SERVICES_DIRS
. /etc/rc.conf
# Directories to find services in
if [ ! "$SERVICES_DIRS" ]
then SERVICES_DIRS=/service
fi
# Booting from cd?
bootcd="`/bin/sysenv bootcd`"
case "$#:$1" in
1:start|1:stop)
action=$1
;;
*) echo >&2 "Usage: $0 [start|stop]"
exit 1
esac
if [ -f "$LOCAL_FILE" ]
then . "$LOCAL_FILE" $1
fi
disabled()
{
ifs="$IFS"; IFS=,
for skip in `sysenv disable`
do
if [ "$skip" = "$1" ]
then
IFS="$ifs"; unset ifs
return 0
fi
done
IFS="$ifs"; unset ifs
return 1
}
daemonize()
{
# Function to start a daemon, if it exists.
local IFS=':'
local name="$1"
test "$1" = tcpd && name="$2"
for dir in $PATH
do
if [ -f "$dir/$1" ]
then
# check if this service is disabled at the boot monitor.
if disabled $name; then return; fi
echo -n " $name"
"$@" &
return
fi
done
}
up()
{
# Function to dynamically start a system service
opt=""
prefix=$(expr "$1 " : '\(-\)')
if [ "$prefix" = "-" ];
then
opt=$1
shift
fi
service=$1
shift
# First check if this service is disabled at the boot monitor.
if disabled $service; then return; fi
# Service is not disabled. Try to bring it up.
found=""
for dir in $SERVICES_DIRS
do bin=$dir/$service
if [ -x $bin -a -z "$found" ]
then minix-service $opt up $bin "$@"
echo -n " $service"
found=yes
fi
done
if [ -z "$found" ]
then echo " ($service not found in $SERVICES_DIRS)"
fi
}
get_eth_labels() {
# Filter out the non-vlan ethernet entries from inet.conf.
# Produce as output a list of "drivername_instancenr"-formatted labels.
sed 's/\008/ /g' /etc/inet.conf | \
sed -n 's/^ *eth[0-9][0-9]* *\([^ ][^ ]*\) *\([0-9][0-9]*\).*$/\1_\2/p' | \
grep -v '^vlan_'
}
# Detect expansion boards on the BeagleBone and load the proper drivers.
capemgr() {
# Probe each possible cape EEPROM slave address for a BeagleBone cape.
for slave_addr in 54 55 56 57
do
# See if there is a readable EEPROM with address ${slave_addr}.
eepromread -f /dev/i2c-3 -a 0x${slave_addr} > /dev/null 2>&1
RESULT=$?
if [ $RESULT -eq 0 ]
then
# Found an alive EEPROM. Try reading the cape name.
CAPE=`eepromread -i -f /dev/i2c-3 -a 0x${slave_addr} | \
sed -n 's/^PART_NUMBER : \(.*\)$/\1/p' | \
sed -e 's/\.*$//g'` # Strip trailing periods.
# Look for a cape specific RC script.
if [ -x /etc/rc.capes/${CAPE} ]
then
# CAT24C256 EEPROM -- all capes have this chip.
test -e /dev/eepromb3s${slave_addr} || \
(cd /dev && MAKEDEV eepromb3s${slave_addr})
up cat24c256 -dev /dev/eepromb3s${slave_addr} \
-label cat24c256.3.${slave_addr} \
-args "bus=3 address=0x${slave_addr}"
# Load the drivers for the cape and do any other configuration.
. "/etc/rc.capes/${CAPE}"
else
echo ""
echo "** UNSUPPORTED CAPE: ${CAPE}"
echo ""
fi
fi
done
}
DAEMONS=/etc/rc.daemons
case $action in
start)
# Select console font.
test -f /etc/font && loadfont /etc/font </dev/console
# Cleanup.
rm -rf /tmp/* /usr/run/* /usr/spool/lpd/* /usr/spool/locks/*
# Start servers and drivers set at the boot monitor.
echo -n "Starting services:"
up -n random -dev /dev/random -period 3HZ
# load random number generator
if [ -f $RANDOM_FILE ]
then
cat < $RANDOM_FILE >/dev/random
# overwrite $RANDOM_FILE. We don't want to use this data again
dd if=/dev/random of=$RANDOM_FILE bs=1024 count=1 2> /dev/null
else
# We couldn't find the old state to restart from, so use a binary
# file and the current date instead, even if this is less than ideal.
cat /bin/sh >> /dev/urandom
date >> /dev/urandom
fi
# start network driver instances for all configured ethernet devices
for label in $(get_eth_labels); do
driver=$(echo $label | sed 's/\(.*\)_.*/\1/')
instance=$(echo $label | sed 's/.*_//')
eval arg=\$${driver}_arg
if [ ! -z "$arg" ]; then arg=" $arg"; fi
arg="-args \"instance=$instance$arg\""
eval up $driver -label $label $arg -period 5HZ
done
if [ X`/bin/sysenv lwip` = Xyes ]
then
up lwip -script /etc/rs.inet -dev /dev/ip
else
up inet -script /etc/rs.inet -dev /dev/ip
fi
# pty needs to know the "tty" group ID
up pty -dev /dev/ptmx -args "gid=`stat -f '%g' /dev/ptmx`"
up uds
up -n ipc
up log -dev /dev/klog
if [ $ARCH = i386 ]
then
up -n printer -dev /dev/lp -period 10HZ
# start VirtualBox time sync driver if the device is there
if grep '^[^ ]* [^ ]* 80EE:CAFE[^ ]* ' /proc/pci >/dev/null; then
up -n vbox -period 10HZ
fi
fi
echo .
# Network initialization.
(: </dev/tcp) 2>/dev/null && net=t # Is there a TCP/IP server?
echo -n "Starting daemons:"
daemonize update
# Ugly error message when starting cron from CD.
# (and cron unnecessary then so..)
if [ ! -f /CD ]
then daemonize cron
else mkdir /tmp/log
rm -f /var/log || true
ln -s /tmp/log /var/log || true
. /etc/rc.cd
fi
echo .
# i2c only supported on ARM at the moment
if [ $ARCH = earm ]
then
echo -n "Starting i2c subsystem: "
for bus in 1 2 3
do
test -e /dev/i2c-${bus} || (cd /dev && MAKEDEV i2c-${bus})
up i2c -dev /dev/i2c-${bus} -label i2c.${bus} \
-args instance=${bus}
done
echo .
BOARD_NAME=`sysenv board`
case "${BOARD_NAME}" in
ARM-ARMV7-TI-BB-WHITE)
echo "Running on a BeagleBone"
echo -n "Starting i2c device drivers: "
# start EEPROM driver for reading board info
test -e /dev/eepromb1s50 || \
(cd /dev && MAKEDEV eepromb1s50)
up cat24c256 -dev /dev/eepromb1s50 \
-label cat24c256.1.50 \
-args 'bus=1 address=0x50'
# Start TPS65217 driver for power management.
up tps65217 -label tps65217.1.24 \
-args 'bus=1 address=0x24'
# check for the presence of a display
eepromread -f /dev/i2c-2 -n > /dev/null 2>&1
RESULT=$?
if [ $RESULT -eq 0 ]
then
# start eeprom driver for reading EDID.
test -e /dev/eepromb2s50 || \
(cd /dev && MAKEDEV eepromb2s50)
up cat24c256 -dev /dev/eepromb2s50 \
-label cat24c256.2.50 \
-args 'bus=2 address=0x50'
# start frame buffer
#up fb -dev /dev/fb0 -args edid.0=cat24c256.2.50
# fb hasn't been ported to AM335X yet.
fi
if [ -e /service/usbd ]
then
echo "Starting USBD"
up usbd
fi
# Detect expansion boards and start drivers.
capemgr
;;
ARM-ARMV7-TI-BB-BLACK)
echo "Running on a BeagleBone Black"
echo -n "Starting i2c device drivers: "
# start EEPROM driver for reading board info
test -e /dev/eepromb1s50 || \
(cd /dev && MAKEDEV eepromb1s50)
up cat24c256 -dev /dev/eepromb1s50 \
-label cat24c256.1.50 \
-args 'bus=1 address=0x50'
# Start TPS65217 driver for power management.
up tps65217 -label tps65217.1.24 \
-args 'bus=1 address=0x24'
# Start TDA19988 driver for reading EDID.
up tda19988 -label tda19988.1.3470 -args \
'cec_bus=1 cec_address=0x34 hdmi_bus=1 hdmi_address=0x70'
# start frame buffer
#up fb -dev /dev/fb0 -args edid.0=tda19988.1.3470
# fb hasn't been ported to AM335X yet.
if [ -e /service/usbd ]
then
echo "Starting USBD"
up usbd
fi
# Detect expansion boards and start drivers.
capemgr
;;
ARM-ARMV7-TI-BBXM-GENERIC)
echo "Running on a BeagleBoard-xM"
echo -n "Starting i2c device drivers: "
# Start TPS65950 driver for power management.
up tps65950 -label tps65950.1.48 \
-args 'bus=1 address=0x48'
# Set the system time to the time in the TPS65950's RTC
readclock
# check for the presence of a display
eepromread -f /dev/i2c-3 -n > /dev/null 2>&1
RESULT=$?
if [ $RESULT -eq 0 ]
then
# start eeprom driver for reading edid
test -e /dev/eepromb3s50 || \
(cd /dev && MAKEDEV eepromb3s50)
up cat24c256 -dev /dev/eepromb3s50 \
-label cat24c256.3.50 \
-args 'bus=3 address=0x50'
# start frame buffer
up fb -dev /dev/fb0 -args edid.0=cat24c256.3.50
fi
;;
esac
echo .
fi
if [ "$net" ]
then
if [ -f /etc/rc.net ]
then
# Let a customized TCP/IP initialization script figure it out.
. /etc/rc.net
else
# Standard network daemons.
echo -n "Starting networking:"
if grep -s 'psip0.*default' /etc/inet.conf >/dev/null
then ifconfig -h 10.0.0.1
else
if [ X`/bin/sysenv lwip` = Xyes ]
then
dhcpd --lwip &
echo -n " dhcpd"
else
daemonize dhcpd
fi
fi
daemonize nonamed -L
if [ -f "$DAEMONS" ]
then . "$DAEMONS"
fi
# The last daemon has been started, so close the list:
echo .
fi
fi
if [ "$net" ]
then
# Get the nodename from the DNS and set it.
trap '' 2
intr -t 20 hostaddr -h
trap 2
fi
# Load the stored hostname into the sysctl database.
test -r /etc/hostname.file && hostname $(cat /etc/hostname.file)
# Recover files being edited when the system crashed.
test -f /usr/bin/elvprsv && elvprsv /usr/tmp/elv*
# Run the daily cleanup on systems that are not on at night.
test -f /usr/etc/daily && sh /usr/etc/daily boot &
;;
stop)
# Save random data, if /usr is mounted rw.
if grep ' \/usr .*rw.*' /etc/mtab >/dev/null
then
if dd if=/dev/random of=$RANDOM_FILE.new bs=1024 count=1 2>/dev/null
then
mv $RANDOM_FILE.new $RANDOM_FILE
else
echo 'Failed to save random data.'
fi
fi
esac