diff options
author | Benedikt Boehm <hollow@gentoo.org> | 2005-09-03 16:10:27 +0000 |
---|---|---|
committer | Benedikt Boehm <hollow@gentoo.org> | 2005-09-03 16:10:27 +0000 |
commit | 15d9155808de928fa26bfeaaecfee7210afde0d3 (patch) | |
tree | f113365bda736d949d39dd94bd99346056030e30 /sbin | |
download | baselayout-vserver-15d9155808de928fa26bfeaaecfee7210afde0d3.tar.gz baselayout-vserver-15d9155808de928fa26bfeaaecfee7210afde0d3.tar.bz2 baselayout-vserver-15d9155808de928fa26bfeaaecfee7210afde0d3.zip |
import initial baselayout sources (1.12.0_pre8)
svn path=/baselayout-vserver/trunk/; revision=3
Diffstat (limited to 'sbin')
-rwxr-xr-x | sbin/MAKEDEV | 1894 | ||||
-rwxr-xr-x | sbin/MAKEDEV-gentoo.patch | 210 | ||||
-rwxr-xr-x | sbin/depscan.sh | 93 | ||||
-rwxr-xr-x | sbin/env-update.sh | 42 | ||||
-rwxr-xr-x | sbin/functions.sh | 868 | ||||
-rwxr-xr-x | sbin/modules-update | 240 | ||||
-rwxr-xr-x | sbin/rc | 975 | ||||
-rwxr-xr-x | sbin/rc-daemon.sh | 382 | ||||
-rwxr-xr-x | sbin/rc-help.sh | 186 | ||||
-rwxr-xr-x | sbin/rc-services.sh | 883 | ||||
-rwxr-xr-x | sbin/rc-update | 162 | ||||
-rwxr-xr-x | sbin/runscript.sh | 581 |
12 files changed, 6516 insertions, 0 deletions
diff --git a/sbin/MAKEDEV b/sbin/MAKEDEV new file mode 100755 index 0000000..8b720d7 --- /dev/null +++ b/sbin/MAKEDEV @@ -0,0 +1,1894 @@ +#! /bin/sh - + +RCSID='$Id: MAKEDEV 560 2004-09-19 05:39:28Z vapier $' + +#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---# +# Customisation: +# The devices fall into various classes. This section contains the mapping +# from a class name into a group name and permission. +# You will almost certainly need to edit the group name to match your +# system, and you may change the permissions to suit your preference. These +# lines _must_ be of the format "user group perm". + + public=" root root 0666" +private=" root root 0600" + system=" root root 0660" + kmem=" root kmem 0640" + tty=" root tty 0660" # Perms was 0666 + cons=" root tty 0600" + vcs=" root root 0600" +dialout=" root dialout 0660" + dip=" root dip 0660" + mouse=" root root 0660" +printer=" root lp 0660" + floppy=" root floppy 0660" + disk=" root disk 0660" + scsi=" root root 0600" + cdrom=" root cdrom 0660" + tape=" root tape 0660" + audio=" root audio 0660" + video=" root video 0660" + fb=" root video 0620" + ibcs2=" root root 0660" # Perms was 0666 +scanner=" root root 0660" # Perms was 0666 + coda=" root root 0600" + ipsec=" root root 0200" +readable=" root root 0444" + +MAXVT=63 + +# defaults for $major_* +major_ide0=3 +major_ide1=22 +major_sd=8 +major_lp=6 + +# Remark: OSS/Linux becomes major_OSSLinux + +#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---# + +# don't stomp on devfs users +if [ -c .devfsd ] +then + echo ".devfsd presence implies active DevFS. Aborting MAKEDEV invocation." + # use exit 0, not 1, so postinst scripts don't fail on this + exit 0 +fi + + +# make sure we are not in / +if [ "`pwd`" = "/" ]; then + echo "Running MAKEDEV in your root filesystem is a VERY BAD IDEA." + exit 0 +fi + +#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---# + +procfs=/proc + +opt_v= +opt_d= +opt_n= + +while [ $# -ge 1 ] +do + case $1 in + --) shift; break ;; + -v) shift; opt_v=1 ;; + -d) shift; opt_d=1 ;; + -n) shift; opt_n=1; opt_v=1 ;; + -V) shift; opt_V=1 ;; + -*) echo "$0: unknown flag \"$1\"" >&2; exit 1 ;; + *) break ;; + esac +done + +if [ "$opt_V" ] +then + echo "$RCSID" + exit 0 +fi + +opts="${opt_n:+-n} ${opt_v:+-v} ${opt_d:+-d}" + +#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---# + +makedev () { # usage: makedev name [bcu] major minor owner group mode + if [ "$opt_v" ] + then if [ "$opt_d" ] + then echo "delete $1" + else echo "create $1 $2 $3 $4 $5:$6 $7" + fi + fi + if [ ! "$opt_n" ] + then if [ "$opt_d" ] + then + rm -f $1 + else + rm -f $1- + mknod $1- $2 $3 $4 && + chown $5:$6 $1- && + chmod $7 $1- && + mv $1- $1 + fi + fi +} +symlink () { # usage: symlink name target + if [ "$opt_v" ] + then if [ "$opt_d" ] + then echo "delete $1" + else echo "create $1 -> $2" + fi + fi + [ ! "$opt_n" ] && rm -f $1 && + [ ! "$opt_d" ] && ln -s $2 $1 +} + +#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---# + +# Debian allows us to assume /bin/sh is a POSIX compliant shell, so go for it! + +math () { + eval echo "\$(($*))" +} +index () { # index string c + eval "I=\${1%$2*}" + eval echo "\${#I}" +} +suffix () { + eval echo "\${1#$2}" +} +strip () { + eval echo "\${1% $2 *} \${1#* $2 }" +} +first () { + eval echo "\${1:0:1}" +} +second () { + eval echo "\${1:1:1}" +} +substr () { + echo $1 | cut -c $2 +} + +#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---# + +devices= +if [ ! -f $procfs/devices ] +then + echo "$0: warning: can't read $procfs/devices" >&2 +else + exec 3<$procfs/devices + while read major device <&3 + do + device=`echo $device | sed 's#/.*##'` + case "$major" in + Character|Block|'') + ;; + *) + eval "major_${device/-/_}=$major" + devices="$devices $device" + ;; + esac + done + exec 3<&- +fi + +Major () { + device=$2 + if [ "$opt_d" ] + then + echo -1 # don't care + else + eval echo \${major_${1/-/_}:-\${device:?\"unknown major number for $1\"}} + fi +} + +cvt () { + while [ $# -ne 0 ] + do + case "$1" in + mem|tty|ttyp|cua|cub|cui) ;; + hd) (for d in a b c d e f g h ; do + echo -n hd$d " " + done) ; echo + ;; + ide0) echo hda hdb ;; + ide1) echo hdc hdd ;; + ide2) echo hde hdf ;; + ide3) echo hdg hdh ;; + ide4) echo hdi hdj ;; + ide5) echo hdk hdl ;; + sd) echo sda sdb sdc sdd ;; + dasd) (for d in a b c d e f g h i j k l m \ + n o p q r s t u v w x y z ; do + echo -n dasd$d " " + done) ; echo + ;; + raw) echo raw ;; + sg) echo sg ;; + sr) echo scd ;; + st) echo st0 ;; + xd) echo xda xdb ;; + ad) echo ada adb ;; + fd) echo fd0 fd1 ;; + lp) echo lp ;; + mt) echo ftape ;; + qft) echo ftape ;; + loop) echo loop ;; + md) echo md ;; + ibcs2) echo ibcs2 ;; + tpqic02) echo qic ;; + sound) echo audio ;; + logiscan) echo logiscan ;; + ac4096) echo ac4096 ;; + hw) echo helloworld ;; + sbpcd | sbpcd[123]) echo $1 ;; + joystick) echo js ;; + input) echo input ;; + apm_bios) echo apm ;; + dcf) echo dcf ;; + aztcd) echo aztcd ;; + cm206cd) echo cm206cd ;; + gscd) echo gscd ;; + pcmcia) ;; # taken care of by its own driver + ttyC) echo cyclades ;; + isdn) echo isdnmodem isdnbri dcbri ;; + vcs) ;; + pty) echo pty ;; + misc) echo misc ;; + 3dfx) echo 3dfx ;; + agpgart) echo agpgart ;; + microcode) echo microcode ;; + ipmi|ipmikcs) echo ipmi ;; + fb) echo fb ;; + nb) echo nb0 nb1 ;; + netlink) echo netlink ;; + tap) echo netlink ;; + hamradio) echo hamradio ;; + snd) ;; + ptm) ;; + pts) ;; + ttyS) echo ttyS0 ttyS1 ttyS2 ttyS3 ;; + ttyI) echo ttyI0 ttyI1 ttyI2 ttyI3 ;; + ircomm|irlpt) echo irda ;; + ppp) echo ppp ;; + usb) echo usb ;; + lvm) ;; # taken care of by LVM userspace tools + ramdisk) echo ram ;; + *) echo "$0: don't know what \"$1\" is" >&2 ;; + esac + shift + done +} + +for arg +do +# case `cvt $arg` in + case $arg in + generic) + if [ -n "`which dpkg 2> /dev/null`" ] + then + # pick the right generic-<arch> using dpkg's knowledge + case `dpkg --print-installation-architecture` in + alpha) + $0 $opts generic-alpha + ;; + arm) + $0 $opts generic-arm + ;; + hppa) + $0 $opts generic-hppa + ;; + i386) + $0 $opts generic-i386 + ;; + ia64) + $0 $opts generic-ia64 + ;; + m68k) + $0 $opts generic-m68k + ;; + mips) + $0 $opts generic-mips + ;; + mipsel) + $0 $opts generic-mipsel + ;; + powerpc) + $0 $opts generic-powerpc + ;; + s390) + $0 $opts generic-s390 + ;; + sparc) + $0 $opts generic-sparc + ;; + *) + echo "$0: no support for generic on this arch" >&2 + exit 1 + ;; + esac + else + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb + $0 $opts xda xdb + $0 $opts sda sdb + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts lp + $0 $opts par + fi + ;; + generic-alpha) + export MDARCH="alpha" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb hdc hdd + $0 $opts xda xdb + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + ;; + generic-arm) + export MDARCH="arm" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb hdc hdd + $0 $opts xda xdb + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + ;; + generic-hppa) + export MDARCH="hppa" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + $0 $opts rtc + ;; + generic-i386) + export MDARCH="i386" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb hdc hdd + $0 $opts xda xdb + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + $0 $opts isdn-io eda edb sonycd mcd mcdx cdu535 + $0 $opts optcd sjcd cm206cd gscd + $0 $opts lmscd sbpcd aztcd bpcd dac960 ida ataraid cciss + ;; + generic-ia64) + export MDARCH="ia64" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb hdc hdd + $0 $opts xda xdb + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4 ttyS5 + $0 $opts busmice + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + $0 $opts efirtc + ;; + generic-m68k) + export MDARCH="m68k" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb hdc hdd + $0 $opts sda sdb sdc sdd + $0 $opts sg + $0 $opts ada adb adc add ade adf + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS5 + $0 $opts m68k-mice + $0 $opts lp + $0 $opts par + $0 $opts nvram + $0 $opts audio + $0 $opts fb + ;; + generic-mips) + export MDARCH="mips" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + $0 $opts busmice + ;; + generic-mipsel) + export MDARCH="mipsel" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts lp + $0 $opts par + $0 $opts audio + $0 $opts fb + $0 $opts rtc + ;; + generic-powerpc) + export MDARCH="powerpc" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 + $0 $opts hda hdb hdc hdd + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts m68k-mice + $0 $opts input + $0 $opts lp + $0 $opts par + $0 $opts nvram + $0 $opts audio + $0 $opts adb + $0 $opts fb + $0 $opts rtc + $0 $opts isdn-io + ;; + generic-s390) + export MDARCH="s390" + $0 $opts std + $0 $opts fd + $0 $opts dasda dasdb dasdc dasdd dasde dasdf dasdg dasdh \ + dasdi dasdj dasdk dasdl dasdm dasdn dasdo dasdp \ + dasdq dasdr dasds dasdt dasdu dasdv dasdw dasdx \ + dasdy dasdz + $0 $opts pty + $0 $opts consoleonly + $0 $opts rtc + ;; + generic-sparc) + export MDARCH="sparc" + $0 $opts std + $0 $opts fd0-bare fd1-bare + $0 $opts hda hdb hdc hdd + $0 $opts sda sdb sdc sdd + $0 $opts scd0 scd1 + $0 $opts st0 st1 + $0 $opts sg + $0 $opts pty + $0 $opts console + $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 + $0 $opts busmice + $0 $opts fb + $0 $opts rtc + makedev kbd c 11 0 $cons + makedev sunmouse c 10 6 $mouse + symlink mouse sunmouse + makedev openprom c 10 139 $mouse + ;; + local) + $0.local $opts + ;; + std) + makedev mem c 1 1 $kmem + makedev kmem c 1 2 $kmem + makedev null c 1 3 $public + makedev port c 1 4 $kmem + makedev zero c 1 5 $public + symlink core $procfs/kcore + makedev full c 1 7 $public + makedev random c 1 8 $public + makedev urandom c 1 9 $readable + makedev tty c 5 0 $tty + $0 $opts ram + $0 $opts loop + ;; + hamradio) + $0 $opts scc + $0 $opts bc + ;; + scc) + for unit in 0 1 2 3 4 5 6 7 + do + makedev scc$unit c 34 $unit $system + done + ;; + bc) + for unit in 0 1 2 3 + do + makedev bc$unit c 51 $unit $system + done + ;; + random) + makedev random c 1 8 $public + ;; + urandom) + makedev urandom c 1 9 $readable + ;; + ram) + for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do + makedev ram$i b 1 $i $disk + done + symlink ram ram1 + ;; + ram[0-9]|ram1[0-6]) + unit=`suffix $arg ram` + makedev ram$unit b 1 $unit $disk + ;; + initrd) + makedev initrd b 1 250 $disk + ;; + raw) + makedev raw c 162 0 $disk + symlink rawctl raw + for i in 1 2 3 4 5 6 7 8; do + makedev raw$i c 162 $i $disk + done + ;; + consoleonly) + makedev tty0 c 4 0 $cons + # new kernels need a device, old ones a symlink... sigh + kern_rev1=`uname -r | awk -F'.' '{print $1}'` + kern_rev2=`uname -r | awk -F'.' '{print $2}'` + if [ $kern_rev1 -gt 2 ] + then + makedev console c 5 1 $cons + else + if [ $kern_rev1 -eq 2 -a $kern_rev2 -ge 1 ] + then + makedev console c 5 1 $cons + else + symlink console tty0 + fi + fi + ;; + console) + $0 $opts consoleonly + major=`Major vcs 7` # not fatal + [ "$major" ] && makedev vcs0 c $major 0 $vcs + symlink vcs vcs0 + [ "$major" ] && makedev vcsa0 c $major 128 $vcs + symlink vcsa vcsa0 + # individual vts + line=1 + while [ $line -le $MAXVT -a $line -le 63 ] + do + makedev tty$line c 4 $line $tty + [ "$major" ] && makedev vcs$line c $major $line $vcs + [ "$major" ] && makedev vcsa$line c $major `math $line + 128` $vcs + line=`math $line + 1` + done + ;; + adb) + myarch= + + if [ -n "`which dpkg 2> /dev/null`" ] + then + # pick the right arch device using dpkg's knowledge + myarch="`dpkg --print-installation-architecture`" + + elif [ -n "${MDARCH}" ] + then + myarch="${MDARCH}" + fi + + case $myarch in + powerpc) + # ADB bus devices (char) + makedev adb c 56 0 $mouse + makedev adbmouse c 10 10 $mouse + ;; + m68k) + # ACSI disk 2, whole device (block) + makedev adb b 28 16 $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + minor=$(( 16 + $part )) + makedev adb$part b 28 $minor $disk + done + ;; + *) + echo "no support for adb on this arch" >&2 + exit 1 + ;; + esac + ;; + raw1394) + makedev raw1394 c 171 0 $disk + ;; + nvram) + makedev nvram c 10 144 $mouse + ;; + tty[1-9]|tty[1-5][0-9]|tty[6][0-3]) + line=`suffix $arg tty` + makedev tty$line c 4 $line $tty + ;; + ttyS[0-9]|ttyS[1-5][0-9]|ttyS[6][0-3]) + line=`suffix $arg ttyS` + minor=`math 64 + $line` + makedev ttyS$line c 4 $minor $dialout + ;; + pty[a-ep-z]) + bank=`suffix $arg pty` + base=`index pqrstuvwxyzabcde $bank` + base=`math $base \* 16` + for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f + do + j=`index 0123456789abcdef $i` + makedev pty$bank$i c 2 `math $base + $j` $tty + makedev tty$bank$i c 3 `math $base + $j` $tty + done + ;; + pty) + ptysufs="" + for i in p q r s t u v w x y z a b c d e + do + ptysufs="$ptysufs pty$i" + done + $0 $opts $ptysufs ptmx + ;; + ptmx) + # master pty multiplexer for 2.1 kernels + makedev ptmx c 5 2 $tty + ;; + cyclades|ttyC) + major1=`Major ttyC 19` || continue + #major2=`Major cub 20` || continue + for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \ + 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + do + makedev ttyC$i c $major1 $i $dialout + #makedev cub$i c $major2 $i $dialout + done + ;; + stallion|ttyE) + major1=`Major ttyE 24` || continue + #major2=`Major cue 25` || continue + majorc=28 + minor=0 + until [ $minor -gt 256 ] + do + makedev ttyE$minor c $major1 $minor $dialout + #makedev cue$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + for i in 0 1 2 3 + do + makedev staliomem$i c $majorc $i $private + done + ;; + chase|ttyH) + major1=`Major ttyH 17` || continue + #major2=`Major cuh 18` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyH$minor c $major1 $minor $dialout + #makedev cuh$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + rocketport|ttyR) + major1=`Major ttyR 46` || continue + #major2=`Major cur 47` || continue + minor=0 + until [ $minor -gt 64 ] # tell me if 64 is wrong + do + makedev ttyR$minor c $major1 $minor $dialout + #makedev cur$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + ttyV) + major1=`Major ttyV 105` || continue + #major2=`Major cuv 106` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyV$minor c $major1 $minor $dialout + #makedev cuv$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + digi|ttyD) + major1=`Major ttyD 22` || continue + #major2=`Major cud 23` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyD$minor c $major1 $minor $dialout + #makedev cud$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + specialix|ttyX) + major1=`Major ttyX 32` || continue + #major2=`Major cux 33` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyX$minor c $major1 $minor $dialout + #makedev cux$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + specialixIO8|ttyW) + major1=`Major ttyW 75` || continue + #major2=`Major cuw 76` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyW$minor c $major1 $minor $dialout + #makedev cuw$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + PAM|ttyM) + major1=`Major ttyM 79` || continue + #major2=`Major cum 80` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyM$minor c $major1 $minor $dialout + #makedev cum$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + riscom|ttyL) + major=`Major ttyL 48` || continue + minor=0 + until [ $minor -gt 16 ] # tell me if 16 is wrong + do + makedev ttyL$minor c $major $minor $dialout + minor=`math $minor + 1` + done + ;; + computone|ttyF) + major=`Major ttyF 71` || continue + #major2=`Major cuf 72` || continue + minor=0 + until [ $minor -gt 255 ] + do + makedev ttyF$minor c $major $minor $dialout + #makedev cuf$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + major=73 + for i in 0 4 8 12 + do + makedev ip2ipl$i c $major $i $private + makedev ip2stat$i c $major `math $i + 1` $private + done + ;; + ESP|ttyP) + major=`Major ttyP 57` || continue + #major2=`Major cup 58` || continue + minor=0 + until [ $minor -gt 4 ] # tell me if 4 is wrong + do + makedev ttyP$minor c $major $minor $dialout + #makedev cup$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + COMX|comx) + major=`Major comx 88` || continue + minor=0 + until [ $minor -gt 4 ] # tell me if 4 is wrong + do + makedev comx$minor c $major $minor $private + minor=`math $minor + 1` + done + ;; + isdnmodem|ttyI) + major1=`Major ttyI 43` || continue + #major2=`Major cui 44` || continue + minor=0 + until [ $minor -gt 63 ] + do + makedev ttyI$minor c $major1 $minor $dialout + #makedev cui$minor c $major2 $minor $dialout + minor=`math $minor + 1` + done + ;; + isdnbri) + major=45 + minor=0 + until [ $minor -gt 63 ] + do + makedev isdn$minor c $major $minor $dialout + makedev isdnctrl$minor c $major `math $minor + 64` $dialout + makedev ippp$minor c $major `math $minor + 128` $dialout + minor=`math $minor + 1` + done + makedev isdninfo c $major 255 $private + ;; + dcbri) + major=52 + for i in 0 1 2 3 + do + makedev dcbri$i c $major $i $dialout + done + ;; + capi) + major=68 + makedev capi20 c $major 0 $dialout + for i in 0 1 2 3 4 5 6 7 8 9 + do + makedev capi20.0$i c $major `math $i + 1` $dialout + done + for i in 10 11 12 13 14 15 16 17 18 19 + do + makedev capi20.$i c $major `math $i + 1` $dialout + done + ;; + ubd) + major=98 + minor=0 + until [ $minor -gt 255 ] + do + makedev ubd$minor b $major $minor $disk + minor=`math $minor + 1` + done + ;; + fb) + for i in 0 1 2 3 4 5 6 7 + do + makedev fb$i c 29 `math 32 \* $i` $fb + makedev fb${i}current c 29 `math 32 \* $i` $fb + makedev fb${i}autodetect c 29 `math 32 \* $i + 1` $fb + done + ;; + fb[0-7]) + dev=`suffix $arg fb` + base=`math 32 \* $dev` + makedev fb$dev c 29 $base $fb + makedev fb${dev}current c 29 $base $fb + makedev fb${dev}autodetect c 29 `math $base + 1` $fb + for i in 0 1 2 3 4 5 6 7 + do + makedev fb${dev}user$i c 29 `math $base + 24 + $i` $fb + done + ;; + netlink|tap|tap[0-9]|tap1[0-5]) + makedev route c 36 0 $coda + makedev skip c 36 1 $coda + makedev fwmonitor c 36 3 $coda + for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev tap$i c 36 `math $i + 16` $coda + done + ;; + lp) + major=`Major lp 6` || continue + makedev ${arg}0 c $major 0 $printer + makedev ${arg}1 c $major 1 $printer + makedev ${arg}2 c $major 2 $printer + ;; + par) + major=`Major lp 6` || continue + makedev ${arg}0 c $major 0 $printer + makedev ${arg}1 c $major 1 $printer + makedev ${arg}2 c $major 2 $printer + ;; + parport) + major=`Major parport 99` || continue + makedev ${arg}0 c $major 0 $printer + makedev ${arg}1 c $major 1 $printer + makedev ${arg}2 c $major 2 $printer + ;; + slm) + major=`Major slm 28` || continue + for i in 0 1 2 3 + do + makedev slm c $major $i $printer + done + ;; + input) + major=`Major pcsp 13` || continue + mkdir -p input + for i in 0 1 2 3 + do + makedev input/js$i c $major $i $mouse + makedev input/mouse$i c $major `math $i + 32` $mouse + makedev input/event$i c $major `math $i + 64` $mouse + done + makedev input/mice c $major 63 $mouse + ;; + busmice) + major=`Major mouse 10` || continue + makedev logibm c $major 0 $mouse + makedev psaux c $major 1 $mouse + makedev inportbm c $major 2 $mouse + makedev atibm c $major 3 $mouse + makedev jbm c $major 4 $mouse + ;; + m68k-mice) + major=`Major mouse 10` || continue + makedev amigamouse c $major 4 $mouse + makedev atarimouse c $major 5 $mouse + makedev amigamouse1 c $major 7 $mouse + makedev adbmouse c $major 10 $mouse + ;; + 3dfx) + major=`Major $arg 107` || continue + makedev $arg c $major 0 $video + ;; + agpgart) + major=`Major $arg 10` || continue + makedev $arg c $major 175 $video + ;; + intel_rng) + major=`Major $arg 10` || continue + makedev $arg c $major 183 $private + ;; + cpu|microcode) + mkdir -p cpu + makedev cpu/microcode c 10 184 $private + for i in 0 1 2 3 + do + mkdir -p cpu/$i + makedev cpu/$i/msr c 202 $i $private + makedev cpu/$i/cpuid c 203 $i $private + done + ;; + ipmi|ipmikcs) + major=`Major ipmikcs 10` || continue + makedev ipmikcs c $major 173 $private + ;; + irda) + for i in 0 1 + do + makedev ircomm$i c 161 $i $dialout + makedev irlpt$i c 161 `math $i + 16` $printer + done + ;; + misc) + major=`Major mouse 10` || continue + makedev logibm c $major 0 $mouse + makedev psaux c $major 1 $mouse + makedev inportbm c $major 2 $mouse + makedev atibm c $major 3 $mouse + makedev jbm c $major 4 $mouse + makedev amigamouse c $major 4 $mouse + makedev atarimouse c $major 5 $mouse + makedev sunmouse c $major 6 $mouse + makedev amigamouse1 c $major 7 $mouse + makedev smouse c $major 8 $mouse + makedev pc110pad c $major 9 $mouse + makedev adbmouse c $major 10 $mouse + makedev beep c $major 128 $mouse + makedev modreq c $major 129 $mouse + makedev watchdog c $major 130 $mouse + makedev temperature c $major 131 $mouse + makedev hwtrap c $major 132 $mouse + makedev exttrp c $major 133 $mouse + makedev apm_bios c $major 134 $mouse + makedev rtc c $major 135 $mouse + makedev openprom c $major 139 $mouse + makedev relay8 c $major 140 $mouse + makedev relay16 c $major 141 $mouse + makedev msr c $major 142 $mouse + makedev pciconf c $major 143 $mouse + makedev nvram c $major 144 $mouse + makedev hfmodem c $major 145 $mouse + makedev led c $major 151 $mouse + makedev mergemem c $major 153 $mouse + makedev pmu c $major 154 $mouse + ;; + smapi|thinkpad) + major=`Major mouse 10` || continue + makedev smapi c $major 170 $mouse + symlink thinkpad smapi + ;; + rtc) + major=`Major mouse 10` || continue + makedev rtc c $major 135 $mouse + ;; + efirtc) + major=`Major mouse 10` || continue + makedev efirtc c $major 136 $mouse + ;; + js) + major=`Major Joystick 13` || continue + for unit in 0 1 2 3 + do + makedev js$unit c $major $unit $readable + makedev djs$unit c $major `math $unit + 128` $readable + done + ;; + fd[0-7]-bare) + sarg="${arg%-bare}" + major=`Major fd 2` || continue + base=`suffix $sarg fd` + if [ $base -ge 4 ] + then + base=`math $base + 124` + fi + makedev ${sarg} b $major $base $floppy + ;; + fd[0-7]) + major=`Major fd 2` || continue + base=`suffix $arg fd` + if [ $base -ge 4 ] + then + base=`math $base + 124` + fi + makedev ${arg} b $major $base $floppy + makedev ${arg}d360 b $major `math $base + 4` $floppy + makedev ${arg}h1200 b $major `math $base + 8` $floppy + makedev ${arg}u360 b $major `math $base + 12` $floppy + makedev ${arg}u720 b $major `math $base + 16` $floppy + makedev ${arg}h360 b $major `math $base + 20` $floppy + makedev ${arg}h720 b $major `math $base + 24` $floppy + makedev ${arg}u1440 b $major `math $base + 28` $floppy + makedev ${arg}u2880 b $major `math $base + 32` $floppy + makedev ${arg}CompaQ b $major `math $base + 36` $floppy + + makedev ${arg}h1440 b $major `math $base + 40` $floppy + makedev ${arg}u1680 b $major `math $base + 44` $floppy + makedev ${arg}h410 b $major `math $base + 48` $floppy + makedev ${arg}u820 b $major `math $base + 52` $floppy + makedev ${arg}h1476 b $major `math $base + 56` $floppy + makedev ${arg}u1722 b $major `math $base + 60` $floppy + makedev ${arg}h420 b $major `math $base + 64` $floppy + makedev ${arg}u830 b $major `math $base + 68` $floppy + makedev ${arg}h1494 b $major `math $base + 72` $floppy + makedev ${arg}u1743 b $major `math $base + 76` $floppy + makedev ${arg}h880 b $major `math $base + 80` $floppy + makedev ${arg}u1040 b $major `math $base + 84` $floppy + makedev ${arg}u1120 b $major `math $base + 88` $floppy + makedev ${arg}h1600 b $major `math $base + 92` $floppy + makedev ${arg}u1760 b $major `math $base + 96` $floppy + makedev ${arg}u1920 b $major `math $base + 100` $floppy + makedev ${arg}u3200 b $major `math $base + 104` $floppy + makedev ${arg}u3520 b $major `math $base + 108` $floppy + makedev ${arg}u3840 b $major `math $base + 112` $floppy + makedev ${arg}u1840 b $major `math $base + 116` $floppy + makedev ${arg}u800 b $major `math $base + 120` $floppy + makedev ${arg}u1600 b $major `math $base + 124` $floppy + ;; + ed[a-b]) + major=`Major ed 36` || continue + unit=`suffix $arg ed` + base=`index ab $unit` + base=`math $base \* 64` + makedev ed$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev ed$unit$part b $major `math $base + $part` $disk + done + ;; + hd[a-b]) + major=`Major ide0` || major=`Major hd 3` || continue + unit=`suffix $arg hd` + base=`index ab $unit` + base=`math $base \* 64` + makedev hd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev hd$unit$part b $major `math $base + $part` $disk + done + ;; + hd[c-d]) + major=`Major ide1 22` || continue + unit=`suffix $arg hd` + base=`index cd $unit` + base=`math $base \* 64` + makedev hd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev hd$unit$part b $major $(( $base + $part )) $disk + done + ;; + hd[e-f]) + major=`Major ide2 33` || continue + unit=`suffix $arg hd` + base=`index ef $unit` + base=`math $base \* 64` + makedev hd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev hd$unit$part b $major $(( $base + $part )) $disk + done + ;; + hd[g-h]) + major=`Major ide3 34` || continue + unit=`suffix $arg hd` + base=`index gh $unit` + base=`math $base \* 64` + makedev hd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev hd$unit$part b $major $(( $base + $part )) $disk + done + ;; + hd[i-j]) + major=`Major ide4 56` || continue + unit=`suffix $arg hd` + base=`index ij $unit` + base=`math $base \* 64` + makedev hd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev hd$unit$part b $major $(( $base + $part )) $disk + done + ;; + hd[k-l]) + major=`Major ide5 57` || continue + unit=`suffix $arg hd` + base=`index kl $unit` + base=`math $base \* 64` + makedev hd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev hd$unit$part b $major $(( $base + $part )) $disk + done + ;; + ht0) + major=`Major ht0 37` || continue + # Only one IDE tape drive is currently supported; ht0. + makedev ht0 c $major 0 $tape + makedev nht0 c $major 128 $tape + ;; + pt) + major=`Major pt 96` || continue + for i in 0 1 2 3 + do + makedev pt$i c $major $i $tape + makedev npt$i c $major `math $i + 128` $tape + done + ;; + xd[a-d]) + major=`Major xd 13` || continue + unit=`suffix $arg xd` + base=`index abcd $unit` + base=`math $base \* 64` + makedev xd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16 17 18 19 20 + do + makedev xd$unit$part b $major $(( $base + $part )) $disk + done + ;; + sd[a-z]) + major=`Major sd 8` || continue + unit=`suffix $arg sd` + base=`index abcdefghijklmnopqrstuvwxyz $unit` + base=$(( $base * 16 )) + if [ $base -lt 256 ]; then + major=8 + else + major=65 + base=$(( $base - 256 )) + fi + makedev sd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + minor=$(( $base + $part )) + makedev sd$unit$part b $major $minor $disk + done + ;; + sd[a-d][a-z]) + unit=`suffix $arg sd` + unitmaj=`first $unit` + unitmin=`second $unit` + basemaj=`index Xabcd $unitmaj` + basemin=`index abcdefghijklmnopqrstuvwxyz $unitmin` + basemaj=`math $basemaj \* 416` + basemin=`math $basemin \* 16` + base=`math $basemaj + $basemin` + basemaj=`math $base / 256` + base=`math $base % 256` + major=`math basemaj \+ 64` + if [ $major -gt 71 ]; then + echo "$0: don't know how to make device \"$arg\"" >&2 + exit 0 + fi + makedev sd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + minor=$(( $base + $part )) + makedev sd$unit$part b $major $minor $disk + done + ;; + dasd[a-z]) + major=`Major dasd 94` || continue + unit=`suffix $arg dasd` + base=`index abcdefghijklmnopqrstuvwxyz $unit` + base=$(( $base * 4 )) + if [ $base -lt 256 ]; then + major=94 + else + major=65 + base=$(( $base - 256 )) + fi + makedev dasd$unit b $major $base $disk + # Not yet implemented. (Feb. 8, 2001) + # for part in 1 2 3 + for part in 1 + do + minor=$(( $base + $part )) + makedev dasd$unit$part b $major $minor $disk + done + ;; + ad[a-p]) + major=`Major ad 28` || continue + unit=`suffix $arg ad` + base=`index abcdefghijklmnop $unit` + base=`math $base \* 16` + makedev ad$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + minor=$(( $base + $part )) + makedev ad$unit$part b $major $minor $disk + done + ;; + dac960) + for ctr in 0 1 2 3 4 5 6 7 + do + $0 $opts dac960.$ctr + done + ;; + dac960.[0-7]) + [ -d rd ] || { + mkdir rd + chown root:root rd + chmod 755 rd + } + unit=`suffix $arg dac960.` + major=`math 48 + $unit` + minor=0 + for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \ + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + do + makedev rd/c${unit}d${ld} b $major $minor $disk + minor=`math $minor + 1` + for part in 1 2 3 4 5 6 7 + do + makedev rd/c${unit}d${ld}p$part b $major $minor $disk + minor=`math $minor + 1` + done + done + ;; + ataraid) + for ctr in 0 1 2 # 3 4 5 6 7 + do + $0 $opts ataraid.$ctr + done + ;; + ataraid.[0-7]) + [ -d ataraid ] || { + mkdir ataraid + chown root:root ataraid + chmod 755 ataraid + } + unit=`suffix $arg ataraid.` + major=114 + minor=`math $unit \* 16` + makedev ataraid/d${unit} b $major $minor $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + minor=`math $minor + 1` + makedev ataraid/d${unit}p$part b $major $minor $disk + done + ;; + ida) + for ctr in 0 1 2 # 3 4 5 6 7 + do + $0 $opts ida.$ctr + done + ;; + ida.[0-7]) + [ -d ida ] || { + mkdir ida + chown root:root ida + chmod 755 ida + } + unit=`suffix $arg ida.` + major=`math 72 + $unit` + minor=0 + for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev ida/c${unit}d${ld} b $major $minor $disk + minor=`math $minor + 1` + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev ida/c${unit}d${ld}p$part b $major $minor $disk + minor=`math $minor + 1` + done + done + ;; + cciss) + for ctr in 0 1 2 # 3 4 5 6 7 + do + $0 $opts cciss.$ctr + done + ;; + cciss.[0-7]) + [ -d cciss ] || { + mkdir cciss + chown root:root cciss + chmod 755 cciss + } + unit=`suffix $arg cciss.` + major=`math 104 + $unit` + minor=0 + for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev cciss/c${unit}d${ld} b $major $minor $disk + minor=`math $minor + 1` + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev cciss/c${unit}d${ld}p$part b $major $minor $disk + minor=`math $minor + 1` + done + done + ;; + rom) + major=`Major rom 31` + for i in 0 1 2 3 4 5 6 7 + do + makedev rom$i b $major $i $disk + makedev rrom$i b $major `math $i +8` $disk + makedev flash$i b $major `math $i +16` $disk + makedev rflash$i b $major `math $i +24` $disk + done + ;; + nb[0-7]) + major=`Major nbd 43` || continue + minor=`suffix $arg nb` + makedev nb$minor b $major $minor $disk + ;; + loop) + for part in 0 1 2 3 4 5 6 7 + do + makedev loop$part b 7 $part $disk + done + ;; + md) + major=`Major md 9` || continue + for part in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev md$part b $major $part $disk + done + ;; + st[0-7]) + major=`Major st 9` + unit=`suffix $arg st` + makedev st${unit} c $major $unit $tape + makedev nst${unit} c $major `math 128 + $unit` $tape + + makedev st${unit}l c $major `math 32 + $unit` $tape + makedev nst${unit}l c $major `math 160 + $unit` $tape + + makedev st${unit}m c $major `math 64 + $unit` $tape + makedev nst${unit}m c $major `math 192 + $unit` $tape + + makedev st${unit}a c $major `math 96 + $unit` $tape + makedev nst${unit}a c $major `math 224 + $unit` $tape + ;; + qic) + major=`Major tpqic02 12` + makedev ntpqic11 c $major 2 $tape + makedev tpqic11 c $major 3 $tape + makedev ntpqic24 c $major 4 $tape + makedev tpqic24 c $major 5 $tape + makedev ntpqic120 c $major 6 $tape + makedev tpqic120 c $major 7 $tape + makedev ntpqic150 c $major 8 $tape + makedev tpqic150 c $major 9 $tape + makedev rmt8 c $major 6 $tape + makedev rmt16 c $major 8 $tape + makedev tape-d c $major 136 $tape + makedev tape-reset c $major 255 $tape + $0 $opts qft + ;; + ftape) + major=`Major qft 27` || continue + for unit in 0 1 2 3 + do + makedev qft$unit c $major $unit $tape + makedev nqft$unit c $major `math $unit + 4` $tape + makedev zqft$unit c $major `math $unit + 16` $tape + makedev nzqft$unit c $major `math $unit + 20` $tape + makedev rawqft$unit c $major `math $unit + 32` $tape + makedev nrawqft$unit c $major `math $unit + 36` $tape + done + symlink ftape qft0 + symlink nftape nqft0 + ;; + sr|scd|scd-all) + major=`Major sr 11` || continue + for unit in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + do + makedev scd$unit b $major $unit $cdrom + symlink sr$unit scd$unit + done + ;; + pktcdvd) + major=97 + for unit in 0 1 2 3 + do + makedev pktcdvd$unit b $major $unit $cdrom + done + ;; + cfs0) + makedev cfs0 c 67 0 $coda + ;; + scd[0-9]|scd[0-1][0-9]) + major=`Major sr 11` || continue + unit=`suffix $arg scd` + makedev scd$unit b $major $unit $cdrom + ln -f scd$unit sr$unit + ;; + ttyI[0-9]|ttyI[1-5][0-9]|ttyI[6][0-3]) + major=43 + unit=`suffix $arg ttyI` + makedev ttyI$unit c $major $unit $dialout + ;; + ppp) + major=108 + makedev ppp c $major 0 $dip + ;; + ippp[0-9]|ippp[1-5][0-9]|ippp[6][0-3]) + major=45 + unit=`suffix $arg ippp` + minor=`math $unit + 128` + makedev ippp$unit c $major $minor $dialout + ;; + isdn[0-9]|isdn[1-5][0-9]|isdn[6][0-3]) + major=45 + unit=`suffix $arg isdn` + minor=`math $unit + 0` + makedev isdn$unit c $major $minor $dialout + ;; + isdnctrl[0-9]|isdnctrl[1-5][0-9]|isdnctrl[6][0-3]) + major=45 + unit=`suffix $arg isdnctrl` + minor=`math $unit + 64` + makedev isdnctrl$unit c $major $minor $dialout + ;; + isdninfo) + makedev isdninfo c 45 255 $private + ;; + isdn-tty) + major=43 + for unit in 0 1 2 3 4 5 6 7 + do + makedev ttyI$unit c $major $unit $dialout + done + ;; + isdn-ippp) + major=45 + for unit in 0 1 2 3 4 5 6 7 + do + makedev ippp$unit c $major `math $unit + 128` $dialout + done + ;; + isdn-io) + for unit in 0 1 2 3 4 5 6 7 + do + makedev isdn$unit c 45 $unit $dialout + makedev isdnctrl$unit c 45 `math $unit + 64` $dialout + makedev ippp$unit c 45 `math $unit + 128` $dialout + done + makedev isdninfo c 45 255 $dialout + ;; + sonycd) + major=`Major sonycd 15` || continue + makedev $arg b $major 0 $cdrom + ;; + mcd) + major=`Major mcd 23` || continue + makedev $arg b $major 0 $cdrom + ;; + mcdx|mcdx[0-4]) + major=`Major $arg 20` || continue + for unit in 0 1 2 3 4 + do + makedev mcdx$unit b $major $unit $cdrom + done + test -r mcdx || symlink mcdx mcdx0 + ;; + cdu535) + makedev $arg b 24 0 $cdrom + ;; + lmscd) + makedev $arg b 24 0 $cdrom + ;; + sbpcd|sbpcd[123]) + major=`Major $arg 25` || continue + base=`suffix ${arg}0 sbpcd` + for minor in 0 1 2 3 + do + # XXX + unit=$(substr 0123456789abcdef $(( $base * 4 + $minor + 1 )) ) + makedev sbpcd$unit b $major $minor $cdrom + done + [ $arg = sbpcd ] && symlink $arg ${arg}0 + ;; + aztcd) + major=`Major $arg 29` || continue + makedev ${arg}0 b $major 0 $cdrom + ;; + cm206cd) + major=`Major $arg 30` || continue + makedev ${arg}0 b $major 0 $cdrom + ;; + gscd) + major=`Major $arg 16` || continue + makedev ${arg}0 b $major 0 $cdrom + ;; + pcd) + for unit in 0 1 2 3 + do + makedev pcd$unit b 46 $unit $cdrom + done + ;; + bpcd) + makedev $arg b 41 0 $cdrom + ;; + optcd) + makedev $arg b 17 0 $cdrom + ;; + sjcd) + makedev $arg b 18 0 $cdrom + ;; + cfs|coda) + makedev cfs0 c 67 0 $private + ;; + xfs|arla) + makedev xfs0 c 103 0 $private + ;; + logiscan) + major=`Major logiscan` || continue + makedev $arg c $major 0 $scanner + ;; + toshiba) + major=`Major $arg 10` || continue + makedev $arg c $major 181 root root 0666 + ;; + m105scan) + major=`Major m105` || continue + makedev $arg c $major 0 $scanner + ;; + ac4096) + major=`Major ac4096` || continue + makedev $arg c $major 0 $scanner + ;; + audio) + major=`Major sound 14` + makedev mixer c $major 0 $audio + makedev mixer1 c $major 16 $audio + makedev mixer2 c $major 32 $audio + makedev mixer3 c $major 48 $audio + makedev sequencer c $major 1 $audio + makedev midi00 c $major 2 $audio + makedev midi01 c $major 18 $audio + makedev midi02 c $major 34 $audio + makedev midi03 c $major 50 $audio + makedev dsp c $major 3 $audio + makedev dsp1 c $major 19 $audio + makedev dsp2 c $major 35 $audio + makedev dsp3 c $major 51 $audio + makedev audio c $major 4 $audio + makedev audio1 c $major 20 $audio + makedev audio2 c $major 36 $audio + makedev audio3 c $major 52 $audio + makedev sndstat c $major 6 $audio + makedev audioctl c $major 7 $audio + major=31 + makedev mpu401data c $major 0 $audio + makedev mpu401stat c $major 1 $audio + major=35 + for i in 0 1 2 3 + do + makedev midi$i c $major $i $audio + makedev rmidi$i c $major `math $i + 64` $audio + makedev smpte$i c $major `math $i + 128` $audio + done + ;; + pcaudio) + major=`Major pcsp 13` || continue + makedev pcmixer c $major 0 $audio + makedev pcsp c $major 3 $audio + makedev pcaudio c $major 4 $audio + ;; + video|video4linux|v4l|radio) + # video4linux api includes radio, teletext, etc. + major=`Major video 81` || continue + minor=0 + until [ $minor -gt 63 ] + do + makedev video$minor c $major $minor $video + makedev radio$minor c $major `math $minor + 64` $video + minor=`math $minor + 1` + done + symlink radio radio0 + minor=0 + until [ $minor -gt 31 ] + do + makedev vtx$minor c $major `math $minor + 192` $video + makedev vbi$minor c $major `math $minor + 224` $video + minor=`math $minor + 1` + done + symlink video video0 + symlink vbi vbi0 + major=82 + minor=0 + until [ $minor -gt 1 ] + do + makedev winradio$minor c $major $minor $video + minor=`math $minor + 1` + done + major=83 + makedev vtx c $major 0 $video + makedev vttuner c $major 16 $video + ;; + i2c) + # making it possible to create an arbitrary number of i2c + # devices might be good, but 8 should suffice for now + major=`Major i2c 89` || continue + minor=0 + until [ $minor -gt 7 ] + do + makedev i2c-$minor c $major $minor $private + minor=`math $minor + 1` + done + ;; + tlk) + major=102 + minor=0 + until [ $minor -gt 3 ] # tell me if 3 is wrong... + do + makedev tlk$minor c $major $minor $video + minor=`math $minor + 1` + done + ;; + srnd) + makedev srnd0 c 110 0 $video + makedev srnd1 c 110 1 $video + ;; + fgrab) + makedev mmetfgrab c 40 0 $video + makedev wvisfgrab c 26 0 $video + for i in 0 1 # more? + do + makedev iscc$i c 93 $i $video + makedev isccctl$i c 93 `math $i + 128` $video + done + for i in 0 1 # more? + do + makedev dcxx$i c 94 $i $video + done + ;; + sg|sg-all) + major=`Major sg 21` + for unit in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + do + makedev sg$unit c $major $unit $scsi + done + ;; + pg) + major=`Major pg 97` + for unit in 0 1 2 3 + do + makedev pg$unit c $major $unit $scsi + done + ;; + fd) + # not really devices, we use the /proc filesystem + symlink fd $procfs/self/fd + symlink stdin fd/0 + symlink stdout fd/1 + symlink stderr fd/2 + ;; + ibcs2) + major=`Major ibcs2 30` || continue + makedev socksys c $major 0 $ibcs2 + symlink nfsd socksys + makedev spx c $major 1 $ibcs2 + symlink X0R null + ;; + netlink) + major=36 + makedev route c $major 0 $private + makedev skip c $major 1 $private + ;; + enskip) + major=64 + makedev enskip c $major 0 $private + ;; + ipfilt*) + major=95 + makedev ipl c $major 0 $private + makedev ipnat c $major 1 $private + makedev ipstate c $major 2 $private + makedev ipauth c $major 3 $private + ;; + qng) + makedev qng c 77 0 $private + ;; + apm) + major=`Major mouse 10` || continue + makedev apm_bios c $major 134 $mouse + ;; + dcf) + major=`Major dcf` || continue + makedev $arg c $major 0 $system + ;; + helloworld) + major=`Major hw` || continue + makedev helloworld c $major 0 $public + ;; + ipsec) + # For the Free S/WAN (http://www.xs4all.nl/~freeswan/) + # implementation of IPSEC + makedev ipsec c 36 10 $ipsec + ;; + comedi) + major=98 + for minor in 0 1 2 3 + do + makedev comedi$minor c $major $minor $public + done + ;; + usb) + mkdir -p usb + major=180 + for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev usb/lp$i c $major $i $printer + makedev usb/mouse$i c $major `math $i + 16` $mouse + makedev usb/ez$i c $major `math $i + 32` $system + makedev usb/scanner$i c $major `math $i + 48` $scanner + makedev ttyACM$i c 166 $i $dialout + makedev ttyUSB$i c 188 $i $dialout + done + makedev usb/rio500 c $major 64 $audio + ;; + paride) + major=45 + for unit in a b c d + do + base=`index abcd $unit` + base=`math $base \* 16` + makedev pd$unit b $major $base $disk + for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev pd$unit$part b $major $(( $base + $part )) $disk + done + done + for i in 0 1 2 3 + do + makedev pcd$i b 46 $i $cdrom + makedev pf$i b 47 $i $floppy + done + ;; + update) + if [ ! "$devices" ] + then + echo "$0: don't appear to have any devices" >&2 + continue + fi + if [ "$opt_d" ] + then + echo "$0: can't delete an update" >&2 + continue + fi + create= + delete= + devs="$devices" + if [ -f DEVICES ] + then + exec 3<DEVICES + while read device major <&3 + do + eval now=\$major_${device/-/_} + if [ "$now" = "" ] + then + delete="$delete `cvt $device`" + continue + elif [ "$now" != $major ] + then + create="$create "`cvt $device` + fi + devs=`strip " $devs " $device` + done + exec 3<&- + fi + create="$create "`cvt $devs` + [ "$delete" != "" ] && $0 $opts -d $delete + [ "$create" != " " ] && $0 $opts $create + [ "$opt_n" ] && continue + for device in $devices + do + if [ "`cvt $device`" ] + then + eval echo $device \$major_${device/-/_} + fi + done > DEVICES + ;; + *) + echo "$0: don't know how to make device \"$arg\"" >&2 + exit 1 + ;; + esac +done + +exit 0 diff --git a/sbin/MAKEDEV-gentoo.patch b/sbin/MAKEDEV-gentoo.patch new file mode 100755 index 0000000..14e5edf --- /dev/null +++ b/sbin/MAKEDEV-gentoo.patch @@ -0,0 +1,210 @@ +--- MAKEDEV.orig 2003-03-09 08:12:11.000000000 +0200 ++++ MAKEDEV 2003-03-09 08:26:25.000000000 +0200 +@@ -260,48 +260,65 @@ + # case `cvt $arg` in + case $arg in + generic) +- # pick the right generic-<arch> using dpkg's knowledge +- case `dpkg --print-installation-architecture` in +- alpha) +- $0 $opts generic-alpha +- ;; +- arm) +- $0 $opts generic-arm +- ;; +- hppa) +- $0 $opts generic-hppa +- ;; +- i386) +- $0 $opts generic-i386 +- ;; +- ia64) +- $0 $opts generic-ia64 +- ;; +- m68k) +- $0 $opts generic-m68k +- ;; +- mips) +- $0 $opts generic-mips +- ;; +- mipsel) +- $0 $opts generic-mipsel +- ;; +- powerpc) +- $0 $opts generic-powerpc +- ;; +- s390) +- $0 $opts generic-s390 +- ;; +- sparc) +- $0 $opts generic-sparc +- ;; +- *) +- echo "$0: no support for generic on this arch" >&2 +- exit 1 +- ;; +- esac ++ if [ -n "`which dpkg 2> /dev/null`" ] ++ then ++ # pick the right generic-<arch> using dpkg's knowledge ++ case `dpkg --print-installation-architecture` in ++ alpha) ++ $0 $opts generic-alpha ++ ;; ++ arm) ++ $0 $opts generic-arm ++ ;; ++ hppa) ++ $0 $opts generic-hppa ++ ;; ++ i386) ++ $0 $opts generic-i386 ++ ;; ++ ia64) ++ $0 $opts generic-ia64 ++ ;; ++ m68k) ++ $0 $opts generic-m68k ++ ;; ++ mips) ++ $0 $opts generic-mips ++ ;; ++ mipsel) ++ $0 $opts generic-mipsel ++ ;; ++ powerpc) ++ $0 $opts generic-powerpc ++ ;; ++ s390) ++ $0 $opts generic-s390 ++ ;; ++ sparc) ++ $0 $opts generic-sparc ++ ;; ++ *) ++ echo "$0: no support for generic on this arch" >&2 ++ exit 1 ++ ;; ++ esac ++ else ++ $0 $opts std ++ $0 $opts fd ++ $0 $opts fd0 fd1 ++ $0 $opts hda hdb ++ $0 $opts xda xdb ++ $0 $opts sda sdb ++ $0 $opts pty ++ $0 $opts console ++ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ++ $0 $opts busmice ++ $0 $opts lp ++ $0 $opts par ++ fi + ;; + generic-alpha) ++ export MDARCH="alpha" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -321,6 +338,7 @@ + $0 $opts fb + ;; + generic-arm) ++ export MDARCH="arm" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -340,6 +358,7 @@ + $0 $opts fb + ;; + generic-hppa) ++ export MDARCH="hppa" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -358,6 +377,7 @@ + $0 $opts rtc + ;; + generic-i386) ++ export MDARCH="i386" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -380,6 +400,7 @@ + $0 $opts lmscd sbpcd aztcd bpcd dac960 ida ataraid cciss + ;; + generic-ia64) ++ export MDARCH="ia64" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -400,6 +421,7 @@ + $0 $opts efirtc + ;; + generic-m68k) ++ export MDARCH="m68k" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -418,6 +440,7 @@ + $0 $opts fb + ;; + generic-mips) ++ export MDARCH="mips" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -436,6 +459,7 @@ + $0 $opts busmice + ;; + generic-mipsel) ++ export MDARCH="mipsel" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -454,6 +478,7 @@ + $0 $opts rtc + ;; + generic-powerpc) ++ export MDARCH="powerpc" + $0 $opts std + $0 $opts fd + $0 $opts fd0 fd1 +@@ -478,6 +503,7 @@ + $0 $opts isdn-io + ;; + generic-s390) ++ export MDARCH="s390" + $0 $opts std + $0 $opts fd + $0 $opts dasda dasdb dasdc dasdd dasde dasdf dasdg dasdh \ +@@ -489,6 +515,7 @@ + $0 $opts rtc + ;; + generic-sparc) ++ export MDARCH="sparc" + $0 $opts std + $0 $opts fd0-bare fd1-bare + $0 $opts hda hdb hdc hdd +@@ -601,8 +628,19 @@ + done + ;; + adb) +- # pick the right arch device using dpkg's knowledge +- case `dpkg --print-installation-architecture` in ++ myarch= ++ ++ if [ -n "`which dpkg 2> /dev/null`" ] ++ then ++ # pick the right arch device using dpkg's knowledge ++ myarch="`dpkg --print-installation-architecture`" ++ ++ elif [ -n "${MDARCH}" ] ++ then ++ myarch="${MDARCH}" ++ fi ++ ++ case $myarch in + powerpc) + # ADB bus devices (char) + makedev adb c 56 0 $mouse diff --git a/sbin/depscan.sh b/sbin/depscan.sh new file mode 100755 index 0000000..1fbf0ef --- /dev/null +++ b/sbin/depscan.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +source /sbin/functions.sh + +if [[ $1 == "--debug" ]] ; then + shift + set -x +fi + +if [[ ! -d ${svcdir} ]]; then + if ! mkdir -p -m 0755 "${svcdir}" 2>/dev/null ; then + eerror "Could not create needed directory '${svcdir}'!" + fi +fi + +for x in softscripts snapshot options daemons \ + started starting inactive stopping failed \ + exclusive exitcodes ; do + if [[ ! -d "${svcdir}/${x}" ]] ; then + if ! mkdir -p -m 0755 "${svcdir}/${x}" 2>/dev/null ; then + eerror "Could not create needed directory '${svcdir}/${x}'!" + fi + fi +done + +# Only update if files have actually changed +update=1 + +if [[ $1 == "-u" ]] ; then + update=0 + clock_screw=0 + mtime_test="${svcdir}/mtime-test.$$" + + # If its not there, we have to update, and make sure its present + # for next mtime testing + if [[ ! -e ${svcdir}/depcache ]] ; then + update=1 + touch "${svcdir}/depcache" + fi + + touch "${mtime_test}" + for config in /etc/conf.d /etc/init.d /etc/rc.conf + do + [[ ${update} == 0 ]] && \ + is_older_than "${svcdir}/depcache" "${config}" && update=1 + + is_older_than "${mtime_test}" "${config}" && clock_screw=1 + done + rm -f "${mtime_test}" + + [[ ${clock_screw} == 1 ]] && \ + ewarn "Some file in '/etc/{conf.d,init.d}' have Modification time in the future!" + + shift +fi + +[[ ${update} == 0 ]] && exit 0 + +ebegin "Caching service dependencies" + +# Clean out the non volitile directories ... +rm -rf "${svcdir}"/dep{cache,tree} "${svcdir}"/{broken,snapshot}/* + +retval=0 +SVCDIR="${svcdir}" +DEPTYPES="${deptypes}" +ORDTYPES="${ordtypes}" + +export SVCDIR DEPTYPES ORDTYPES + +cd /etc/init.d + +/bin/gawk \ + -f /lib/rcscripts/awk/functions.awk \ + -f /lib/rcscripts/awk/cachedepends.awk || \ + retval=1 + +bash "${svcdir}/depcache" | \ +/bin/gawk \ + -f /lib/rcscripts/awk/functions.awk \ + -f /lib/rcscripts/awk/gendepends.awk || \ + retval=1 + +touch "${svcdir}"/dep{cache,tree} +chmod 0644 "${svcdir}"/dep{cache,tree} + +eend ${retval} "Failed to cache service dependencies" + +exit ${retval} + +# vim:ts=4 diff --git a/sbin/env-update.sh b/sbin/env-update.sh new file mode 100755 index 0000000..533e989 --- /dev/null +++ b/sbin/env-update.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +source /sbin/functions.sh || exit 1 + +if [ "${EUID}" -ne 0 ] +then + eerror "$0: must be root." + exit 1 +fi + +usage() { +echo "usage: env-update.sh + +note: + This utility generates /etc/profile.env and /etc/csh.env + from the contents of /etc/env.d/ +" + exit 1 +} + +export SVCDIR="${svcdir}" + +# Only update if files have actually changed +if [ "$1" == "-u" ] +then + is_older_than "${svcdir}/envcache" /etc/env.d && exit 0 + shift +fi + +if [ "$#" -ne 0 ] +then + usage +else + /bin/gawk \ + -f /lib/rcscripts/awk/functions.awk \ + -f /lib/rcscripts/awk/genenviron.awk +fi + + +# vim:ts=4 diff --git a/sbin/functions.sh b/sbin/functions.sh new file mode 100755 index 0000000..a210c4f --- /dev/null +++ b/sbin/functions.sh @@ -0,0 +1,868 @@ +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +RC_GOT_FUNCTIONS="yes" + +# daemontools dir +SVCDIR="/var/lib/supervise" + +# Check /etc/conf.d/rc for a description of these ... +svcdir="/var/lib/init.d" +svclib="/lib/rcscripts" +svcmount="no" +svcfstype="tmpfs" +svcsize=1024 + +# Different types of dependencies +deptypes="need use" +# Different types of order deps +ordtypes="before after" + +# +# Internal variables +# + +# Dont output to stdout? +RC_QUIET_STDOUT="no" +RC_VERBOSE=${RC_VERBOSE:-no} + +# Should we use color? +RC_NOCOLOR=${RC_NOCOLOR:-no} +# Can the terminal handle endcols? +RC_ENDCOL="yes" + +# +# Default values for rc system +# +RC_TTY_NUMBER=11 +RC_NET_STRICT_CHECKING="no" +RC_PARALLEL_STARTUP="no" +RC_USE_CONFIG_PROFILE="yes" + +# +# Default values for e-message indentation and dots +# +RC_INDENTATION='' +RC_DEFAULT_INDENT=2 +#RC_DOT_PATTERN=' .' +RC_DOT_PATTERN='' + +# Override defaults with user settings ... +[ -f /etc/conf.d/rc ] && source /etc/conf.d/rc + +# void import_addon(char *addon) +# +# Import code from the specified addon if it exists +# +import_addon() { + local addon=${svclib}/addons/$1 + if [[ -r ${addon} ]] ; then + source "${addon}" + return 0 + fi + return 1 +} + +# void splash(...) +# +# Notify bootsplash/splashutils/gensplash/whatever about +# important events. +# +splash() { + return 0 +} +# This will override the splash() function... +if ! import_addon splash-functions.sh ; then + [ -f /sbin/splash-functions.sh ] && source /sbin/splash-functions.sh +fi + +# void profiling(...) +# +# Notify bootsplash/whatever about important events. +# +profiling() { + return 0 +} +import_addon profiling-functions.sh + +# void bootlog(...) +# +# Notify bootlogger about important events. +bootlog() { + return 0 +} +[[ ${RC_BOOTLOG} == "yes" ]] && import_addon bootlogger.sh + +# void get_bootconfig() +# +# Get the BOOTLEVEL and SOFTLEVEL by setting +# 'bootlevel' and 'softlevel' via kernel +# parameters. +# +get_bootconfig() { + local copt= + local newbootlevel= + local newsoftlevel= + + if [[ -r /proc/cmdline ]] ; then + for copt in $(</proc/cmdline) ; do + case "${copt%=*}" in + bootlevel) + newbootlevel=${copt##*=} + ;; + softlevel) + newsoftlevel=${copt##*=} + ;; + esac + done + fi + + if [[ -n ${newbootlevel} ]] ; then + export BOOTLEVEL=${newbootlevel} + else + export BOOTLEVEL="boot" + fi + + if [[ -n ${newsoftlevel} ]] ; then + export DEFAULTLEVEL=${newsoftlevel} + else + export DEFAULTLEVEL="default" + fi + + return 0 +} + +setup_defaultlevels() { + get_bootconfig + + if get_bootparam "noconfigprofile" ; then + export RC_USE_CONFIG_PROFILE="no" + + elif get_bootparam "configprofile" ; then + export RC_USE_CONFIG_PROFILE="yes" + fi + + if [ "${RC_USE_CONFIG_PROFILE}" = "yes" -a -n "${DEFAULTLEVEL}" ] && \ + [ -d "/etc/runlevels/${BOOTLEVEL}.${DEFAULTLEVEL}" -o \ + -L "/etc/runlevels/${BOOTLEVEL}.${DEFAULTLEVEL}" ] + then + export BOOTLEVEL="${BOOTLEVEL}.${DEFAULTLEVEL}" + fi + + if [ -z "${SOFTLEVEL}" ] ; then + if [ -f "${svcdir}/softlevel" ] ; then + export SOFTLEVEL="$(< ${svcdir}/softlevel)" + else + export SOFTLEVEL="${BOOTLEVEL}" + fi + fi + + return 0 +} + +# void get_libdir(void) +# +# prints the current libdir {lib,lib32,lib64} +# +get_libdir() { + if [ -n "${CONF_LIBDIR_OVERRIDE}" ] ; then + CONF_LIBDIR="${CONF_LIBDIR_OVERRIDE}" + elif [ -x "/usr/bin/portageq" ] ; then + CONF_LIBDIR="$(/usr/bin/portageq envvar CONF_LIBDIR)" + fi + echo ${CONF_LIBDIR:=lib} +} + +# void esyslog(char* priority, char* tag, char* message) +# +# use the system logger to log a message +# +esyslog() { + local pri= + local tag= + + if [ -x /usr/bin/logger ] + then + pri="$1" + tag="$2" + + shift 2 + [[ -z "$*" ]] && return 0 + + /usr/bin/logger -p "${pri}" -t "${tag}" -- "$*" + fi + + return 0 +} + +# void eindent(int num) +# +# increase the indent used for e-commands. +# +eindent() { + local i=$1 + (( i > 0 )) || (( i = RC_DEFAULT_INDENT )) + esetdent $(( ${#RC_INDENTATION} + i )) +} + +# void eoutdent(int num) +# +# decrease the indent used for e-commands. +# +eoutdent() { + local i=$1 + (( i > 0 )) || (( i = RC_DEFAULT_INDENT )) + esetdent $(( ${#RC_INDENTATION} - i )) +} + +# void esetdent(int num) +# +# hard set the indent used for e-commands. +# num defaults to 0 +# +esetdent() { + local i=$1 + (( i < 0 )) && (( i = 0 )) + RC_INDENTATION=$(printf "%${i}s" '') +} + +# void einfo(char* message) +# +# show an informative message (with a newline) +# +einfo() { + einfon "$*\n" + LAST_E_CMD=einfo + return 0 +} + +# void einfon(char* message) +# +# show an informative message (without a newline) +# +einfon() { + [[ ${RC_QUIET_STDOUT} == yes ]] && return 0 + [[ ${RC_ENDCOL} != yes && ${LAST_E_CMD} == ebegin ]] && echo + echo -ne " ${GOOD}*${NORMAL} ${RC_INDENTATION}$*" + LAST_E_CMD=einfon + return 0 +} + +# void ewarn(char* message) +# +# show a warning message + log it +# +ewarn() { + if [[ ${RC_QUIET_STDOUT} == yes ]]; then + echo " $*" + else + [[ ${RC_ENDCOL} != yes && ${LAST_E_CMD} == ebegin ]] && echo + echo -e " ${WARN}*${NORMAL} ${RC_INDENTATION}$*" + fi + + # Log warnings to system log + esyslog "daemon.warning" "rc-scripts" "$*" + + LAST_E_CMD=ewarn + return 0 +} + +# void eerror(char* message) +# +# show an error message + log it +# +eerror() { + if [[ ${RC_QUIET_STDOUT} == yes ]]; then + echo " $*" >/dev/stderr + else + [[ ${RC_ENDCOL} != yes && ${LAST_E_CMD} == ebegin ]] && echo + echo -e " ${BAD}*${NORMAL} ${RC_INDENTATION}$*" + fi + + # Log errors to system log + esyslog "daemon.err" "rc-scripts" "$*" + + LAST_E_CMD=eerror + return 0 +} + +# void ebegin(char* message) +# +# show a message indicating the start of a process +# +ebegin() { + local msg="$*" dots spaces=${RC_DOT_PATTERN//?/ } + [[ ${RC_QUIET_STDOUT} == yes ]] && return 0 + + if [[ -n ${RC_DOT_PATTERN} ]]; then + dots=$(printf "%$(( COLS - 3 - ${#RC_INDENTATION} - ${#msg} - 7 ))s" '') + dots=${dots//${spaces}/${RC_DOT_PATTERN}} + msg="${msg}${dots}" + else + msg="${msg} ..." + fi + einfon "${msg}" + [[ ${RC_ENDCOL} == yes ]] && echo + + LAST_E_LEN=$(( 3 + ${#RC_INDENTATION} + ${#msg} )) + LAST_E_CMD=ebegin + return 0 +} + +# void _eend(int error, char *efunc, char* errstr) +# +# indicate the completion of process, called from eend/ewend +# if error, show errstr via efunc +# +# This function is private to functions.sh. Do not call it from a +# script. +# +_eend() { + local retval=${1:-0} efunc=${2:-eerror} msg + shift 2 + + if [[ ${retval} == 0 ]]; then + [[ ${RC_QUIET_STDOUT} == yes ]] && return 0 + msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}" + else + if [[ -c /dev/null ]]; then + rc_splash "stop" &>/dev/null & + else + rc_splash "stop" & + fi + if [[ -n "$*" ]]; then + ${efunc} "$*" + fi + msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}" + fi + + if [[ ${RC_ENDCOL} == yes ]]; then + echo -e "${ENDCOL} ${msg}" + else + [[ ${LAST_E_CMD} == ebegin ]] || LAST_E_LEN=0 + printf "%$(( COLS - LAST_E_LEN - 6 ))s%b\n" '' "${msg}" + fi + + return ${retval} +} + +# void eend(int error, char* errstr) +# +# indicate the completion of process +# if error, show errstr via eerror +# +eend() { + local retval=${1:-0} + shift + + _eend ${retval} eerror "$*" + + LAST_E_CMD=eend + return $retval +} + +# void ewend(int error, char* errstr) +# +# indicate the completion of process +# if error, show errstr via ewarn +# +ewend() { + local retval=${1:-0} + shift + + _eend ${retval} ewarn "$*" + + LAST_E_CMD=ewend + return $retval +} + +# v-e-commands honor RC_VERBOSE which defaults to no. +# The condition is negated so the return value will be zero. +veinfo() { [[ "${RC_VERBOSE}" != yes ]] || einfo "$@"; } +veinfon() { [[ "${RC_VERBOSE}" != yes ]] || einfon "$@"; } +vewarn() { [[ "${RC_VERBOSE}" != yes ]] || ewarn "$@"; } +veerror() { [[ "${RC_VERBOSE}" != yes ]] || eerror "$@"; } +vebegin() { [[ "${RC_VERBOSE}" != yes ]] || ebegin "$@"; } +veend() { + [[ "${RC_VERBOSE}" == yes ]] && { eend "$@"; return $?; } + return ${1:-0} +} +veend() { + [[ "${RC_VERBOSE}" == yes ]] && { ewend "$@"; return $?; } + return ${1:-0} +} + +# char *KV_major(string) +# +# Return the Major (X of X.Y.Z) kernel version +# +KV_major() { + [[ -z $1 ]] && return 1 + + local KV=$@ + echo ${KV%%.*} +} + +# char *KV_minor(string) +# +# Return the Minor (Y of X.Y.Z) kernel version +# +KV_minor() { + [[ -z $1 ]] && return 1 + + local KV=$@ + KV=${KV#*.} + echo ${KV%%.*} +} + +# char *KV_micro(string) +# +# Return the Micro (Z of X.Y.Z) kernel version. +# +KV_micro() { + [[ -z $1 ]] && return 1 + + local KV=$@ + KV=${KV#*.*.} + echo ${KV%%[^[:digit:]]*} +} + +# int KV_to_int(string) +# +# Convert a string type kernel version (2.4.0) to an int (132096) +# for easy compairing or versions ... +# +KV_to_int() { + [[ -z $1 ]] && return 1 + + local KV_MAJOR=$(KV_major "$1") + local KV_MINOR=$(KV_minor "$1") + local KV_MICRO=$(KV_micro "$1") + local KV_int=$(( KV_MAJOR * 65536 + KV_MINOR * 256 + KV_MICRO )) + + # We make version 2.2.0 the minimum version we will handle as + # a sanity check ... if its less, we fail ... + if [[ ${KV_int} -ge 131584 ]] ; then + echo "${KV_int}" + return 0 + fi + + return 1 +} + +# int get_KV() +# +# Return the kernel version (major, minor and micro concated) as an integer. +# Assumes X and Y of X.Y.Z are numbers. Also assumes that some leading +# portion of Z is a number. +# e.g. 2.4.25, 2.6.10, 2.6.4-rc3, 2.2.40-poop, 2.0.15+foo +# +get_KV() { + local KV=$(uname -r) + + echo $(KV_to_int "${KV}") + + return $? +} + +# bool get_bootparam(param) +# +# return 0 if gentoo=param was passed to the kernel +# +# EXAMPLE: if get_bootparam "nodevfs" ; then .... +# +get_bootparam() { + local x copt params retval=1 + + [ ! -r "/proc/cmdline" ] && return 1 + + for copt in $(< /proc/cmdline) + do + if [ "${copt%=*}" = "gentoo" ] + then + params="$(gawk -v PARAMS="${copt##*=}" ' + BEGIN { + split(PARAMS, nodes, ",") + for (x in nodes) + print nodes[x] + }')" + + # Parse gentoo option + for x in ${params} + do + if [ "${x}" = "$1" ] + then +# echo "YES" + retval=0 + fi + done + fi + done + + return ${retval} +} + +# Safer way to list the contents of a directory, +# as it do not have the "empty dir bug". +# +# char *dolisting(param) +# +# print a list of the directory contents +# +# NOTE: quote the params if they contain globs. +# also, error checking is not that extensive ... +# +dolisting() { + local x= + local y= + local tmpstr= + local mylist= + local mypath="$*" + + if [ "${mypath%/\*}" != "${mypath}" ] + then + mypath="${mypath%/\*}" + fi + + for x in ${mypath} + do + [ ! -e "${x}" ] && continue + + if [ ! -d "${x}" ] && ( [ -L "${x}" -o -f "${x}" ] ) + then + mylist="${mylist} $(ls "${x}" 2> /dev/null)" + else + [ "${x%/}" != "${x}" ] && x="${x%/}" + + cd "${x}"; tmpstr="$(ls)" + + for y in ${tmpstr} + do + mylist="${mylist} ${x}/${y}" + done + fi + done + + echo "${mylist}" +} + +# void save_options(char *option, char *optstring) +# +# save the settings ("optstring") for "option" +# +save_options() { + local myopts="$1" + + shift + if [ ! -d "${svcdir}/options/${myservice}" ] + then + mkdir -p -m 0755 "${svcdir}/options/${myservice}" + fi + + echo "$*" > "${svcdir}/options/${myservice}/${myopts}" + + return 0 +} + +# char *get_options(char *option) +# +# get the "optstring" for "option" that was saved +# by calling the save_options function +# +get_options() { + if [ -f "${svcdir}/options/${myservice}/$1" ] + then + echo "$(< ${svcdir}/options/${myservice}/$1)" + fi + + return 0 +} + +# char *add_suffix(char * configfile) +# +# Returns a config file name with the softlevel suffix +# appended to it. For use with multi-config services. +add_suffix() { + if [ "${RC_USE_CONFIG_PROFILE}" = "yes" -a -e "$1.${DEFAULTLEVEL}" ] + then + echo "$1.${DEFAULTLEVEL}" + else + echo "$1" + fi + + return 0 +} + +# char *get_base_ver() +# +# get the version of baselayout that this system is running +# +get_base_ver() { + [[ ! -r /etc/gentoo-release ]] && return 0 + local ver=$(</etc/gentoo-release) + echo ${ver##* } +} + +# Network filesystems list for common use in rc-scripts. +# This variable is used in is_net_fs and other places such as +# localmount. +NET_FS_LIST="afs cifs coda davfs gfs ncpfs nfs nfs4 ocfs2 shfs smbfs" + +# bool is_net_fs(path) +# +# return 0 if path is the mountpoint of a networked filesystem +# +# EXAMPLE: if is_net_fs / ; then ... +# +is_net_fs() { + local fstype + # /proc/mounts is always accurate but may not always be available + if [[ -e /proc/mounts ]]; then + fstype=$( sed -n -e '/^rootfs/!s:.* '"$1"' \([^ ]*\).*:\1:p' /proc/mounts ) + else + fstype=$( mount | sed -n -e 's:.* on '"$1"' type \([^ ]*\).*:\1:p' ) + fi + [[ " ${NET_FS_LIST} " == *" ${fstype} "* ]] + return $? +} + +# bool is_uml_sys() +# +# return 0 if the currently running system is User Mode Linux +# +# EXAMPLE: if is_uml_sys ; then ... +# +is_uml_sys() { + grep -qs 'UML' /proc/cpuinfo + return $? +} + +# bool is_vserver_sys() +# +# return 0 if the currently running system is a Linux VServer +# +# EXAMPLE: if is_vserver_sys ; then ... +# +is_vserver_sys() { + grep -qs '^s_context:[[:space:]]*[1-9]' /proc/self/status + return $? +} + +# bool is_xenU_sys() +# +# return 0 if the currently running system is an unprivileged Xen domain +# +# EXAMPLE: if is_xenU_sys ; then ... +# +is_xenU_sys() { + [[ -d /proc/xen && ! -f /proc/xen/privcmd ]] +} + +# bool get_mount_fstab(path) +# +# return the parameters to pass to the mount command generated from fstab +# +# EXAMPLE: cmd=$( get_mount_fstab /proc ) +# cmd=${cmd:--t proc none /proc} +# mount -n ${cmd} +# +get_mount_fstab() { + awk '$1 ~ "^#" { next } + $2 == "'$*'" { stab="-t "$3" -o "$4" "$1" "$2; } + END { print stab; } + ' /etc/fstab +} + +# char *reverse_list(list) +# +# Returns the reversed order of list +# +reverse_list() { + for (( i = $# ; i > 0 ; --i )); do + echo -n "${!i} " + done +} + +# void start_addon(addon) +# +# Starts addon. +# +start_addon() { + local addon=$1 + (import_addon ${addon}-start.sh) + return 0 +} + +# void start_volumes() +# +# Starts all volumes in RC_VOLUME_ORDER. +# +start_volumes() { + local x= + + for x in ${RC_VOLUME_ORDER}; do + start_addon "${x}" + done + + return 0 +} + +# void stop_addon(addon) +# +# Stops addon. +# +stop_addon() { + local addon=$1 + (import_addon ${addon}-stop.sh) + return 0 +} + +# void stop_volumes() +# +# Stops all volumes in RC_VOLUME_ORDER (reverse order). +# +stop_volumes() { + local x= + + for x in $(reverse_list ${RC_VOLUME_ORDER}); do + stop_addon "${x}" + done + + return 0 +} + +# bool is_older_than(reference, files/dirs to check) +# +# return 0 if any of the files/dirs are newer than +# the reference file +# +# EXAMPLE: if is_older_than a.out *.o ; then ... +is_older_than() { + local x= + local ref="$1" + shift + + for x in "$@" ; do + [[ ${x} -nt ${ref} ]] && return 0 + + if [[ -d ${x} ]] ; then + is_older_than "${ref}" "${x}"/* && return 0 + fi + done + + return 1 +} + +# char* bash_variable(char *variable) +# +# Turns the given variable into something that bash can use +# Basically replaces anything not a-z,A-Z into a _ +# +bash_variable() { + local args="$@" + LC_ALL=C echo "${args//[![:word:]]/_}" +} + +# void requote() +# +# Requotes params so they're suitable to be eval'd, just like this would: +# set -- 1 2 "3 4" +# /usr/bin/getopt -- '' "$@" | sed 's/^ -- //' +# +requote() { + local q=\' + set -- "${@//\'/$q\'$q}" # quote inner instances of ' + set -- "${@/#/$q}" # add ' to start of each param + set -- "${@/%/$q}" # add ' to end of each param + echo "$*" +} + +############################################################################## +# # +# This should be the last code in here, please add all functions above!! # +# # +# *** START LAST CODE *** # +# # +############################################################################## + +if [ -z "${EBUILD}" ] ; then + # Setup a basic $PATH. Just add system default to existing. + # This should solve both /sbin and /usr/sbin not present when + # doing 'su -c foo', or for something like: PATH= rcscript start + PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:${PATH}" + + # Cache the CONSOLETYPE - this is important as backgrounded shells don't + # have a TTY. rc unsets it at the end of running so it shouldn't hang + # around + if [[ -z ${CONSOLETYPE} ]]; then + export CONSOLETYPE=$( /sbin/consoletype 2>/dev/null ) + fi + if [[ ${CONSOLETYPE} == "serial" ]] ; then + RC_NOCOLOR="yes" + RC_ENDCOL="no" + fi + + for arg in "$@" ; do + case "${arg}" in + # Lastly check if the user disabled it with --nocolor argument + --nocolor|-nc) + RC_NOCOLOR="yes" + ;; + esac + done + + if [ -r "/proc/cmdline" ] ; then + setup_defaultlevels + fi +else + # Should we use colors ? + if [[ $* != *depend* ]]; then + # Check user pref in portage + RC_NOCOLOR="$(portageq envvar NOCOLOR 2>/dev/null)" + [ "${RC_NOCOLOR}" = "true" ] && RC_NOCOLOR="yes" + else + # We do not want colors during emerge depend + RC_NOCOLOR="yes" + # No output is seen during emerge depend, so this is not needed. + RC_ENDCOL="no" + fi +fi + +if [[ -n ${EBUILD} && $* = *depend* ]]; then + # We do not want stty to run during emerge depend + COLS=80 +else + # Setup COLS and ENDCOL so eend can line up the [ ok ] + COLS=${COLUMNS:-0} # bash's internal COLUMNS variable + (( COLS == 0 )) && COLS=$(stty size 2>/dev/null | cut -d' ' -f2) + (( COLS > 0 )) || (( COLS = 80 )) # width of [ ok ] == 7 +fi + +if [[ ${RC_ENDCOL} == yes ]]; then + ENDCOL=$'\e[A\e['$(( COLS - 8 ))'C' +else + ENDCOL='' +fi + +# Setup the colors so our messages all look pretty +if [[ ${RC_NOCOLOR} == yes ]]; then + unset GOOD WARN BAD NORMAL HILITE BRACKET +else + GOOD=$'\e[32;01m' + WARN=$'\e[33;01m' + BAD=$'\e[31;01m' + NORMAL=$'\e[0m' + HILITE=$'\e[36;01m' + BRACKET=$'\e[34;01m' +fi + +############################################################################## +# # +# *** END LAST CODE *** # +# # +# This should be the last code in here, please add all functions above!! # +# # +############################################################################## + + +# vim:ts=4 diff --git a/sbin/modules-update b/sbin/modules-update new file mode 100755 index 0000000..77c25be --- /dev/null +++ b/sbin/modules-update @@ -0,0 +1,240 @@ +#!/bin/bash +# +# This is the modules-update script for Debian GNU/Linux. +# Written by Wichert Akkerman <wakkerma@debian.org> +# Copyright (C) 1998, 1999 Software in the Public Interest +# +# Modifications by Daniel Robbins <drobbins@gentoo.org>, Gentoo Foundation +# 02 Sep 2001 -- Removed "arch" stuff since I see no reason to have +# support for varying CPU architectures on a single system. +# +# Updated by Aron Griffis <agriffis@gentoo.org> +# 05 May 2004 -- handle --assume-kernel argument for livecd building + +if [[ 0 -ne $(id -u) ]] ; then + echo "You have to be root to do this." + exit 2 +fi + +CFGFILE="/etc/modules.conf" +TMPFILE="${CFGFILE}.$$" +CFGFILE2="/etc/modprobe.conf" +TMPFILE2="${CFGFILE2}.$$" +TMPFILE2B="${CFGFILE2}B.$$" +CFGFILE3="/etc/modules.devfs" +TMPFILE3="${CFGFILE3}.$$" +CFGFILE4="/etc/modprobe.devfs" +TMPFILE4="${CFGFILE4}.$$" +MODDIR="/etc/modules.d" +ARCHDIR="${MODDIR}/arch" +HEADER="### This file is automatically generated by modules-update" +FULLHEADER="${HEADER} +# +# Please do not edit this file directly. If you want to change or add +# anything please take a look at the files in ${MODDIR} and read +# the manpage for modules-update(8). +# +" + +source /sbin/functions.sh + +# Parse command-line +FORCE=false +ASSUME_KV= +while [[ -n $1 ]] ; do + case "$1" in + force) + FORCE=true ;; + --assume-kernel=*) + ASSUME_KV=${1#*=} ;; + *) + eerror "Error: I don't understand $1" + exit 1 ;; + esac + shift +done + +# Set kernel version, either from --assume-kernel or uname -r +KV=${ASSUME_KV:-$(uname -r)} +if [[ $(KV_to_int ${KV}) -ge $(KV_to_int 2.5.48) ]]; then + KERNEL_2_6=true +else + KERNEL_2_6=false +fi + +# Check if $CONF is valid +[[ ! -r ${CONF} ]] && CONF= + +set -e + +# Reset the sorting order since we depend on it +export LC_COLLATE="C" + +depdir() { + local dep=$(sed -n -e '/[ \t]*depfile=/h;${x;s/[ \t]*depfile=//g;s,/[^/]*$,,p}' \ + "${CFGFILE}") + [[ -z ${dep} ]] && dep="/lib/modules/${KV}" + echo "${dep}" +} + +CFGFILES=${CFGFILE} +if ${KERNEL_2_6} ; then + CFGFILES="${CFGFILES} ${CFGFILE2}" + [[ -d /etc/devfs.d ]] && CFGFILES="${CFGFILES} ${CFGFILE4}" +fi + +for x in ${CFGFILES} ; do + if [[ -f ${x} ]] ; then + if ! sed -ne 1p "${x}" | egrep -q "^${HEADER}" ; then + # Do not bother if its modutils config file, and we + # have a 2.6 kernel without modprobe.old + [[ ${x} == "${CFGFILE}" ]] && ${KERNEL_2_6} && \ + ! type -p modprobe.old > /dev/null && \ + continue + + ewarn "Error: the current ${x} is not automatically generated." + + if $FORCE ; then + ewarn "force specified, (re)generating file anyway." + else + eerror "Use \"modules-update force\" to force (re)generation." + exit 1 + fi + fi + fi +done + +generate_config() { + local cfg= + local conf="$1" + local moddir="$2" + local tmpfile="$3" + local do_mprobe="$4" + + for cfg in "${moddir}"/* "${conf}" ; do + [[ -d ${cfg} ]] && continue + + [[ ! -r ${cfg} ]] && continue + + # Skip backup and RCS files; fixes bug 20597 (07 May 2004 agriffis) + [[ ${cfg} == *~ || ${cfg} == *.bak || ${cfg} == *,v ]] && continue + + [[ ${do_mprobe} -eq 1 && -e "/etc/modprobe.d/${cfg##*/}" ]] && continue + + echo "### modules-update: start processing ${cfg}" >> "${tmpfile}" + + if [[ -x ${cfg} ]] ; then + # $cfg can be executable; nice touch, Wichert! :) + "${cfg}" >> "${tmpfile}" + else + cat "${cfg}" >> "${tmpfile}" + fi + + echo >> "${tmpfile}" + echo "### modules-update: end processing ${cfg}" >> "${tmpfile}" + echo >> "${tmpfile}" + done + + return 0 +} + +if type -p modprobe.old > /dev/null ; then + if ${FORCE} || is_older_than ${CFGFILE} ${MODDIR} || \ + [[ ! -e ${CFGFILE} ]] ; then + ebegin "Updating ${CFGFILE}" + echo "${FULLHEADER}" > "${TMPFILE}" + generate_config "${CONF}" "${MODDIR}" "${TMPFILE}" 0 + [[ -e ${CFGFILE} ]] && mv -f "${CFGFILE}" "${CFGFILE}.old" + mv -f "${TMPFILE}" "${CFGFILE}" + eend 0 + fi +fi + +if ${FORCE} || is_older_than ${CFGFILE2} ${MODDIR} || [[ ! -e ${CFGFILE2} ]]; then + if [[ -x /sbin/generate-modprobe.conf ]] && ${KERNEL_2_6} ; then + # Make sure that generate-modprobe.conf can handle --assume-kernel + # if we were called with it. + if [[ -n ${ASSUME_KV} ]] && \ + ! grep -qe -- --assume-kernel /sbin/generate-modprobe.conf + then + eerror "Error: modules-update called with --assume-kernel flag, but" + eerror "generate-modprobe.conf doesn't understand it. You need to" + eerror "install >=module-init-tools-3.0-r2" + exit 3 + fi + + ebegin "Updating ${CFGFILE2}" + echo "${FULLHEADER/modules.d/modprobe.d}" > "${TMPFILE2}" + if /sbin/generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ + >> "${TMPFILE2}" 2>/dev/null + then + [[ -e ${CFGFILE2} ]] && mv -f "${CFGFILE2}" "${CFGFILE2}.old" + mv -f "${TMPFILE2}" "${CFGFILE2}" + eend 0 + else + # + # If we made it here, it means either generate-modprobe.conf + # bombed on us, or the user doesn't have modutils installed. + # If the latter is true, then we should generate modprobe.conf + # ourselves with any old files laying around in /etc/modules.d. + # + rm -f "${TMPFILE2}" + if type -p modprobe.old > /dev/null ; then + eend 1 "Warning: could not generate ${CFGFILE2}!" + else + echo "${FULLHEADER/modules.d/modprobe.d}" > "${TMPFILE2B}" + generate_config "${CONF}" "${MODDIR}" "${TMPFILE2}" 1 + export TESTING_MODPROBE_CONF="${TMPFILE2}" + if /sbin/generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ + >> "${TMPFILE2B}" 2> /dev/null + then + [[ -e ${CFGFILE2} ]] && mv -f "${CFGFILE2}" "${CFGFILE2}.old" + mv -f "${TMPFILE2B}" "${CFGFILE2}" + eend 0 + else + eend 1 "Warning: could not generate ${CFGFILE2}!" + rm -f "${TMPFILE2B}" + fi + rm -f "${TMPFILE2}" + fi + fi + + if [[ -f ${CFGFILE3} ]] ; then + ebegin "Updating ${CFGFILE4}" + gawk '$0 !~ /^[[:space:]]*include/ { print $0 }' "${CFGFILE3}" \ + > "${TMPFILE3}" + + echo "${FULLHEADER/modules.d/modprobe.d}" > "${TMPFILE4}" + export TESTING_MODPROBE_CONF="${TMPFILE3}" + if /sbin/generate-modprobe.conf ${ASSUME_KV:+--assume-kernel=${KV}} \ + >> "${TMPFILE4}" 2> /dev/null + then + [[ -e ${CFGFILE4} ]] && mv -f "${CFGFILE4}" "${CFGFILE4}.old" + mv -f "${TMPFILE4}" "${CFGFILE4}" + + echo >> "${CFGFILE4}" + echo "include /etc/modprobe.conf" >> "${CFGFILE4}" + eend 0 + else + eend 1 "Warning: could not generate ${CFGFILE4}!" + rm -f "${TMPFILE4}" + fi + rm -f "${TMPFILE3}" + fi + fi +fi + +# We also call depmod here to stop insmod from complaining that modules.conf +# is more recent then modules.dep +if [[ ${CFGFILE2} -nt /lib/modules/${KV}/modules.dep ]] ; then + if [[ -d $(depdir) && -f /proc/modules ]] ; then + if [[ -f /usr/src/linux/System.map ]] ; then + depmod -a -F /usr/src/linux/System.map ${KV} + else + ewarn "System.map not found - unable to check symbols" + fi + fi +fi + + +# vim:ts=4 @@ -0,0 +1,975 @@ +#!/sbin/runscript +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +trap ":" INT QUIT TSTP +source /sbin/functions.sh +# Only source this when this is a livecd booting ... +[ -f /sbin/livecd-functions.sh ] && source /sbin/livecd-functions.sh +umask 022 + +try() { + local errstr + local retval=0 + + if [ -c /dev/null ]; then + errstr="$((eval $*) 2>&1 >/dev/null)" + else + errstr="$((eval $*) 2>&1)" + fi + retval=$? + if [ "${retval}" -ne 0 ] + then + splash "critical" & + + echo -e "${ENDCOL}${NORMAL}[${BAD} oops ${NORMAL}]" + echo + eerror "The \"${1}\" command failed with error:" + echo + echo "${errstr#*: }" + echo + eerror "Since this is a critical task, startup cannot continue." + echo + /sbin/sulogin ${CONSOLE} + einfo "Unmounting filesystems" + if [ -c /dev/null ]; then + /bin/mount -a -o remount,ro &>/dev/null + else + /bin/mount -a -o remount,ro + fi + einfo "Rebooting" + /sbin/reboot -f + fi + + return ${retval} +} + +# Check that $1 exists ... +check_statedir() { + [ -z "$1" ] && return 0 + + if [ ! -d "$1" ] ; then + if ! mkdir -p "$1" &>/dev/null ; then + splash "critical" & + echo + eerror "For Gentoo to function properly, \"$1\" needs to exist." + if [[ ${RC_FORCE_AUTO} == "yes" ]] ; then + eerror "Attempting to create \"$1\" for you ..." + mount -o remount,rw / + mkdir -p "$1" + else + eerror "Please mount your root partition read/write, and execute:" + echo + eerror " # mkdir -p $1" + echo; echo + /sbin/sulogin ${CONSOLE} + fi + einfo "Unmounting filesystems" + /bin/mount -a -o remount,ro &>/dev/null + einfo "Rebooting" + /sbin/reboot -f + fi + fi + + return 0 +} + +udev_version() { + local version=0 + + if [ -x "/sbin/udev" ] + then + version=$(/sbin/udev -V) + # We need it without a leading '0', else bash do the wrong thing + version="${version##0}" + # Older udev's will print nothing + [ -z "${version}" ] && version=0 + fi + + echo "${version}" +} + +# void noblock_read(var) +# +# reads a line of input into var like regular read +# but it does not block waiting for input +# +noblock_read() { + local old_tty_settings="$(stty -g)" + stty -icanon min 0 time 0 + read "$@" + stty "${old_tty_settings}" +} + +# bool user_want_interactive(void) +# +# return 0 if user wants interactive mode +# +user_want_interactive() { + local user_input + noblock_read user_input + [[ ${user_input} == *"I"* || ${user_input} == *"i"* ]] +} + +# void do_interactive +# +# starts, skips, continues or drops to the shell +# depending on user selection +# +do_interactive() { + local service="$1" + shift + + local start_text="Start service" + local skip_text="Skip service" + local continue_text="Continue boot process" + local shell_text="Exit to shell" + + echo + echo "About to start the service ${service}" + PS3="Enter your selection: " + select action in "${start_text}" "${skip_text}" "${continue_text}" \ + "${shell_text}" + do + case ${action} in + "${start_text}") + "$@" + break + ;; + "${skip_text}") + break + ;; + "${continue_text}") + interactive="no" + "$@" + break + ;; + "${shell_text}") + echo + sulogin "${CONSOLE}" + ;; + esac + done +} + +populate_udev() { + # Now populate /dev + /sbin/udevstart + + # Not provided by sysfs but needed + ln -snf /proc/self/fd /dev/fd + ln -snf fd/0 /dev/stdin + ln -snf fd/1 /dev/stdout + ln -snf fd/2 /dev/stderr + [ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core + + # Create nodes that udev can't + [ -x /sbin/dmsetup ] && /sbin/dmsetup mknodes &>/dev/null + [ -x /sbin/lvm ] && /sbin/lvm vgscan -P --mknodes --ignorelockingfailure &>/dev/null + [ -x /sbin/evms_activate ] && /sbin/evms_activate -q &>/dev/null + + # Create problematic directories + mkdir -p /dev/{pts,shm} + + # Same thing as /dev/.devfsd + touch /dev/.udev + + return 0 +} + +get_critical_services() { + local x= + CRITICAL_SERVICES= + + if [ -f "/etc/runlevels/${BOOTLEVEL}/.critical" ] + then + for x in $(< /etc/runlevels/${BOOTLEVEL}/.critical) + do + CRITICAL_SERVICES="${CRITICAL_SERVICES} ${x##*/}" + done + else + CRITICAL_SERVICES="checkroot hostname modules checkfs localmount clock" + fi + + export CRITICAL_SERVICES + + return 0 +} + +# Save $1 +argv1="$1" + +# First time boot stuff goes here. Note that 'sysinit' is an internal runlevel +# used to bring up local filesystems, and should not be started with /sbin/rc +# directly ... +if [[ ( ${RUNLEVEL} == "S" || ${RUNLEVEL} == "1" ) && ${argv1} = "sysinit" ]] +then + # Setup initial $PATH just in case + PATH="/bin:/sbin:/usr/bin:/usr/sbin:${PATH}" + + # Help users recover their systems incase these go missing + [ -c /dev/null ] && dev_null=1 || dev_null=0 + [ -c /dev/console ] && dev_console=1 || dev_console=0 + + echo + echo -e "${GOOD}Gentoo Linux${GENTOO_VERS}; ${BRACKET}http://www.gentoo.org/${NORMAL}" + echo -e " Copyright 1999-2005 Gentoo Foundation; Distributed under the GPLv2" + echo + echo -e "Press ${GOOD}I${NORMAL} to enter interactive boot mode" + echo + check_statedir /proc + + ebegin "Mounting proc at /proc" + if [[ ${RC_USE_FSTAB} = "yes" ]] ; then + mntcmd=$(get_mount_fstab /proc) + else + unset mntcmd + fi + try mount -n ${mntcmd:--t proc proc /proc} + eend $? + + # Read off the kernel commandline to see if there's any special settings + # especially check to see if we need to set the CDBOOT environment variable + # Note: /proc MUST be mounted + [ -f /sbin/livecd-functions.sh ] && livecd_read_commandline + + if [ "$(get_KV)" -ge "$(KV_to_int '2.6.0')" ] ; then + if [[ -d /sys ]] ; then + ebegin "Mounting sysfs at /sys" + if [[ ${RC_USE_FSTAB} = "yes" ]] ; then + mntcmd=$(get_mount_fstab /sys) + else + unset mntcmd + fi + try mount -n ${mntcmd:--t sysfs sysfs /sys} + eend $? + else + ewarn "No /sys to mount sysfs needed in 2.6 and later kernels!" + fi + fi + + check_statedir /dev + + # Fix weird bug where there is a /dev/.devfsd in a unmounted /dev + devfs_automounted="no" + if [ -e "/dev/.devfsd" ] + then + mymounts="$(awk '($3 == "devfs") { print "yes"; exit 0 }' /proc/mounts)" + if [ "${mymounts}" != "yes" ] + then + rm -f /dev/.devfsd + else + devfs_automounted="yes" + fi + fi + + # Try to figure out how the user wants /dev handled + # - check $RC_DEVICES from /etc/conf.d/rc + # - check boot parameters + # - make sure the required binaries exist + # - make sure the kernel has support + if [ "${RC_DEVICES}" = "static" ] + then + ebegin "Using existing device nodes in /dev" + eend 0 + else + fellback_to_devfs="no" + case "${RC_DEVICES}" in + devfs) devfs="yes" + udev="no" + ;; + udev) devfs="yes" + udev="yes" + fellback_to_devfs="yes" + ;; + auto|*) devfs="yes" + udev="yes" + ;; + esac + + # Check udev prerequisites and kernel params + if [ "${udev}" = "yes" ] + then + if get_bootparam "noudev" || \ + [ ! -x /sbin/udev -o -e "/dev/.devfsd" ] || \ + [ "$(get_KV)" -lt "$(KV_to_int '2.6.0')" ] + then + udev="no" + fi + fi + + # Check devfs prerequisites and kernel params + if [ "${devfs}" = "yes" ] + then + if get_bootparam "nodevfs" || [ "${udev}" = "yes" ] + then + devfs="no" + fi + fi + + # Actually start setting up /dev now + if [[ ${udev} = "yes" ]] ; then + # Setup temporary storage for /dev + ebegin "Mounting /dev for udev" + if [[ ${RC_USE_FSTAB} = "yes" ]] ; then + mntcmd=$(get_mount_fstab /dev) + else + unset mntcmd + fi + if [[ -n ${mntcmd} ]] ; then + try mount -n ${mntcmd} + else + if egrep -qs tmpfs /proc/filesystems ; then + mntcmd="tmpfs" + else + mntcmd="ramfs" + fi + # many video drivers require exec access in /dev #92921 + try mount -n -t ${mntcmd} udev /dev -o exec,nosuid,mode=0755 + fi + eend $? + + # Selinux lovin; /selinux should be mounted by selinux-patched init + if [[ -x /sbin/restorecon ]] && [[ -c /selinux/null ]] ; then + restorecon /dev &> /selinux/null + fi + + # Actually get udev rolling + ebegin "Configuring system to use udev" + if [[ ${RC_DEVICE_TARBALL} = "yes" ]] && [[ -s /lib/udev-state/devices.tar.bz2 ]] + then + einfo " Populating /dev with device nodes ..." + try tar -jxpf /lib/udev-state/devices.tar.bz2 -C /dev + fi + populate_udev + + # Setup hotplugging (if possible) + if [ -e /proc/sys/kernel/hotplug ] ; then + if [ "$(udev_version)" -ge "48" ] ; then + einfo " Setting /sbin/udevsend as hotplug agent ..." + echo "/sbin/udevsend" > /proc/sys/kernel/hotplug + elif [ -x /sbin/hotplug ] ; then + einfo " Using /sbin/hotplug as hotplug agent ..." + else + einfo " Setting /sbin/udev as hotplug agent ..." + echo "/sbin/udev" > /proc/sys/kernel/hotplug + fi + fi + eend 0 + + # With devfs, /dev can be mounted by the kernel ... + elif [ "${devfs}" = "yes" ] + then + mymounts="$(awk '($2 == "devfs") { print "yes"; exit 0 }' /proc/filesystems)" + # Is devfs support compiled in? + if [ "${mymounts}" = "yes" ] + then + if [ "${devfs_automounted}" = "no" ] + then + ebegin "Mounting devfs at /dev" + try mount -n -t devfs devfs /dev + eend $? + else + ebegin "Kernel automatically mounted devfs at /dev" + eend 0 + fi + ebegin "Starting devfsd" + /sbin/devfsd /dev >/dev/null + eend $? "Could not start /sbin/devfsd" + else + devfs="no" + fi + + # Did the user want udev in the config file but for + # some reason, udev support didnt work out ? + if [ "${fellback_to_devfs}" = "yes" ] + then + ewarn "You wanted udev but support for it was not available!" + ewarn "Please review your system after it's booted!" + fi + fi + + # OK, if we got here, things are probably not right :) + if [ "${devfs}" = "no" ] && [ "${udev}" = "no" ] + then + clear + echo + einfo "The Gentoo Linux system initialization scripts have detected that" + einfo "your system does not support DEVFS or UDEV. Since Gentoo Linux" + einfo "has been designed with these dynamic /dev managers in mind, it is" + einfo "highly suggested that you build support for it into your kernel." + einfo "Please read the Gentoo Handbook for more information!" + echo + einfo " http://www.gentoo.org/doc/en/handbook/" + echo + einfo "Thanks for using Gentoo! :)" + echo + read -t 15 -p "(hit Enter to continue or wait 15 seconds ...)" + fi + fi + + # From linux-2.5.68 we need to mount /dev/pts again ... + if [ "$(get_KV)" -ge "$(KV_to_int '2.5.68')" ] + then + have_devpts="$(awk '($2 == "devpts") { print "yes"; exit 0 }' /proc/filesystems)" + + if [ "${have_devpts}" = "yes" ] + then + # Only try to create /dev/pts if we have /dev mounted dynamically, + # else it might fail as / might be still mounted readonly. + if [ ! -d /dev/pts ] && \ + [ "${devfs}" = "yes" -o "${udev}" = "yes" ] + then + # Make sure we have /dev/pts + mkdir -p /dev/pts &>/dev/null || \ + ewarn "Could not create /dev/pts!" + fi + + if [[ -d /dev/pts ]] ; then + ebegin "Mounting devpts at /dev/pts" + if [[ ${RC_USE_FSTAB} = "yes" ]] ; then + mntcmd=$(get_mount_fstab /dev/pts) + else + unset mntcmd + fi + try mount -n ${mntcmd:--t devpts -o gid=5,mode=0620 devpts /dev/pts} + eend $? + fi + fi + fi + + # Start logging console output since we have all /dev stuff setup + bootlog start + + # Swap needs to be activated *after* /dev has been fully setup so that + # the fstab can be properly parsed. This first pass we send to /dev/null + # in case the user has swap points setup on different partitions. We + # will run swapon again in localmount and that one will report errors. + ebegin "Activating (possible) swap" + /sbin/swapon -a >& /dev/null + eend 0 + + # Set the console loglevel to 1 for a cleaner boot + # the logger should anyhow dump the ring-0 buffer at start to the + # logs, and that with dmesg can be used to check for problems + /bin/dmesg -n 1 + + # We set the forced softlevel from the kernel command line + # It needs to be run right after proc is mounted for the + # boot runlevel + setup_defaultlevels + + # $BOOT can be used by rc-scripts to test if it is the first time + # the 'boot' runlevel is executed. Now also needed by some stuff in + # the 'sysinit' runlevel ... + export BOOT="yes" + + start_critical_service() { + ( + local retval= + local service=$1 + # Needed for some addons like dm-crypt that starts in critical services + local myservice=$1 + + source "/etc/init.d/${service}" || eerror "Failed to source /etc/init.d/${service}" + retval=$? + [ "${retval}" -ne 0 ] && return "${retval}" + [ -e "/etc/conf.d/${service}" ] && source "/etc/conf.d/${service}" + source /etc/rc.conf + + start || eerror "Failed to start /etc/init.d/${service}" + retval=$? + + return "${retval}" + ) + } + + # We first try to find a locally defined list of critical services + # for a particular runlevel. If we cannot find it, we use the + # defaults. + get_critical_services + + splash "rc_init" "${argv1}" + + export START_CRITICAL="yes" + + # We do not want to break compatibility, so we do not fully integrate + # these into /sbin/rc, but rather start them by hand ... + for x in ${CRITICAL_SERVICES} + do + splash "svc_start" "${x}" + user_want_interactive && interactive="yes" + if ! start_critical_service "${x}" ; then + splash "critical" &>/dev/null & + + echo + eerror "One of more critical startup scripts failed to start!" + eerror "Please correct this, and reboot ..." + echo; echo + /sbin/sulogin ${CONSOLE} + einfo "Unmounting filesystems" + /bin/mount -a -o remount,ro &>/dev/null + einfo "Rebooting" + /sbin/reboot -f + fi + + splash "svc_started" "${x}" "0" + done + + unset START_CRITICAL + + # /var/log should be writable now, so starting saving the boot output + bootlog sync + + # have to run this after /var/run is mounted rw #85304 + if [ -x /sbin/irqbalance -a "$(get_KV)" -ge "$(KV_to_int '2.5.0')" ] + then + ebegin "Starting irqbalance" + /sbin/irqbalance + eend $? + fi + + # Check that $svcdir exists ... + check_statedir "${svcdir}" + + # Should we use tmpfs/ramfs/ramdisk for caching dependency and + # general initscript data? Note that the 'gentoo=<fs>' kernel + # option should override any other setting ... + for fs in tmpfs ramfs ramdisk + do + if get_bootparam "${fs}" + then + svcmount="yes" + svcfstype="${fs}" + break + fi + done + if [ "${svcmount}" = "yes" ] + then + ebegin "Mounting ${svcfstype} at ${svcdir}" + case "${svcfstype}" in + ramfs) + try mount -n -t ramfs svcdir "${svcdir}" \ + -o rw,mode=0755,size="${svcsize}"k + ;; + ramdisk) + try dd if=/dev/zero of=/dev/ram0 bs=1k count="${svcsize}" + try /sbin/mke2fs -i 1024 -vm0 /dev/ram0 "${svcsize}" + try mount -n -t ext2 /dev/ram0 "${svcdir}" -o rw + ;; + tmpfs|*) + try mount -n -t tmpfs svcdir "${svcdir}" \ + -o rw,mode=0755,size="${svcsize}"k + ;; + esac + eend 0 + fi + + # If booting off CD, we want to update inittab before setting the runlevel + if [ -f "/sbin/livecd-functions.sh" -a -n "${CDBOOT}" ] + then + ebegin "Updating inittab" + livecd_fix_inittab + eend $? + /sbin/telinit q &>/dev/null + fi + + # Clear $svcdir from stale entries, but leave the caches around, as it + # should help speed things up a bit + rm -rf $(ls -d1 "${svcdir}/"* 2>/dev/null | \ + grep -ve '\(depcache\|deptree\|envcache\)') + + echo "sysinit" > "${svcdir}/softlevel" + echo "${interactive}" > "${svcdir}/interactive" + + # Update the dependency cache + /sbin/depscan.sh -u + + # Now that the dependency cache are up to date, make sure these + # are marked as started ... + ( + # Needed for mark_service_started() + source "${svclib}/sh/rc-services.sh" + + for x in ${CRITICAL_SERVICES} + do + mark_service_started "${x}" + done + ) + + # If the user's /dev/null or /dev/console are missing, we + # should help them out and explain how to rectify the situation + if [ ${dev_null} -eq 0 -o ${dev_console} -eq 0 ] \ + && [ -e /usr/share/baselayout/issue.devfix ] + then + # Backup current /etc/issue + if [ -e /etc/issue -a ! -e /etc/issue.devfix ] + then + mv /etc/issue /etc/issue.devfix + fi + + cp /usr/share/baselayout/issue.devfix /etc/issue + fi + + # Setup login records ... this has to be done here because when + # we exit this runlevel, init will write a boot record to utmp + # If /var/run is readonly, then print a warning, not errors + if touch /var/run/utmp 2>/dev/null + then + > /var/run/utmp + touch /var/log/wtmp + chgrp utmp /var/run/utmp /var/log/wtmp + chmod 0664 /var/run/utmp /var/log/wtmp + # Remove /var/run/utmpx (bug from the past) + rm -f /var/run/utmpx + else + ewarn "Skipping /var/run/utmp initialization (ro root?)" + fi + + # All done logging + bootlog quit + + exit 0 +fi # Sysinit ends here + +if [[ ( ${RUNLEVEL} == "S" || ${RUNLEVEL} == "1" ) && ${argv1} == "boot" ]] +then + setup_defaultlevels + + if [ -n "${DEFAULTLEVEL}" -a "${DEFAULTLEVEL}" != "default" ] + then + # Setup our default runlevel runlevel that will be run + # the first time /sbin/rc is called with argv1 != sysinit|boot + echo "${DEFAULTLEVEL}" > "${svcdir}/ksoftlevel" + fi + + # $BOOT can be used by rc-scripts to test if it is the first time + # the 'boot' runlevel is executed + export BOOT="yes" + + # We reset argv1 to the bootlevel given on the kernel command line + # if there is one + argv1="${BOOTLEVEL}" + +elif [[ ${RUNLEVEL} != "S" && ${RUNLEVEL} != "1" && -e ${svcdir}/ksoftlevel ]] +then + argv1="$(< ${svcdir}/ksoftlevel)" + rm -f "${svcdir}/ksoftlevel" +elif [[ ${RUNLEVEL} != "S" && ${RUNLEVEL} != "1" && ${argv1} == "single" ]] +then + /sbin/telinit S + exit 0 +elif [[ ( ${RUNLEVEL} == "S" || ${RUNLEVEL} == "1" ) && ${argv1} != "single" ]] +then + level=$(awk -v level="${argv1}" ' + $2 == level { + split($0, fields, ":") + print fields[2] + exit + }' /etc/inittab 2>/dev/null) + [[ -z ${level} ]] && level=3 + /sbin/telinit "${level}" + exit 0 +fi + +source "${svclib}/sh/rc-services.sh" + +if [ -f "${svcdir}/softlevel" ] +then + # Set OLDSOFTLEVEL if we had a valid SOFTLEVEL + export OLDSOFTLEVEL="$(< ${svcdir}/softlevel)" +else + export OLDSOFTLEVEL= +fi + +if [ -z "${argv1}" ] +then + if [ -f "${svcdir}/softlevel" ] + then + export SOFTLEVEL="$(< ${svcdir}/softlevel)" + else + export SOFTLEVEL="${BOOTLEVEL}" + fi +else + export SOFTLEVEL="${argv1}" +fi + +if [ ! -f "${svcdir}/softlevel" ] +then + echo "${SOFTLEVEL}" > "${svcdir}/softlevel" +fi + +# For keeping a list of services that fails during boot/halt +if [ ! -d "${svcdir}/failed" ] +then + mkdir -p -m 0755 "${svcdir}/failed" +else + rm -rf "${svcdir}"/failed/* +fi + +splash "rc_init" "${argv1}" + +if [ "${SOFTLEVEL}" = "reboot" -o "${SOFTLEVEL}" = "shutdown" ] +then + myscripts= + +elif [ "${SOFTLEVEL}" = "single" ] +then + get_critical_services + + myscripts="${CRITICAL_SERVICES}" + +elif [ ! -d "/etc/runlevels/${SOFTLEVEL}" ] +then + eerror "ERROR: runlevel ${SOFTLEVEL} does not exist; exiting ..." + exit 1 +else + myscripts= + if [ "${SOFTLEVEL}" != "${BOOTLEVEL}" ] + then + # Normal runlevels *include* boot scripts + mylevels="$(dolisting "/etc/runlevels/${SOFTLEVEL}/")" + mylevels="${mylevels} $(dolisting /etc/runlevels/${BOOTLEVEL}/)" + else + # Non-normal runlevels don't include boot scripts as default + mylevels="$(dolisting "/etc/runlevels/${SOFTLEVEL}/")" + fi + + [ "${OLDSOFTLEVEL}" = "${BOOTLEVEL}" -o "${OLDSOFTLEVEL}" = "single" ] \ + && /bin/dmesg -n 1 + + for x in ${mylevels} + do + [ -L "${x}" ] && myscripts="${myscripts} ${x##*/}" + done +fi + +# The softscripts dir contains all scripts that belong to the +# runlevel specified in ${svcdir}/softlevel +# It needs to be a new directory, else when stopping the services +# and the old directory is not intact, things get broken + +mkdir -p -m 0755 "${svcdir}/softscripts.new" + +for x in ${myscripts} ; do + if [[ ! -e /etc/init.d/${x} ]] ; then + ewarn "WARNING: /etc/init.d/${x} missing; skipping ..." + continue + fi + # The -f eliminates a warning if the symlink already exists, + # which can happen if a service is in both the boot level and + # the current "normal" runlevel + ln -snf "/etc/init.d/${x}" "${svcdir}/softscripts.new/${x}" +done + +get_stop_services() { + local x list + + for x in $(dolisting "${svcdir}/inactive/") \ + $(dolisting "${svcdir}/started/") ; do + list="${list} ${x##*/}" + done + + reverse_list $(trace_dependencies ${list}) +} + +dep_stop() { + local x dep needsme depservice + local myservice=${1##*/} + + service_stopped "${myservice}" && return 0 + + # Candidate for zapping ? + [[ ! -L ${svcdir}/softscripts.new/${myservice} ]] || \ + return 0 + + # If this is a 'net' service, we do not want to stop it if it was + # not in the previous runlevel, and we are not shutting down, + # rebooting or going to single runlevel. This is because the user + # (or hotplut) might have started it (net.ppp?) ... + if net_service "${myservice}" && \ + [[ ${SOFTLEVEL} != "reboot" && \ + ${SOFTLEVEL} != "shutdown" && \ + ${SOFTLEVEL} != "single" ]] ; then + if [[ -z ${OLDSOFTLEVEL} ]] || \ + ! in_runlevel "${myservice}" "${OLDSOFTLEVEL}" + then + # This service is not in the previous runlevel, so + # do not stop it ... + return 0 + fi + fi + + # Should not work for 'use' + if [[ -z $(needsme "${myservice}") ]] ; then + # Nothing depends on me + stop_service "${myservice}" + else + # Something may depend on me + needsme=0 + + for dep in $(needsme "${myservice}") ; do + #if service_started "${dep}" && \ + if [[ -L "${svcdir}/softscripts.new/${dep}" ]] ; then + # This dep is valid + needsme=1 + + break + fi + done + + [[ ${needsme} -eq 0 ]] && stop_service "${myservice}" + fi +} + +# Stop services +if [[ ${SOFTLEVEL} != "single" && \ + ${SOFTLEVEL} != "reboot" && \ + ${SOFTLEVEL} != "shutdown" ]] +then + for i in $(get_stop_services) ; do + dep_stop "${i}" + done + + # Wait for any services that may still be stopping ... + [ "${RC_PARALLEL_STARTUP}" = "yes" ] && wait +else + get_critical_services + + is_critical_service() { + local x + local myservice=${1##*/} + + for x in ${CRITICAL_SERVICES} ${LOGGER_SERVICE} ; do + [[ ${myservice} == "${x}" ]] && return 0 + done + + return 1 + } + + # First stop non critical services + for i in $(get_stop_services) ; do + is_critical_service "${i}" || dep_stop "${i}" + done + + # Wait for any services that may still be stopping ... + [ "${RC_PARALLEL_STARTUP}" = "yes" ] && wait + + export STOP_CRITICAL="yes" + # Now stop the rest + for i in $(get_stop_services) ; do + dep_stop "${i}" + done + unset STOP_CRITICAL +fi + +# Only change softlevel AFTER all the services have been stopped, +# else they will not get the depend's right (wrong SOFTLEVEL) + +echo "${SOFTLEVEL}" > "${svcdir}/softlevel" + +if [[ ${SOFTLEVEL} == "reboot" || ${SOFTLEVEL} == "shutdown" ]] ; then + source /sbin/functions.sh + + # Clear $svcdir from stale entries, but leave the caches around, as it + # should help speed things up a bit + rm -rf $(ls -d1 "${svcdir}/"* 2>/dev/null | \ + grep -ve '\(depcache\|deptree\|envcache\)') + + source /etc/init.d/halt.sh + + if [[ ${SOFTLEVEL} == "reboot" ]] ; then + source /etc/init.d/reboot.sh + else + source /etc/init.d/shutdown.sh + fi + + # Should never get here + exit 0 +fi + +if [[ ${SOFTLEVEL} == "single" ]] ; then + /sbin/sulogin ${CONSOLE} + exit 0 +fi + +# Move the old softscritps directory to a different one +# and make the new softscripts directory the current + +mv -f "${svcdir}/softscripts" "${svcdir}/softscripts.old" +mv -f "${svcdir}/softscripts.new" "${svcdir}/softscripts" + +get_start_services() { + local x list + + get_critical_services + list=${CRITICAL_SERVICES} + + [[ -n ${LOGGER_SERVICE} && \ + -L ${svcdir}/softscripts/${LOGGER_SERVICE} ]] && \ + list="${list} ${LOGGER_SERVICE}" + + for x in $(dolisting "${svcdir}/softscripts/") ; do + list="${list} ${x##*/}" + done + + trace_dependencies ${list} +} + +[[ -e "${svcdir}/interactive" ]] \ + && interactive="$(<"${svcdir}/interactive")" + +# Start scripts +for i in $(get_start_services) ; do + if service_stopped "${i}" ; then + user_want_interactive && interactive="yes" + if [[ ${interactive} == "yes" ]]; then + do_interactive "${i}" start_service "${i}" + else + start_service "${i}" + fi + fi +done + +# Wait for any services that may still be running ... +[ "${RC_PARALLEL_STARTUP}" = "yes" ] && wait + +# Clean the old runlevel +rm -rf "${svcdir}/softscripts.old" &>/dev/null + +# Depends gets nuked, so update them +# (this problem should be solved now, but i think it will be a good idea +# to recreate the deps after a change in runlevel) + +#/sbin/depscan.sh &>/dev/null + +# We want devfsd running after a change of runlevel (this is mostly if we return +# from runlevel 'single') +if [ -z "`ps --no-heading -C 'devfsd'`" -a \ + -n "`gawk '/\/dev devfs/ { print }' /proc/mounts 2>/dev/null`" ] +then + if [ "${RC_DEVFSD_STARTUP}" != "no" ] + then + /sbin/devfsd /dev &>/dev/null + fi +fi + +# Runlevel end, so clear stale fail list +rm -rf "${svcdir}/failed" &>/dev/null + +# If we were in the boot runlevel, it is done now ... +if [[ -n ${BOOT} ]]; then + unset BOOT + # Save our interactive mode into the default runlevel + echo "${interactive}" > "${svcdir}/interactive" +else + # As we're not boot, we remove the interactive file + [[ -e "${svcdir}/interactive" ]] && rm -f "${svcdir}/interactive" +fi + +# Remove the cached CONSOLETYPE +unset CONSOLETYPE + +splash "rc_exit" + +# vim:ts=4 diff --git a/sbin/rc-daemon.sh b/sbin/rc-daemon.sh new file mode 100755 index 0000000..fab3577 --- /dev/null +++ b/sbin/rc-daemon.sh @@ -0,0 +1,382 @@ +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# RC functions to work with daemons +# Basically we're a fancy wrapper for start-stop-daemon +# and should be called as such. This means that our init scripts +# should work as is with zero modification :) + +# Actually, the above is a small as lie we have some init scripts which try to +# get start-stop-daemon to launch a shell script. While this does work with +# the start-stop-daemon program in /sbin, it does cause a problem for us +# when we're testing for the daemon to be running. I (Roy Marples) view this +# as behaviour by design as start-stop-daemon should not be used to run shell +# scripts! +# At the time of writing, the only culprit I know of is courier-imap. +# There may be others! + +RC_GOT_DAEMON="yes" + +[[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh +[[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh" + +RC_RETRY_KILL="no" +RC_RETRY_TIMEOUT=1 +RC_RETRY_COUNT=5 +RC_FAIL_ON_ZOMBIE="no" +RC_KILL_CHILDREN="no" +RC_WAIT_ON_START="0.1" + +# Override default settings with user settings ... +[[ -f /etc/conf.d/rc ]] && source /etc/conf.d/rc + +# void rc_shift_args(void) +# +# Proccess vars - makes things easier by using the shift command +# and indirect variables +rc_shift_args() { + while [[ $# != "0" ]]; do + if [[ $1 != "-"* && -n ${addvar} ]]; then + if [[ -z ${!addvar} ]]; then + eval "${addvar}=\"$1\"" + else + eval "${addvar}=\"${!addvar} $1\"" + fi + shift + continue + fi + unset addvar + case "$1" in + -S|--start) + stopping=false + ;; + -K|--stop) + stopping=true + ;; + -n|--name) + addvar="name" + ;; + -x|--exec|-a|--startas) + addvar="cmd" + ;; + -p|--pidfile) + addvar="pidfile" + ;; + --pidfile=*) + pidfile="${1##--pidfile=}" + ;; + --pid=*) + pidfile="${1##--pid=}" + ;; + -s|--signal) + addvar="signal" + ;; + -t|--test|-o|--oknodo) + nothing=true + ;; + esac + shift + done +} + +# void rc_setup_daemon_vars(void) +# +# Setup our vars based on the start-stop-daemon command +rc_setup_daemon_vars() { + local name i + local -a sargs=( "${args%% \'--\' *}" ) + local -a eargs + local x="${args// \'--\' /}" + [[ ${x} != "${args}" ]] && eargs=( "${args##* \'--\' }" ) + + rc_shift_args ${sargs[@]} + + [[ -z ${cmd} ]] && cmd="${name}" + + # We may want to launch the daemon with a custom command + # This is mainly useful for debugging with apps like valgrind, strace + local bash_service=$( bash_variable "${myservice}" ) + eval x=\"\$\{RC_DAEMON_${bash_service}\}\" + if [[ -n ${x} ]]; then + local -a d=( ${x} ) + if ${stopping}; then + args="--stop" + else + args="--start" + fi + + # Add -- or - arguments as s-s-d options + j=${#d[@]} + for (( i=0; i<j; i++ )); do + [[ ${d[i]:0:1} != "-" ]] && break + args="${args} ${d[i]}" + unset d[i] + done + d=$( "${d[@]}" ) + + eval args=\"${args} --exec '${d[0]}' -- ${d[@]:1} '${cmd}' ${eargs[@]}\" + ! ${stopping} && cmd="${d[0]}" + fi + + return 0 +} + +# bool rc_try_kill_pid(int pid, char* signal, bool session) +# +# Repeatedly kill the pid with the given signal until it dies +# If session is true then we use tread pid as session and send it +# via pkill +# Returns 0 if successfuly otherwise 1 +rc_try_kill_pid() { + local pid="$1" signal="${2:-TERM}" session="${3:-false}" i s + + # We split RC_RETRY_TIMEOUT into tenths of seconds + # So we return as fast as possible + (( s=${RC_RETRY_TIMEOUT}/10 )) + + for (( i=0; i<RC_RETRY_COUNT*10; i++ )); do + if ${session} ; then + if [[ -x /usr/bin/pkill ]]; then + /usr/bin/pkill "-${signal}" -s "${pid}" || return 0 + else + local pids=$(/bin/ps -eo pid,sid | /bin/sed -n 's/'${pid}'$//p') + [[ -z ${pids} ]] && return 0 + /bin/kill -s "${signal}" ${pids} 2>/dev/null + fi + else + /bin/kill -s "${signal}" "${pid}" 2>/dev/null || return 0 + fi + LC_ALL=C /bin/sleep "${s}" + done + + return 1 +} + +# bool rc_kill_pid(int pid, bool session) +# +# Kills the given pid/session +# Returns 1 if we fail to kill the pid (if it's valid) otherwise 0 +rc_kill_pid() { + local pid="$1" session="${2:-false}" + + rc_try_kill_pid "${pid}" "${signal}" "${session}" && return 0 + + [[ ${RC_RETRY_KILL} == "yes" ]] \ + && rc_try_kill_pid "${pid}" KILL "${session}" && return 0 + + return 1 +} + +# char* pidof(char* cmd, ...) +# +# Returns a space seperated list of pids associated with the command +# This is to handle the rpc.nfsd program which acts weird +pidof() { + local arg args + + for arg in "$@"; do + [[ ${arg##*/} == "rpc.nfsd" ]] && arg="${arg%/*}/nfsd" + args="${args} '"${arg}"'" + done + + eval /bin/pidof -x ${args} +} + +# bool is_daemon_running(char* cmd, char* pidfile) +# +# Returns 0 if the given daemon is running, otherwise 1 +# If a pidfile is supplied, the pid inside it must match +# a pid in the list of pidof ${cmd} +is_daemon_running() { + local cmd pidfile pids pid + + if [[ $# == "1" ]]; then + cmd="$1" + else + local i j="$#" + for (( i=0; i<j-1; i++ )); do + cmd="${cmd} $1" + shift + done + pidfile="$1" + fi + + pids=$( pidof ${cmd} ) + [[ -z ${pids} ]] && return 1 + + [[ -s ${pidfile} ]] || return 0 + + read pid < "${pidfile}" + pids=" ${pids} " + [[ ${pids// ${pid} } != "${pids}" ]] +} + +# int rc_start_daemon(void) +# +# We don't do anyting fancy - just pass the given options +# to start-stop-daemon and return the value +rc_start_daemon() { + eval /sbin/start-stop-daemon "${args}" + local retval="$?" + + [[ ${retval} != "0" ]] && return "${retval}" + [[ ${RC_WAIT_ON_START} == "0" ]] && return "${retval}" + + # We pause for RC_WAIT_ON_START seconds and then + # check if the daemon is still running - this is mainly + # to handle daemons who launch and then fail due to invalid + # configuration files + LC_ALL=C /bin/sleep "${RC_WAIT_ON_START}" + is_daemon_running ${cmd} "${pidfile}" + retval="$?" + [[ ${retval} == "0" ]] && return 0 + + # Stop if we can to clean things up + if [[ $( type -t stop ) == "function" ]]; then + stop >/dev/null # We don't want to echo ebegin/eend + elif [[ -n ${pidfile} ]]; then + rc_stop_daemon + fi + return "${retval}" +} + +# bool rc_stop_daemon(void) +# +# Instead of calling start-stop-daemon we instead try and +# kill the process ourselves and any children left over +# Returns 0 if everything was successful otherwise 1 +rc_stop_daemon() { + local pid pids retval="0" + + if [[ -n ${cmd} ]]; then + if ! is_daemon_running ${cmd} "${pidfile}" ; then + [[ ${RC_FAIL_ON_ZOMBIE} == "yes" ]] && return 1 + fi + pids=$( pidof ${cmd} ) + fi + + if [[ -s ${pidfile} ]]; then + read pid < "${pidfile}" + # Check that the given program is actually running the pid + if [[ -n ${pids} ]]; then + pids=" ${pids} " + [[ ${pids// ${pid} } == ${pids} ]] && return 1 + fi + pids=${pid} + fi + + for pid in ${pids}; do + if [[ ${RC_FAIL_ON_ZOMBIE} == "yes" ]]; then + /bin/ps -p "${pid}" &>/dev/null || return 1 + fi + + if rc_kill_pid "${pid}" false ; then + # Remove the pidfile if the process didn't + [[ -f ${pidfile} ]] && /bin/rm -f "${pidfile}" + else + retval=1 + fi + + if [[ ${RC_KILL_CHILDREN} == "yes" ]]; then + rc_kill_pid "${pid}" true || retval=1 + fi + done + + return "${retval}" +} + +# void update_service_status(char *service) +# +# Loads the service state file and ensures that all listed daemons are still +# running - hopefully on their correct pids too +# If not, we stop the service +update_service_status() { + local service="$1" daemonfile="${svcdir}/daemons/$1" i + local -a RC_DAEMONS=() RC_PIDFILES=() + + # We only care about marking started services as stopped if the daemon(s) + # for it are no longer running + ! service_started "${service}" && return + [[ ! -f ${daemonfile} ]] && return + + # OK, now check that every daemon launched is active + # If the --start command was any good a pidfile was specified too + source "${daemonfile}" + for (( i=0; i<${#RC_DAEMONS[@]}; i++ )); do + if ! is_daemon_running ${RC_DAEMONS[i]} "${RC_PIDFILES[i]}" ; then + if [[ -e "/etc/init.d/${service}" ]]; then + ( /etc/init.d/"${service}" stop &>/dev/null ) + break + fi + fi + done +} + +# int start-stop-daemon(...) +# +# Provide a wrapper to start-stop-daemon +# Return the result of start_daemon or stop_daemon depending on +# how we are called +start-stop-daemon() { + local args=$( requote "$@" ) result i + local cmd pidfile pid stopping signal nothing=false + local daemonfile="${svcdir}/daemons/${myservice}" + local -a RC_DAEMONS=() RC_PIDFILES=() + + [[ -e ${daemonfile} ]] && source "${daemonfile}" + + rc_setup_daemon_vars + + # We pass --oknodo and --test directly to start-stop-daemon and return + if ${nothing}; then + eval /sbin/start-stop-daemon "${args}" + return "$?" + fi + + if ${stopping}; then + rc_stop_daemon + result="$?" + if [[ ${result} == "0" ]]; then + # We stopped the daemon successfully + # so we remove it from our state + for (( i=0; i<${#RC_DAEMONS[@]}; i++ )); do + # We should really check for valid cmd AND pidfile + # But most called to --stop only set the pidfile + if [[ ${RC_DAEMONS[i]} == "{cmd}" \ + || ${RC_PIDFILES[i]}="${pidfile}" ]]; then + unset RC_DAEMONS[i] RC_PIDFILES[i] + RC_DAEMONS=( "${RC_DAEMONS[@]}" ) + RC_PIDFILES=( "${RC_PIDFILES[@]}" ) + break + fi + done + fi + else + rc_start_daemon + result="$?" + if [[ ${result} == "0" ]]; then + # We started the daemon sucessfully + # so we add it to our state + local max="${#RC_DAEMONS[@]}" + RC_DAEMONS[max]="${cmd}" + RC_PIDFILES[max]="${pidfile}" + fi + fi + + # Write the new list of daemon states for this service + if [[ ${#RC_DAEMONS[@]} == "0" ]]; then + [[ -f ${daemonfile} ]] && rm -f "${daemonfile}" + else + echo "RC_DAEMONS[0]=\"${RC_DAEMONS[0]}\"" > "${daemonfile}" + echo "RC_PIDFILES[0]=\"${RC_PIDFILES[0]}\"" >> "${daemonfile}" + + for (( i=1; i<${#RC_DAEMONS[@]}; i++ )); do + echo "RC_DAEMONS[${i}]=\"${RC_DAEMONS[i]}\"" >> "${daemonfile}" + echo "RC_PIDFILES[${i}]=\"${RC_PIDFILES[i]}\"" >> "${daemonfile}" + done + fi + + return "${result}" +} + +# vim:ts=4 diff --git a/sbin/rc-help.sh b/sbin/rc-help.sh new file mode 100755 index 0000000..2a28859 --- /dev/null +++ b/sbin/rc-help.sh @@ -0,0 +1,186 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +source /sbin/functions.sh + +if [ "${RC_NOCOLOR}" = "yes" ] +then + unset BLUE GREEN OFF CYAN +else + BLUE="\033[34;01m" + GREEN="\033[32;01m" + OFF="\033[0m" + CYAN="\033[36;01m" +fi + +myscript="${1}" +if [ -L "${1}" ] +then + myservice="$(readlink "${1}")" +else + myservice=${1} +fi + +myservice=${myservice##*/} + +echo -e " +${GREEN}Gentoo Linux RC-Scripts; ${BLUE}http://www.gentoo.org/${OFF} + Copyright 1999-2004 Gentoo Foundation; Distributed under the GPL + +Usage: ${CYAN}${myservice}${OFF} < ${GREEN}flags${OFF} > [ ${GREEN}options${OFF} ] + +${CYAN}Options:${OFF} + ${GREEN}start${OFF} + Start service, as well as the services it depends on (if not already + started). + + ${GREEN}stop${OFF} + Stop service, as well as the services that depend on it (if not already + stopped). + + ${GREEN}restart${OFF} + Restart service, as well as the services that depend on it. + + Note to developers: If this function is replaced with a custom one, + 'svc_start' and 'svc_stop' should be used instead of 'start' and + 'stop' to restart the service. This is so that the dependencies + can be handled correctly. Refer to the portmap rc-script for an + example. + + ${GREEN}pause${OFF} + Same as 'stop', but the services that depends on it, will not be + stopped. This is useful for stopping a network interface without + stopping all the network services that depend on 'net'. + + ${GREEN}zap${OFF} + Reset a service that is currently stopped, but still marked as started, + to the stopped state. Basically for killing zombie services. + + ${GREEN}status${OFF} + Prints \"status: started\" if the service is running, else it + prints \"status: stopped\". + + Note that if the '--quiet' flag is given, it will return true if the + service is running, else false. + + ${GREEN}ineed|iuse${OFF} + List the services this one depends on. Consult the section about + dependencies for more info on the different types of dependencies. + + ${GREEN}needsme|usesme${OFF} + List the services that depend on this one. Consult the section about + dependencies for more info on the different types of dependencies. + + ${GREEN}broken${OFF} + List the missing or broken dependencies of type 'need' this service + depends on. + +${CYAN}Flags:${OFF} + ${GREEN}--quiet${OFF} + Suppress output to stdout, except if: + + 1) It is a warning, then output to stdout + 2) It is an error, then output to stderr + + ${GREEN}--nocolor${OFF} + Suppress the use of colors. + +${CYAN}Dependencies:${OFF} + This is the heart of the Gentoo RC-Scripts, as it determines the order + in which services gets started, and also to some extend what services + get started in the first place. + + The following example demonstrates how to use dependencies in + rc-scripts: + + depend() { + need foo bar + use ray + } + + Here we have foo and bar as dependencies of type 'need', and ray of + type 'use'. You can have as many dependencies of each type as needed, as + long as there is only one entry for each type, listing all its dependencies + on one line only. + + ${GREEN}need${OFF} + These are all the services needed for this service to start. If any service + in the 'need' line is not started, it will be started even if it is not + in the current, or 'boot' runlevel, and then this service will be started. + If any services in the 'need' line fails to start or is missing, this + service will never be started. + + ${GREEN}use${OFF} + This can be seen as representing optional services this service depends on + that are not critical for it to start. For any service in the 'use' line, + it must be added to the 'boot' or current runlevel to be considered a valid + 'use' dependency. It can also be used to determine startup order. + + ${GREEN}before${OFF} + This, together with the 'after' dependency type, can be used to control + startup order. In core, 'before' and 'after' do not denote a dependency, + but should be used for order changes that will only be honoured during + a change of runlevel. All services listed will get started *after* the + current service. In other words, this service will get started *before* + all listed services. + + ${GREEN}after${OFF} + All services listed will be started *before* the current service. Have a + look at 'before' for more info. + + ${GREEN}provide${OFF} + This is not really a dependency type, rather it will enable you to create + virtual services. This is useful if there is more than one version of + a specific service type, system loggers or crons for instance. Just + have each system logger provide 'logger', and make all services in need + of a system logger depend on 'logger'. This should make things much more + generic. + + Note that the 'need', 'use', 'before' and 'after' dependeny types can have '*' + as argument. Having: + + depend() { + before * + } + + will make the service start first in the current runlevel, and: + + depend() { + after * + } + + will make the service the last to start. + + You should however be careful how you use this, as I really will not + recommend using it with the 'need' or 'use' dependency type ... you have + been warned! + +${CYAN}'net' Dependency and 'net.*' Services:${OFF} + Example: + + depend() { + need net + } + + This is a special dependency of type 'need'. It represents a state where + a network interface or interfaces besides lo is up and active. Any service + starting with 'net.' will be treated as a part of the 'net' dependency, + if: + + 1. It is part of the 'boot' runlevel + 2. It is part of the current runlevel + + A few examples are the /etc/init.d/net.eth0 and /etc/init.d/net.lo services. + +${CYAN}Configuration files:${OFF} + There are two files which will be sourced for possible configuration by + the rc-scripts. They are (sourced from top to bottom): + + /etc/conf.d/${myservice} + /etc/rc.conf + +${CYAN}Management:${OFF} + Services are added and removed via the 'rc-update' tool. Running it without + arguments should give sufficient help. +" diff --git a/sbin/rc-services.sh b/sbin/rc-services.sh new file mode 100755 index 0000000..7ead024 --- /dev/null +++ b/sbin/rc-services.sh @@ -0,0 +1,883 @@ +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# RC Dependency and misc service functions + +RC_GOT_SERVICES="yes" + +[[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh + +if [[ ${RC_GOT_DEPTREE_INFO} != "yes" ]]; then + # Only try and update if we are root + if [[ ${EUID} == "0" ]] && ! /sbin/depscan.sh -u ; then + echo + eerror "Error running '/sbin/depscan.sh'!" + eerror "Please correct any problems above." + exit 1 + fi + + source "${svcdir}/deptree" + if [[ ${RC_GOT_DEPTREE_INFO} != "yes" ]]; then + echo + eerror "Dependency info is missing! Please run" + eerror " # /sbin/depscan.sh" + eerror "to fix this." + exit 1 + fi +fi + +##################### +# Internal variables +##################### + +# The name of the service whose dependency info we currently have +rc_name= +# The index of the service whose dependency info we currently have +rc_index=0 +# Our dependency types ... +rc_ineed= +rc_needsme= +rc_iuse= +rc_usesme= +rc_ibefore= +rc_iafter= +rc_broken= +rc_mtime= + +############ +# Functions +############ + +# bool get_service_index(service, index) +# +# Print the index of 'service'. 'index' is the current index. +# +get_service_index() { + if [[ -z $1 || -z $2 ]]; then + echo "0" + return 1 + fi + + local x myservice="$1" index="$2" + + # Do we already have the index? + if [[ -n ${index} && ${index} -gt 0 \ + && ${myservice} == ${RC_DEPEND_TREE[${index}]} ]]; then + echo "${index}" + return 0 + fi + + for (( x=1; x<=${RC_DEPEND_TREE[0]}; x++ )); do + index=$(( ${x} * ${rc_index_scale} )) + if [[ ${myservice} == ${RC_DEPEND_TREE[${index}]} ]]; then + echo "${index}" + return 0 + fi + done + + echo "0" + return 1 +} + +# bool get_dep_info(service) +# +# Set the Dependency variables to contain data for 'service' +# +get_dep_info() { + [[ -z $1 ]] && return 1 + + local myservice="$1" + + # We already have the right stuff ... + [[ ${myservice} == ${rc_name} && -n ${rc_mtime} ]] && return 0 + + rc_index="`get_service_index "${myservice}" "${rc_index}"`" + rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}" + + # Verify that we have the correct index (rc_index) ... + # [[ ${rc_index} == "0" ]] && return 1 + + rc_name="${RC_DEPEND_TREE[${rc_index}]}" + rc_ineed="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ineed}))]}" + rc_needsme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_needsme}))]}" + rc_iuse="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iuse}))]}" + rc_usesme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_usesme}))]}" + rc_ibefore="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ibefore}))]}" + rc_iafter="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iafter}))]}" + rc_broken="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_broken}))]}" + rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}" + return 0 +} + +# string check_dependency(deptype, service1) +# +# List all the services that depend on 'service1' of dependency +# type 'deptype' +# +# bool check_dependency(deptype, -t, service1, service2) +# +# Returns true if 'service2' is a dependency of type 'deptype' +# of 'service1' +# +check_dependency() { + [[ -z $1 || -z $2 ]] && return 1 + + local x myservice deps + + # Set the dependency variables to relate to 'service1' + if [[ $2 == "-t" ]]; then + [[ -z $3 || -z $4 ]] && return 1 + myservice="$3" + else + myservice="$2" + fi + + if ! get_dep_info "${myservice}" >/dev/null ; then + eerror "Could not get dependency info for \"${myservice}\"!" > /dev/stderr + eerror "Please run:" > /dev/stderr + eerror " # /sbin/depscan.sh" > /dev/stderr + eerror "to try and fix this." > /dev/stderr + return 1 + fi + + # Do we have valid info for 'deptype' ? + eval deps=\"\$\{rc_$1\}\" + [[ -z ${deps} ]] && return 1 + + if [[ $2 == "-t" && -n $4 ]]; then + # Check if 'service1' have 'deptype' dependency on 'service2' + for x in ${deps}; do + [[ ${x} == $4 ]] && return 0 + done + return 1 + else + # Just list all services that 'service1' have 'deptype' dependency on. + echo "${deps}" + return 0 + fi +} + +# Same as for check_dependency, except 'deptype' is set to +# 'ineed'. It will return all the services 'service1' NEED's. +ineed() { + check_dependency ineed "$@" +} + +# Same as for check_dependency, except 'deptype' is set to +# 'needsme'. It will return all the services that NEED 'service1'. +needsme() { + check_dependency needsme "$@" +} + +# Same as for check_dependency, except 'deptype' is set to +# 'iuse'. It will return all the services 'service1' USE's. +iuse() { + check_dependency iuse "$@" +} + +# Same as for check_dependency, except 'deptype' is set to +# 'usesme'. It will return all the services that USE 'service1'. +usesme() { + check_dependency usesme "$@" +} + +# Same as for check_dependency, except 'deptype' is set to +# 'ibefore'. It will return all the services that are started +# *after* 'service1' (iow, it will start 'service1' before the +# list of services returned). +ibefore() { + check_dependency ibefore "$@" +} + +# Same as for check_dependency, except 'deptype' is set to +# 'iafter'. It will return all the services that are started +# *before* 'service1' (iow, it will start 'service1' after the +# list of services returned). +iafter() { + check_dependency iafter "$@" +} + +# Same as for check_dependency, except 'deptype' is set to +# 'broken'. It will return all the services that 'service1' +# NEED, but are not present. +broken() { + check_dependency broken "$@" +} + +# bool is_fake_service(service, runlevel) +# +# Returns ture if 'service' is a fake service in 'runlevel'. +# +is_fake_service() { + local x fake_services + + [[ -z $1 || -z $2 ]] && return 1 + + [[ $2 != ${BOOTLEVEL} && -e "/etc/runlevels/${BOOTLEVEL}/.fake" ]] \ + && fake_services="$( < /etc/runlevels/${BOOTLEVEL}/.fake )" + + [[ -e "/etc/runlevels/$2/.fake" ]] \ + && fake_services="${fake_services} $( < /etc/runlevels/$2/.fake )" + + for x in ${fake_services}; do + [[ $1 == ${x##*/} ]] && return 0 + done + + return 1 +} + +# bool in_runlevel(service, runlevel) +# +# Returns true if 'service' is in runlevel 'runlevel'. +# +in_runlevel() { + [[ -z $1 || -z $2 ]] && return 1 + + [[ -L "/etc/runlevels/$2/$1" ]] && return 0 + + return 1 +} + +# bool is_runlevel_start() +# +# Returns true if it is a runlevel change, and we are busy +# starting services. +# +is_runlevel_start() { + [[ -d ${svcdir}/softscripts.old && \ + ${SOFTLEVEL} != "${OLDSOFTLEVEL}" ]] && return 0 + + return 1 +} + +# bool is_runlevel_stop() +# +# Returns true if it is a runlevel change, and we are busy +# stopping services. +# +is_runlevel_stop() { + [[ -d ${svcdir}/softscripts.new && \ + ${SOFTLEVEL} != "${OLDSOFTLEVEL}" ]] && return 0 + + return 1 +} + +# void sevice_message([char *type] char *message) +# +# Print out a service message if we are on parallel +service_message() { + [[ ${RC_PARALLEL_STARTUP} != "yes" ]] && return + + local cmd="einfo" + if [[ $1 == 1 || $1 == "error" || $1 == "eerror" ]]; then + cmd="eerror" + shift + fi + + local r="${RC_QUIET_STDOUT}" + RC_QUIET_STDOUT="no" + ${cmd} "$@" + RC_QUIET_STDOUT="${r}" +} + +# bool begin_service( service ) +# +# atomically marks the service as being executed +# use like this: +# +# if begin_service service ; then +# whatever is in here can only be executed by one process +# end_service service +# fi +begin_service() +{ + [[ {$START_CRITICAL} == "yes" ]] && return 0 + + mkfifo "${svcdir}/exclusive/${service}" 2> /dev/null + return $? +} + +# void end_service(service, exitcode) +# +# stops executing a exclusive region and +# wakes up anybody who is waiting for the exclusive region +# +end_service() +{ + local service="$1" exitstatus="$2" + + # if we are doing critical services, there is no fifo + [[ ${START_CRITICAL} == "yes" ]] && return + + if [[ -n ${exitstatus} ]] ; then + echo "${exitstatus}" > "${svcdir}/exitcodes/${service}" + fi + + # move the fifo to a unique name so no-one is waiting for it + local fifo="${svcdir}/exclusive/${service}" + if [[ -e "${fifo}" ]]; then + local tempname="${fifo}.$$" + mv -f "${fifo}" "${tempname}" + + # wake up anybody that was waiting for the fifo + touch "${tempname}" + + # We dont need the fifo anymore + rm -f "${tempname}" + fi +} + +# int wait_service(service) +# +# If a service has started, or a fifo does not exist return 0 +# Otherwise, wait until we get an exit code via the fifo and return +# that instead. +wait_service() +{ + local service="$1" + local fifo="${svcdir}/exclusive/${service}" + + [[ ${START_CRITICAL} == "yes" || ${STOP_CRITICAL} == "yes" ]] && return 0 + [[ ! -e ${fifo} ]] && return 0 + + # This will block until the service fifo is touched + # Otheriwse we don't block + local tmp=$( < "${fifo}" &>/dev/null ) + local exitstatus=$( < "${svcdir}/exitcodes/${service}" ) + + return "${exitstatus}" +} + +# int start_service(service) +# +# Start 'service' if it is not already running. +# +start_service() { + local service="$1" + [[ -z ${service} ]] && return 1 + + if [[ ! -e "/etc/init.d/${service}" ]]; then + mark_service_stopped "${service}" + return 1 + fi + + service_starting "${service}" && return 0 + service_started "${service}" && return 0 + service_inactive "${service}" && return 1 + + if is_fake_service "${service}" "${SOFTLEVEL}" ; then + mark_service_started "${service}" + splash "svc_start" "${service}" + splash "svc_started" "${service}" "0" + return 0 + fi + + begin_service "${service}" || return 0 + splash "svc_start" "${service}" + if [[ ${RC_PARALLEL_STARTUP} != "yes" \ + || ${START_CRITICAL} == "yes" ]] ; then + # if we can not start the services in parallel + # then just start it and return the exit status + ( "/etc/init.d/${service}" start ) + retval="$?" + splash "svc_started" "${service}" "${retval}" + end_service "${service}" "${retval}" + return "${retval}" + else + # if parallel startup is allowed, start it in background + ( + "/etc/init.d/${service}" start + retval="$?" + splash "svc_started" "${service}" "${retval}" + end_service "${service}" "${retval}" + ) & + return 0 + fi +} + +# int stop_service(service) +# +# Stop 'service' if it is not already running. +# +stop_service() { + local service="$1" + [[ -z ${service} ]] && return 1 + + if [[ ! -e "/etc/init.d/${service}" ]]; then + mark_service_stopped "${service}" + return 0 + fi + + service_stopping "${service}" && return 0 + service_stopped "${service}" && return 0 + + local level="${SOFTLEVEL}" + is_runlevel_stop && level="${OLDSOFTLEVEL}" + + if is_fake_service "${service}" "${level}" ; then + splash "svc_stop" "${service}" + mark_service_stopped "${service}" + splash "svc_stopped" "${service}" "0" + return 0 + fi + + begin_service "${service}" || return 0 + + splash "svc_stop" "${service}" + if [[ ${RC_PARALLEL_STARTUP} != "yes" \ + || ${STOP_CRITICAL} == "yes" ]] ; then + # if we can not start the services in parallel + # then just start it and return the exit status + ( "/etc/init.d/${service}" stop ) + retval="$?" + splash "svc_stopped" "${service}" "${retval}" + end_service "${service}" "${retval}" + return "${retval}" + else + # if parallel startup is allowed, start it in background + ( + ( "/etc/init.d/${service}" stop ) + retval="$?" + splash "svc_stopped" "${service}" "${retval}" + end_service "${service}" "${retval}" + ) & + return 0 + fi +} + +# bool mark_service_starting(service) +# +# Mark 'service' as starting. +# +mark_service_starting() { + [[ -z $1 ]] && return 1 + + ln -snf "/etc/init.d/$1" "${svcdir}/starting/$1" + local retval=$? + + [[ -f "${svcdir}/started/$1" ]] && rm -f "${svcdir}/started/$1" + [[ -f "${svcdir}/inactive/$1" ]] && rm -f "${svcdir}/inactive/$1" + [[ -f "${svcdir}/stopping/$1" ]] && rm -f "${svcdir}/stopping/$1" + + return "${retval}" +} + +# bool mark_service_started(service) +# +# Mark 'service' as started. +# +mark_service_started() { + [[ -z $1 ]] && return 1 + + ln -snf "/etc/init.d/$1" "${svcdir}/started/$1" + local retval="$?" + + [[ -f "${svcdir}/starting/$1" ]] && rm -f "${svcdir}/starting/$1" + [[ -f "${svcdir}/inactive/$1" ]] && rm -f "${svcdir}/inactive/$1" + [[ -f "${svcdir}/stopping/$1" ]] && rm -f "${svcdir}/stopping/$1" + + return "${retval}" +} + +# bool mark_service_inactive(service) +# +# Mark service as inactive +# +mark_service_inactive() { + [[ -z $1 ]] && return 1 + + ln -snf "/etc/init.d/$1" "${svcdir}/inactive/$1" + local retval="$?" + [[ -f "${svcdir}/started/$1" ]] && rm -f "${svcdir}/started/$1" + [[ -f "${svcdir}/starting/$1" ]] && rm -f "${svcdir}/starting/$1" + [[ -f "${svcdir}/stopping/$1" ]] && rm -f "${svcdir}/stopping/$1" + + return "${retval}" +} + +# bool mark_service_stopping(service) +# +# Mark 'service' as stopping. +# +mark_service_stopping() { + [[ -z $1 ]] && return 1 + + ln -snf "/etc/init.d/$1" "${svcdir}/stopping/$1" + local retval="$?" + + [ -f "${svcdir}/starting/$1" ] && rm -f "${svcdir}/starting/$1" + [ -f "${svcdir}/started/$1" ] && rm -f "${svcdir}/started/$1" + [ -f "${svcdir}/inactive/$1" ] && rm -f "${svcdir}/inactive/$1" + + return "${retval}" +} + +# bool mark_service_stopped(service) +# +# Mark 'service' as stopped. +# +mark_service_stopped() { + [[ -z $1 ]] && return 1 + + [[ -f "${svcdir}/starting/$1" ]] && rm -f "${svcdir}/starting/$1" + [[ -f "${svcdir}/started/$1" ]] && rm -f "${svcdir}/started/$1" + [[ -f "${svcdir}/inactive/$1" ]] && rm -f "${svcdir}/inactive/$1" + [[ -f "${svcdir}/stopping/$1" ]] && rm -f "${svcdir}/stopping/$1" + + return $? +} + +# bool test_service_state(char *service, char *state) +# +# Returns 0 if the service link exists and points to a file, otherwise 1 +# If 1 then the link is erased if it exists +test_service_state() { + [[ -z $1 || -z $2 ]] && return 1 + + local f="${svcdir}/$2/$1" + + # Service is in the state requested + [[ -L ${f} ]] && return 0 + + if [[ ! -e ${f} ]]; then + rm -f "${f}" + return 1 + fi + + return 0 +} + +# bool service_starting(service) +# +# Returns true if 'service' is starting +# +service_starting() { + test_service_state "$1" "starting" +} + +# bool service_started(service) +# +# Returns true if 'service' is started +# +service_started() { + test_service_state "$1" "started" +} + +# bool service_inactive(service) +# +# Returns true if 'service' is inactive +# +service_inactive() { + test_service_state "$1" "inactive" +} + +# bool service_stopping(service) +# +# Returns true if 'service' is stopping +# +service_stopping() { + test_service_state "$1" "stopping" +} + +# bool service_stopped(service) +# +# Returns true if 'service' is stopped +# +service_stopped() { + [[ -z $1 ]] && return 1 + + service_starting "$1" && return 1 + service_started "$1" && return 1 + service_stopping "$1" && return 1 + service_inactive "$1" && return 1 + + return 0 +} + +# bool mark_service_failed(service) +# +# Mark service as failed for current runlevel. Note that +# this is only valid on runlevel change ... +# +mark_service_failed() { + [[ -z $1 || ! -d "${svcdir}/failed" ]] && return 1 + + ln -snf "/etc/init.d/$1" "${svcdir}/failed/$1" +} + +# bool service_failed(service) +# +# Return true if 'service' have failed during this runlevel. +# +service_failed() { + [[ -n $1 && -L "${svcdir}/failed/$1" ]] +} + +# bool net_service(service) +# +# Returns true if 'service' is a service controlling a network interface +# +net_service() { + [[ -n $1 && ${1%%.*} == "net" && ${1##*.} != $1 ]] +} + +# bool is_net_up() +# +# Return true if service 'net' is considered up, else false. +# +# Notes for RC_NET_STRICT_CHECKING values: +# none net is up without checking anything - usefull for vservers +# lo Interface 'lo' is counted and if only it is up, net is up. +# no Interface 'lo' is not counted, and net is down even with it up, +# so there have to be at least one other interface up. +# yes All interfaces must be up. +is_net_up() { + local netcount=0 + + case "${RC_NET_STRICT_CHECKING}" in + none) + return 0 + ;; + lo) + netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \ + egrep -c "\/net\..*$")" + ;; + *) + netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \ + grep -v 'net\.lo' | egrep -c "\/net\..*$")" + ;; + esac + + # Only worry about net.* services if this is the last one running, + # or if RC_NET_STRICT_CHECKING is set ... + if [ "${netcount}" -lt 1 -o "${RC_NET_STRICT_CHECKING}" = "yes" ] + then + return 1 + fi + + return 0 +} + +# bool dependon(service1, service2) +# +# Does service1 depend (NEED or USE) on service2 ? +# +dependon() { + ineed -t "$1" "$2" || iuse -t "$1" "$2" +} + +# string validi(use/after, service) +# +# This is the main code for valid_after and valid_iuse +# No point in writing it twice! +valid_i() { + local x + # Just set to dummy for now (don't know if $svcdir/softlevel exists yet). + local mylevel=${BOOTLEVEL} + + [[ $1 != "after" && $1 != "use" ]] && return 1 + + # Cannot be SOFTLEVEL, as we need to know current runlevel + [[ -f ${svcdir}/softlevel ]] && mylevel=$( < "${svcdir}/softlevel" ) + + for x in $( i$1 "$2" ) + do + [[ -e "/etc/runlevels/${BOOTLEVEL}/${x}" \ + || -e "/etc/runlevels/${mylevel}/${x}" \ + || ${x} == "net" ]] \ + && echo "${x}" + done + + return 0 +} + +# string valid_iuse(service) +# +# This will only give the valid use's for the service +# (they must be in the boot or current runlevel) +# +valid_iuse() { + valid_i "use" "$1" +} + +#string valid_iafter(service) +# +# Valid services for current or boot rc level that should start +# before 'service' +# +valid_iafter() { + valid_i "after" "$1" +} + +# string trace_dependencies(service[s]) +# +# Get and sort the dependencies of given service[s]. +# +trace_dependencies() { + local -a services=( "$@" ) deps + local i j + + if [[ $1 == -* ]]; then + deptype="${1/-}" + if net_service "${myservice}" ; then + services=( "net" "${myservice}" ) + else + services=( "${myservice}" ) + fi + fi + + # If its a net service, just replace it with 'net' + if [[ -z ${deptype} ]] ; then + for (( i=0; i<${#services[@]} ; i++ )) ; do + net_service "${services[i]}" && services[i]="net" + done + fi + + sort_unique() { + set -- " ${@/%/\n}" + echo -e "$@" | sort -u + } + + local last="" + while [[ ${services[@]} != "${last}" ]]; do + last="${services[*]}" + for (( i=0; i<${#services[@]}; i++ )); do + if [[ -n ${deptype} ]] ; then + deps=( "${deps[@]}" $( "${deptype}" "${services[i]}" ) ) + else + ndeps=( + $( ineed "${services[i]}" ) + $( valid_iuse "${services[i]}" ) + ) + + if is_runlevel_start || is_runlevel_stop ; then + ndeps=( "${ndeps[@]}" $( valid_iafter "${services[i]}" ) ) + fi + + #If its a net service, just replace it with 'net' + for (( j=0; j<${#ndeps[*]}; j++ )) ; do + net_service "${ndeps[j]}" && ndeps[j]="net" + done + + deps=( "${deps[@]}" "${ndeps[@]}" ) + fi + done + services=( $(sort_unique ${services[@]} ${deps[@]}) ) + done + + # Now, we sort our services + # When a service is first visited, we mark it dead and then + # revisit any dependencies. Finally we add ourselves to the sorted list. + # This should never get into an infinite loop, thanks to our dead array. + local -a dead=() deadname=() sorted=() + for (( i=0; i<${#services[@]}; i++ )); do + dead[i]=false; + deadname[i]="${services[i]}" + done + + after_visit() { + local service="$1" i + + for (( i=0; i<${#deadname[@]}; i++)); do + [[ ${service} == ${deadname[i]} ]] && break + done + + ${dead[i]} && return + dead[i]=true + + local x deps="$( ineed ${service} ) $( valid_iuse ${service} )" + if is_runlevel_start || is_runlevel_stop ; then + deps="${deps} $( valid_iafter ${service} )" + fi + + if [[ -z ${deptype} ]] ; then + # If its a net service, just replace it with 'net' + for (( j=0; j<${#deps[@]}; j++ )) ; do + net_service "${deps[j]}" && deps[j]="net" + done + fi + + for x in ${deps}; do + after_visit "${x}" + done + + sorted=( "${sorted[@]}" "${service}" ) + } + + for (( i=0; i<${#services[*]}; i++ )); do + after_visit "${services[i]}" + done + services=( "${sorted[@]}" ) + + if [[ -n ${deptype} ]] ; then + # If deptype is set, we do not want the name of this service + x=" ${services[@]} " + services=( ${x// ${myservice} / } ) + + # If its a net service, do not include "net" + if net_service "${myservice}" ; then + x=" ${services[@]} " + sorted=( ${services// net / } ) + fi + else + local netserv y + + # XXX: I dont think RC_NET_STRICT_CHECKING should be considered + # here, but you never know ... + netserv=$( cd "${svcdir}"/started; ls net.* 2>/dev/null ) + + get_netservices() { + local runlevel="$1" + + if [[ -d "/etc/runlevels/${runlevel}" ]] ; then + cd "/etc/runlevels/${runlevel}" + ls net.* 2>/dev/null + fi + } + + # If no net services are running or we only have net.lo up, then + # assume we are in boot runlevel or starting a new runlevel + if [[ -z ${netserv} || ${netserv} == "net.lo" ]]; then + local mylevel="${BOOTLEVEL}" + local startnetserv=$( get_netservices "${mylevel}" ) + + [[ -f "${svcdir}/softlevel" ]] && mylevel=$( < "${svcdir}/softlevel" ) + [[ ${BOOTLEVEL} != ${mylevel} ]] && \ + startnetserv="${startnetserv} $( get_netservices "${mylevel}" )" + [[ -n ${startnetserv} ]] && netserv="${startnetserv}" + fi + + # Replace 'net' with the actual net services + x=" ${services[@]} " + services=( ${x// net / ${netserv} } ) + fi + + echo "${services[@]}" +} + +# bool query_before(service1, service2) +# +# Return true if 'service2' should be started *before* +# service1. +# +query_before() { + local x list + local netservice="no" + + [[ -z $1 || -z $2 ]] && return 1 + + list=$( trace_dependencies "$1" ) + + net_service "$2" && netservice="yes" + + for x in ${list} ; do + [[ ${x} == "$2" ]] && return 0 + + # Also match "net" if this is a network service ... + [[ ${netservice} == "yes" && ${x} == "net" ]] && return 0 + done + + return 1 +} + +# vim:ts=4 diff --git a/sbin/rc-update b/sbin/rc-update new file mode 100755 index 0000000..b13e406 --- /dev/null +++ b/sbin/rc-update @@ -0,0 +1,162 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +source /sbin/functions.sh +if [[ ${EUID} -ne 0 ]] ; then + eerror "$0: must be root." + exit 1 +fi + +usage() { +cat << FOO +usage: rc-update -a|add script runlevel2 [runlevel2 ...] + rc-update -d|del script [runlevel1 ...] + rc-update -s|show [runlevel1 ...] + +examples: + # rc-update add net.eth0 default + Adds the net.eth0 script (in /etc/init.d) to the "default" runlevel. + + # rc-update del sysklogd + Deletes the sysklogd script from all runlevels. The original script + is not deleted, just any symlinks to the script in /etc/runlevels/*. + + # rc-update del net.eth2 default wumpus + Delete the net.eth2 script from the default and wumpus runlevels. + All other runlevels are unaffected. Again, the net.eth2 script + residing in /etc/init.d is not deleted, just any symlinks in + /etc/runlevels/default and /etc/runlevels/wumpus. + + # rc-update show + Show all the available scripts and list at which runlevels they + will execute. +FOO + exit 1 +} + +add() { + local x= + local myscript= + + if [[ $# -lt 3 ]] ; then + eerror "${0}: at least two arguments expected after \"$1\"." + exit 1 + fi + shift + myscript="$1" + if [[ ! -e /etc/init.d/${myscript} ]] ; then + eerror "$0: /etc/init.d/${myscript} not found; aborting." + exit 1 + fi + shift + for x in $* ; do + if [[ ! -e /etc/runlevels/${x} ]] ; then + ewarn "runlevel ${x} not found; skipping" + continue + fi + if [[ -L /etc/runlevels/${x}/${myscript} ]] ; then + ewarn "${myscript} already installed in runlevel ${x}; skipping" + continue + fi + if [[ ! -x /etc/init.d/${myscript} ]] ; then + ewarn "${myscript} not executable; skipping" + continue + fi + ln -snf "/etc/init.d/${myscript}" "/etc/runlevels/${x}/${myscript}" + if [[ $? -ne 0 ]] ; then + eerror "$0: failed to add ${myscript} to ${x}." + exit 1 + fi + regen=1 + einfo "${myscript} added to runlevel ${x}" + done +} + +del() { + local x= + local mylevels= + local myscript= + local remlevels= + + if [[ $# -lt 2 ]] ; then + eerror "$0: at least one argument expected after \"$1\"." + exit 1 + fi + shift + myscript=$1 + shift + if [[ $# -eq 0 ]] ; then + mylevels=$(cd /etc/runlevels/; ls) + else + mylevels="$*" + fi + remlevels="" + for x in ${mylevels} ; do + if [[ -L /etc/runlevels/${x}/${myscript} ]] ; then + regen=1 + rm -f "/etc/runlevels/${x}/${myscript}" + remlevels="${remlevels} ${x}" + fi + done + if [[ -z ${remlevels} ]] ; then + einfo "${myscript} not found in any of the specified runlevels." + else + einfo "${myscript} removed from the following runlevels:${remlevels}" + fi +} + +show() { + local x= + local y= + local mylevels= + local myscripts= + + shift + if [[ $# -eq 0 ]] ; then + mylevels=$(cd /etc/runlevels/; ls) + else + mylevels="$*" + fi + myscripts=$(cd /etc/init.d; ls) + + for x in ${myscripts} ; do + if [[ ${x%%.sh} = "${x}" ]] ; then + printf "%20s | " ${x:0:19} + for y in ${mylevels} ; do + if [[ -L /etc/runlevels/${y}/${x} ]] ; then + echo -n "${y} " + else + printf "%${#y}s " " " + fi + done + echo "" + fi + done +} + +if [[ $# -lt 1 ]] ; then + usage + exit 1 +fi + +regen=0 + +case "$1" in + add|-a) + add "$@" + ;; + del|delete|-d) + del "$@" + ;; + show|-s) + show "$@" + ;; + *) + usage + exit 1 + ;; +esac + + +# vim:ts=4 diff --git a/sbin/runscript.sh b/sbin/runscript.sh new file mode 100755 index 0000000..0c13372 --- /dev/null +++ b/sbin/runscript.sh @@ -0,0 +1,581 @@ +#!/bin/bash +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# Common functions +[[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh +# Functions to handle dependencies and services +[[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh" +# Functions to control daemons +[[ ${RC_GOT_DAEMON} != "yes" ]] && source "${svclib}/sh/rc-daemon.sh" + +# User must be root to run most script stuff (except status) +if [[ ${EUID} != 0 ]] && ! [[ $2 == "status" && $# -eq 2 ]] ; then + eerror "$0: must be root to run init scripts" + exit 1 +fi + +# State variables +svcpause="no" +svcrestart="no" + +myscript=$1 +if [[ -L $1 ]] && [[ ! -L /etc/init.d/${1##*/} ]] ; then + myservice=$(readlink "$1") +else + myservice=$1 +fi + +myservice=${myservice##*/} +export SVCNAME=${myservice} +mylevel=$(<"${svcdir}/softlevel") + +# Set $IFACE to the name of the network interface if it is a 'net.*' script +if [[ ${myservice%%.*} == "net" ]] && [[ ${myservice##*.} != ${myservice} ]] ; then + IFACE=${myservice##*.} + NETSERVICE="yes" +else + IFACE= + NETSERVICE= +fi + +# Source configuration files. +# (1) Source /etc/conf.d/${myservice} to get initscript-specific +# configuration (if it exists). +# (2) Source /etc/conf.d/net if it is a net.* service +# (3) Source /etc/rc.conf to pick up potentially overriding +# configuration, if the system administrator chose to put it +# there (if it exists). + +[[ -e $(add_suffix /etc/conf.d/${myservice}) ]] && source "$(add_suffix /etc/conf.d/${myservice})" +[[ -e $(add_suffix /etc/conf.d/net) ]] && \ +[[ ${NETSERVICE} == "yes" ]] && source "$(add_suffix /etc/conf.d/net)" +[[ -e $(add_suffix /etc/rc.conf) ]] && source "$(add_suffix /etc/rc.conf)" + +usage() { + local IFS="|" + myline="Usage: ${myservice} { $* " + echo + eerror "${myline}}" + eerror " ${myservice} without arguments for full help" +} + +stop() { + # Return success so the symlink gets removed + return 0 +} + +start() { + eerror "ERROR: \"${myservice}\" does not have a start function." + # Return failure so the symlink doesn't get created + return 1 +} + +restart() { + svc_restart || return $? +} + +status() { + # Dummy function + return 0 +} + +svc_stop() { + local x= + local mydep= + local mydeps= + local retval=0 + local ordservice= + local was_inactive=false + + if service_stopping "${myservice}" ; then + eerror "ERROR: \"${myservice}\" is already stopping." + return 0 + elif service_stopped "${myservice}" ; then + eerror "ERROR: \"${myservice}\" has not yet been started." + return 0 + fi + + # Do not try to stop if it had already failed to do so on runlevel change + if is_runlevel_stop && service_failed "${myservice}" ; then + return 1 + fi + + service_inactive "${myservice}" && was_inactive=true + + # Remove symlink to prevent recursion + mark_service_stopping "${myservice}" + + service_message "Stopping service ${myservice}" + + if in_runlevel "${myservice}" "${BOOTLEVEL}" && \ + [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" && \ + ${SOFTLEVEL} != "single" ]] + then + ewarn "WARNING: you are stopping a boot service." + fi + + if [[ ${svcpause} != "yes" ]] ; then + if [[ ${NETSERVICE} == "yes" ]] ; then + # A net.* service + if in_runlevel "${myservice}" "${BOOTLEVEL}" || \ + in_runlevel "${myservice}" "${mylevel}" + then + # Only worry about net.* services if this is the last one running, + # or if RC_NET_STRICT_CHECKING is set ... + if ! is_net_up ; then + mydeps="net" + fi + fi + + mydeps="${mydeps} ${myservice}" + else + mydeps=${myservice} + fi + fi + + # Save the IN_BACKGROUND var as we need to clear it for stopping depends + local ib_save="${IN_BACKGROUND}" + unset IN_BACKGROUND + local -a servicelist=() index=0 + + for mydep in ${mydeps} ; do + # If some service 'need' $mydep, stop it first; or if it is a runlevel change, + # first stop all services that is started 'after' $mydep. + if needsme "${mydep}" >/dev/null || \ + (is_runlevel_stop && ibefore "${mydep}" >/dev/null) + then + local -a sl=( $(needsme "${mydep}") ) + + # On runlevel change, stop all services "after $mydep" first ... + if is_runlevel_stop ; then + sl=( "${sl[@]}" $(ibefore "${mydep}") ) + fi + + local z="${#sl[@]}" + for (( x=0; x<z; x++ )); do + # Service not currently running, continue + if ! service_started "${sl[x]}" ; then + unset sl[x] + continue + fi + + if ibefore -t "${mydep}" "${x}" >/dev/null && \ + [[ -L ${svcdir}/softscripts.new/${x} ]] + then + # Service do not 'need' $mydep, and is still present in + # new runlevel ... + unset sl[x] + continue + fi + + stop_service "${sl[x]}" + done + fi + servicelist[index]="${sl[index]}" + (( index++ )) + done + + index=0 + for mydep in ${mydeps} ; do + for x in ${servicelist[index]} ; do + service_stopped "${x}" && continue + + if ibefore -t "${mydep}" "${x}" >/dev/null && \ + [[ -L "${svcdir}/softscripts.new/${x}" ]] + then + # Service do not 'need' $mydep, and is still present in + # new runlevel ... + continue + fi + + wait_service "${x}" + + if ! service_stopped "${x}" ; then + # If we are halting the system, try and get it down as + # clean as possible, else do not stop our service if + # a dependent service did not stop. + if needsme -t "${mydep}" "${x}" >/dev/null && \ + [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] + then + retval=1 + fi + break + fi + done + (( index++ )) + done + + IN_BACKGROUND="${ib_save}" + + if [[ ${retval} -ne 0 ]] ; then + eerror "ERROR: problems stopping dependent services." + eerror " \"${myservice}\" is still up." + else + # Stop einfo/ebegin/eend from working as parallel messes us up + [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes" + # Now that deps are stopped, stop our service + ( stop ) + retval=$? + + # If a service has been marked inactive, exit now as something + # may attempt to start it again later + service_inactive "${myservice}" && return 0 + fi + + if [[ ${retval} -ne 0 ]] ; then + # Did we fail to stop? create symlink to stop multible attempts at + # runlevel change. Note this is only used at runlevel change ... + if is_runlevel_stop ; then + mark_service_failed "${myservice}" + fi + + # If we are halting the system, do it as cleanly as possible + if [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then + if ${was_inactive} ; then + mark_service_inactive "${myservice}" + else + mark_service_started "${myservice}" + fi + fi + + service_message "eerror" "FAILED to stop service ${myservice}!" + else + # If we're stopped from a daemon that sets ${IN_BACKGROUND} such as + # wpa_monitor when we mark as inactive instead of taking the down + if ${IN_BACKGROUND:-false} ; then + mark_service_inactive "${myservice}" + else + mark_service_stopped "${myservice}" + fi + service_message "Stopped service ${myservice}" + fi + + return "${retval}" +} + +svc_start() { + local retval=0 + local startfail="no" + local x= + local y= + local myserv= + local ordservice= + + if service_starting "${myservice}" ; then + ewarn "WARNING: \"${myservice}\" is already starting." + return 0 + elif service_stopping "${myservice}" ; then + ewarn "WARNING: please wait for \"${myservice}\" to stop first." + return 0 + elif service_inactive "${myservice}" ; then + if [[ ${IN_BACKGROUND} != "true" ]] ; then + ewarn "WARNING: \"${myservice}\" has already been started." + return 0 + fi + elif service_started "${myservice}" ; then + ewarn "WARNING: \"${myservice}\" has already been started." + return 0 + fi + + # Do not try to start if i have done so already on runlevel change + if is_runlevel_start && service_failed "${myservice}" ; then + return 1 + fi + + mark_service_starting "${myservice}" + service_message "Starting service ${myservice}" + + # On rc change, start all services "before $myservice" first + if is_runlevel_start ; then + startupservices="$(ineed "${myservice}") \ + $(valid_iuse "${myservice}") \ + $(valid_iafter "${myservice}")" + else + startupservices="$(ineed "${myservice}") \ + $(valid_iuse "${myservice}")" + fi + + # Start dependencies, if any + for x in ${startupservices} ; do + if [[ ${x} == "net" ]] && [[ ${NETSERVICE} != "yes" ]] && ! is_net_up ; then + local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \ + $(dolisting "/etc/runlevels/${mylevel}/net.*")" + + for y in ${netservices} ; do + mynetservice=${y##*/} + if service_stopped "${mynetservice}" ; then + start_service "${mynetservice}" + fi + done + elif [[ ${x} != "net" ]] ; then + if service_stopped "${x}"; then + start_service "${x}" + fi + fi + done + + # wait for dependencies to finish + for x in ${startupservices} ; do + if [ "${x}" = "net" -a "${NETSERVICE}" != "yes" ] ; then + local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \ + $(dolisting "/etc/runlevels/${mylevel}/net.*")" + + for y in ${netservices} ; do + mynetservice="${y##*/}" + + wait_service "${mynetservice}" + + if ! service_started "${mynetservice}" ; then + # A 'need' dependency is critical for startup + if ineed -t "${myservice}" "${x}" >/dev/null ; then + # Only worry about a net.* service if we do not have one + # up and running already, or if RC_NET_STRICT_CHECKING + # is set .... + if ! is_net_up ; then + startfail="yes" + fi + fi + fi + done + elif [ "${x}" != "net" ] ; then + wait_service "${x}" + if ! service_started "${x}" ; then + # A 'need' dependacy is critical for startup + if ineed -t "${myservice}" "${x}" >/dev/null ; then + startfail="yes" + fi + fi + fi + done + + if [[ ${startfail} == "yes" ]] ; then + eerror "ERROR: Problem starting needed services." + eerror " \"${myservice}\" was not started." + retval=1 + elif broken "${myservice}" ; then + eerror "ERROR: Some services needed are missing. Run" + eerror " './${myservice} broken' for a list of those" + eerror " services. \"${myservice}\" was not started." + retval=1 + else + ( + exit() { + RC_QUIET_STDOUT="no" + eerror "DO NOT USE EXIT IN INIT.D SCRIPTS" + eerror "This IS a bug, please fix your broken init.d" + unset -f exit + exit $@ + } + # Stop einfo/ebegin/eend from working as parallel messes us up + [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes" + start + ) + retval=$? + + # If a service has been marked inactive, exit now as something + # may attempt to start it again later + service_inactive "${myservice}" && return 1 + fi + + if [[ ${retval} != 0 ]]; then + is_runlevel_start && mark_service_failed "${myservice}" + + # Remove link if service didn't start; but only if we're not booting + # If we're booting, we need to continue and do our best to get the + # system up. + if [[ ${SOFTLEVEL} != "${BOOTLEVEL}" ]]; then + mark_service_stopped "${myservice}" + fi + + service_message "eerror" "FAILED to start service ${myservice}!" + else + mark_service_started "${myservice}" + + service_message "Service ${myservice} started OK" + fi + + return "${retval}" +} + +svc_restart() { + if ! service_stopped "${myservice}" ; then + svc_stop || return "$?" + fi + svc_start || return "$?" +} + +svc_status() { + # The basic idea here is to have some sort of consistent + # output in the status() function which scripts can use + # as an generic means to detect status. Any other output + # should thus be formatted in the custom status() function + # to work with the printed " * status: foo". + local efunc="" state="" + + # If we are effectively root, check to see if required daemons are running + # and update our status accordingly + [[ ${EUID} == 0 ]] && update_service_status "${myservice}" + + if service_starting "${myservice}" ; then + efunc="einfo" + state="starting" + elif service_inactive "${myservice}" ; then + efunc="ewarn" + state="inactive" + elif service_started "${myservice}" ; then + efunc="einfo" + state="started" + elif service_stopping "${myservice}" ; then + efunc="eerror" + state="stopping" + else + efunc="eerror" + state="stopped" + fi + [[ ${RC_QUIET_STDOUT} != "yes" ]] \ + && ${efunc} "status: ${state}" + + status + [[ ${efunc} != "eerror" ]] +} + +rcscript_errors=$(bash -n "${myscript}" 2>&1) || { + [[ -n ${rcscript_errors} ]] && echo "${rcscript_errors}" >&2 + eerror "ERROR: \"${myscript}\" has syntax errors in it; aborting ..." + exit 1 +} + +# set *after* wrap_rcscript, else we get duplicates. +opts="start stop restart" + +source "${myscript}" + +# make sure whe have valid $opts +if [[ -z ${opts} ]] ; then + opts="start stop restart" +fi + +svc_homegrown() { + local arg=$1 + local x= + + # Walk through the list of available options, looking for the + # requested one. + for x in ${opts} ; do + if [[ ${x} == ${arg} ]] ; then + if typeset -F "${x}" &>/dev/null ; then + # Run the homegrown function + "${x}" + + return $? + fi + fi + done + + # If we're here, then the function wasn't in $opts. + eerror "ERROR: wrong args. ( "${arg}" / $* )" + # Do not quote this either ... + usage ${opts} + exit 1 +} + +shift +if [[ $# -lt 1 ]] ; then + eerror "ERROR: not enough args." + usage ${opts} + exit 1 +fi +for arg in $* ; do + case "${arg}" in + --quiet) + RC_QUIET_STDOUT="yes" + ;; +# We check this in functions.sh ... +# --nocolor) +# RC_NOCOLOR="yes" +# ;; + --verbose) + RC_VERBOSE="yes" + ;; + esac +done +for arg in $* ; do + case "${arg}" in + stop) + svc_stop + ;; + start) + svc_start + ;; + needsme|ineed|usesme|iuse|broken) + trace_dependencies "-${arg}" + ;; + status) + svc_status + ;; + zap) + if ! service_stopped "${myservice}" ; then + einfo "Manually resetting ${myservice} to stopped state." + mark_service_stopped "${myservice}" + fi + ;; + restart) + svcrestart="yes" + + # Create a snapshot of started services + rm -rf "${svcdir}/snapshot/$$" + mkdir -p "${svcdir}/snapshot/$$" + cp -a "${svcdir}"/started/* "${svcdir}/snapshot/$$/" + + # Simple way to try and detect if the service use svc_{start,stop} + # to restart if it have a custom restart() funtion. + if [[ -n $(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}") ]] ; then + if [[ -z $(egrep 'svc_stop' "/etc/init.d/${myservice}") ]] || \ + [[ -z $(egrep 'svc_start' "/etc/init.d/${myservice}") ]] + then + echo + ewarn "Please use 'svc_stop; svc_start' and not 'stop; start' to" + ewarn "restart the service in its custom 'restart()' function." + ewarn "Run ${myservice} without arguments for more info." + echo + svc_restart + else + restart + fi + else + restart + fi + + # Restart dependencies as well + if service_started "${myservice}" ; then + for x in $(trace_dependencies \ + $(dolisting "${svcdir}/snapshot/$$/") ) ; do + if service_stopped "${x##*/}" ; then + start_service "${x##*/}" + fi + done + fi + + # Wait for any services that may still be running ... + [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait + + rm -rf "${svcdir}/snapshot/$$" + svcrestart="no" + ;; + pause) + svcpause="yes" + svc_stop + svcpause="no" + ;; + --quiet|--nocolor) + ;; + *) + # Allow for homegrown functions + svc_homegrown ${arg} + ;; + esac +done + + +# vim:ts=4 |