# Copyright (c) 2003..2006 - RZ Uni Freiburg # Copyright (c) 2006..2010 - OpenSLX GmbH # # This program/file is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your feedback to feedback@openslx.org # # General information about OpenSLX can be found under http://openslx.org # # configuration script for general SuSE to configure linux stateless clients # (included by init, hwautocfg, servconfig within InitialRamFS after # inclusion of the main functions file). This file is the main base for the # several SuSE distro versions # settings of central variables (formerly done via config-*, these variables # are disputable ...) # D_DIRINBINDMNT - lists of directories to be created in bind mounted rw # part of the client filesystem # D_RODIRSINRW - ReadOnly Directories in RW part of filesystem to save on # TempFS usage # D_DIRINDXS - directories in client filesystem which should be present # anyhow D_BINDMPTS="tmp root media home" D_DIRINBINDMNT="/var/run /var/log /var/tmp" D_RODIRSINRW="/etc/bootsplash /etc/gconf /etc/X11/xkb /var/adm /var/lib/texmf \ /var/lib/rpm /var/cache/fontconfig" D_DIRINDXS="/var/X11R6/compose-cache /var/run/sysconfig/tmp /var/adm \ /var/lib/rpm /var/lib/nobody /var/lib/pam_devperm /var/lib/bluetooth \ /var/lib/texmf /var/lib/nfs/sm /var/lib/nfs/sm.bak /var/lib/misc \ /var/lib/acpi /var/spool/cron /var/lock/subsys/sysconfig" # empty functions are defined at the beginning of /etc/functions # distro specific function called from servconfig script config_distro () { # clean the runlevel directories which will be populated by the stage3 setup for dir in rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d boot.d ; do rm -rf /mnt/etc/init.d/${dir}/* done rm -rf /mnt/etc/init.d/.depend.* touch /mnt/var/log/btmp touch /mnt/var/log/lastlog # link the additional key setup (notbook special keys) grep -q -E "otebook" /etc/hwinfo.bios && \ [ -e /mnt/etc/init.d/hotkey-setup ] && rllinker "hotkey-setup" 25 25 # no need to run start scripts in parallel # enable magic sysrequest for the clients sed -e "1i# /etc/sysconfig/sysctl - modified by $0 version $version" \ -e "s,ENABLE_SYSRQ=.*,ENABLE_SYSRQ=\"yes\"," \ -i /mnt/etc/sysconfig/sysctl # add slx specific path /var/opt/openslx/bin ... echo -e "# stuff generated by $0 (out of InitRamFS written $date)\n\ PATH=\"\$PATH:/var/opt/openslx/bin\"\n\ test \"\$UID\" -ge 100 && PATH=\"\$PATH:.\"\n\ QTDIR=/usr/lib/qt3\nexport QTDIR\nno_proxy='localhost'\n\ export no_proxy" >/mnt/etc/SuSEconfig/profile echo -e "SLX VERSION = $SLXVERSION\nINITRAMFS GENERATION DATE = $date" \ >>/mnt/etc/SuSE-release # remove annoying udev rule set for changing eth interface and rtc symlink rm /mnt/etc/udev/rules.d/*persistent-net.rules \ /mnt/etc/udev/rules.d/*net_persistent_names.rules >/dev/null 2>&1 sed '/SYMLINK+="rtc"/d' -i \ /mnt/etc/udev/rules.d/50-udev-default.rules >/dev/null 2>&1 # create a stateless specific halt script echo -e '#!/bin/sh\n# script generated in InitRamFS (SLX stage3) . /etc/rc.status\n trap "echo" SIGINT SIGSEGV SIGQUIT SIGTERM\nset +e\n\n case "$0" in\n\t*halt) \t message="The system will be halted immediately." \t command="halt -p"\n\t ;;\n\t*reboot)\n \t message="Please stand by while rebooting the system..." \t command="reboot"\n\t ;;\nesac\n rc_reset\ntest -e /etc/init.d/halt.local && { \techo Running /etc/init.d/halt.local\n\t/bin/sh /etc/init.d/halt.local \trc_status -v1 -r\n} echo $message\nexec $command -d -f' >/mnt/etc/init.d/halt # add the halt link to the 0 and 6 runlevel directories ln -sf ../halt /mnt/etc/init.d/rc0.d/S20halt ln -sf ../halt /mnt/etc/init.d/rc6.d/S20reboot echo "LOGFILE=${LOGFILE}" >/mnt/etc/sysconfig/logfile # fixme: rather ugly to write that boot script this way echo ' #!/bin/sh # SuSE specific initial boot file modified for the use with OpenSLX clients # ########################################################################### # Configuration and coloring of the boot messages . /etc/rc.status . /etc/sysconfig/boot . /etc/sysconfig/logfile # Avoid be interrupted by child or keyboard trap "echo" SIGINT SIGSEGV SIGQUIT set +e # reasonable start values for bootsplash progress export progress=0 export sscripts=45 export kscripts=45 echo -n "System Boot Control: " echo "Running $0" ########################################################################### # # some important (un)mounts rc_reset echo -n "Mounting /proc, /sys and /dev/pts filesystems" # file /etc/fstab in some scenarios not available mount -t proc proc /proc &>/dev/null rc_status -v -r echo -n "Mounting /dev/pts" mount -t devpts -o mode=0620,gid=5 devpts /dev/pts rc_status -v -r if [ -d /sys ] ; then while read a b c ; do case "$b" in sysfs) echo -n "Mounting /sys filesystem" echo -e "sysfs\t\t/sys\t\tsysfs\t\trw\t\t 0 0\n" \ >>/etc/fstab mount -t sysfs sysfs /sys rc_status -v -r break ;; esac done < /proc/filesystems fi # Start blogd, requires /proc and /dev/pts. # Export the real device in variable REDIRECT. test -x /sbin/blogd -a -n "$REDIRECT" && /sbin/blogd $REDIRECT if test -z "$REDIRECT" ; then if (echo -n > /dev/tty) 2>/dev/null ; then REDIRECT=/dev/tty else REDIRECT=/dev/console fi fi ########################################################################### # # Save old terminal settings and set -nl to avoid staircase # effect, do not lock scrolling, and avoid break characters. otty=$(stty -g) if test "$FLOW_CONTROL" = "yes" ; then stty -nl ixon ignbrk -brkint else stty -nl -ixon ignbrk -brkint fi ########################################################################### # # Common used variables bootrc=/etc/init.d/boot.d rex="[0-9][0-9]" failed="" skipped="" callord="" # # Initialize boosplash progressbar variables # . /etc/rc.splash B splashtrigger "rlchange B" ########################################################################### # # Do we stop/start script in parallel? startpar=$(type -p startpar) test "$RUN_PARALLEL" = "yes" || startpar="" # Start bootup client scripts. if test -d ${bootrc}/ ; then for i in ${bootrc}/S*; do test -f $i || continue B=${i##*/} script=${B#*S$rex} B=${B%$script} rc_splash "$script start" if test -z "$startpar" ; then blogger "$script start" if test -x "$i" ; then $i start else echo Running $i /bin/sh $i b rc_status -v1 -r fi status=$? echo -en "$rc_reset" case $status in [1-4]) failed="${failed:+$failed }$script" ;; [56]) skipped="${skipped:+$skipped }$script" ;; [07]|*) ;; esac blogger "$script start exits with status $status" else # Parallel boot only for valid scripts test -x $i || continue # Current vector eval cur=\${$B} test -n "$cur" || callord="${callord:+$callord }$B" # Remember scripts eval $B="\${cur:+$i }\${cur:-$i}" fi done fi ########################################################################### # # Call the scripts in correct order if test -n "$startpar" ; then declare -i s for p in $callord ; do vect=$p eval p=(\${$p}) blogger "run boot scripts (${p[@]##*S$rex})" if test ${#p[@]} -eq 1 ; then ${p} start status=($?) else status=($($startpar -t 30 -T 3 -a start ${p[@]})) fi echo -en "$rc_reset" blogger "exit status of (${p[@]##*S$rex}) is (${status[@]})" s=0 for script in ${p[@]##*S$rex} ; do case "${status[$s]}" in [1-4]) failed="${failed:+$failed }$script" ;; [56]) skipped="${skipped:+$skipped }$script" ;; 0|*) ;; esac : $((s++)) done done fi ########################################################################### # # Be verbose and print stats echo -n "System Boot Control: " echo -e "The system has been ${stat}${extd}set up${norm}" if test -n "$failed" ; then n=$((${#failed} + 7)) echo -n "Failed features: " test $n -lt 47 && echo -en "\033[${COLUMNS}C\033[${n}D" echo -e "${warn}${failed}${norm}" fi if test -n "$skipped" ; then n=$((${#skipped} + 7)) echo -n "Skipped features: " test $n -lt 47 && echo -en "\033[${COLUMNS}C\033[${n}D" echo -e "${attn}${skipped}${norm}" fi ########################################################################### # # Check for boot cycle detection test -s /lib/bootcycle/stats && . /lib/bootcycle/stats # Restore old terminal settings stty $otty ########################################################################### # # Let zic set timezone - if present (from boot.ldconfig). if test -n "$TIMEZONE" -a -x /usr/sbin/zic ; then echo -n Setting up timezone data /usr/sbin/zic -l $TIMEZONE rc_status -v -r fi ########################################################################### # # start user defined bootup script. if test -f /etc/init.d/boot.local ; then ECHO_RETURN=$rc_done_up echo "Running /etc/init.d/boot.local" /bin/sh /etc/init.d/boot.local || rc_failed rc_status -v1; rc_reset rc_splash "boot.local start" fi rc_reset exit 0' >/mnt/etc/init.d/boot ## end of initial stage4 boot script # enable execution of all important start scripts # running stuff in parallel seems to be rather useless and generates some # difficult to solve problems. If you want to try nevertheless enable the # following line and disable the latter one (switching off that feature) sed -e "s,RUN_PARALLEL=.*,RUN_PARALLEL=\"no\"," \ -i /mnt/etc/sysconfig/boot # if YaST2 should be runnable (without much effect anyway) on the client testmkd /mnt/var/log/YaST2 # for screen sessions testmkd /mnt/var/run/uscreens 4777 # set special SuSE HOSTNAME file echo "$host_name" > /mnt/etc/HOSTNAME # produce proper output formatting (of "done", "failed", ...) sed -e '/^test $LINES/ { i\ # Script modified here by \$0 during stage3 bootup\ LINECOL=$(stty size); LINES=${LINECOL% *}; COLUMNS=${LINECOL#* } }' -e "/^if test -z \"\$LINES/,/fi$/d" -i /mnt/etc/rc.status # check for inittab file test -f /mnt/etc/inittab || error "$df_erritab" } # initial (boot time) runlevel scripts initial_boot () { local scripts=$* local count=10 # check if /mnt/etc/init.d/boot.compcache aka ramzswap is available [ -f /mnt/etc/init.d/boot.compcache ] && COMPCACHE=boot.compcache # boot.slx is a special runlevel script generated within initialramfs which # should be executed before the normal runlevel scripts. Proper shutdown is # not needed!? for i in boot.udev boot.proc boot.klog boot.loadmodules boot.slx boot.clock \ boot.sysctl boot.ipconfig $COMPCACHE boot.swap $D_SPLASHY kbd; do count=$(($count + 1)) [ $DEBUGLEVEL -ge 2 ] && echo "boot-runlevelscript $i" ln -sf /etc/init.d/$i /mnt/etc/init.d/boot.d/S${count}$i done } # linking runlevel scripts rllinker () { local script="$1" if [ $2 -lt 10 ] ; then local start="0$2"; else local start="$2" fi if [ $3 -lt 10 ] ; then local stop="0$3"; else local stop="$3" fi # empty runlevel links - decision on running certain services is # passed via configuration for i in rc3.d/K$stop$script rc5.d/K$stop$script \ rc3.d/S$start$script rc5.d/S$start$script ; do ln -sf ../$script /mnt/etc/init.d/$i done } # group of functions for the normal runlevels - first parameter is start # second stop # function for ntp configuration config_ntp () { if [ -e /mnt/etc/init.d/ntp ] ; then if ! strinfile "ntp:" /mnt/etc/passwd ; then echo -e "ntp:x:74:65534:NTP daemon:/var/lib/ntp:/bin/false" \ >>/mnt/etc/passwd echo -e "ntp:!:13099:0:99999:7:::" >>/mnt/etc/shadow fi testmkd /mnt/var/lib/ntp/var/run/ntp if [ "x$start_ntp" = "xyes" ] ; then rllinker "ntp" 7 14 fi fi } # function for atd config_atd () { if [ "x$start_atd" = "xyes" ]; then rllinker "atd" 14 4 fi } # function for configuration of cron services config_cron () { if [ "x$start_cron" = "xyes" ] ; then if [ -f /mnt/etc/init.d/cron ] ; then rllinker "cron" 18 2 testmkd /mnt/var/spool/cron/lastrun testmkd /mnt/var/spool/cron/tabs echo -e "# /etc/crontab - file generated by $0:\n\ #\t$date\nSHELL=/bin/sh\nPATH=/usr/bin:/usr/sbin:/sbin:/bin:/usr/lib/news/bin\ \nMAILTO=\n-*/15 * * * *\troot\ttest -x /usr/lib/cron/run-crons && \ /usr/lib/cron/run-crons >/dev/null 2>&1" >/mnt/etc/crontab else error "$df_errcron" nonfatal fi fi } # name service caching daemon (useful in most cases) config_nscd () { if [ -f /mnt/etc/init.d/nscd ] ; then rllinker "nscd" 20 5 fi } # secure shell service config_sshd () { if [ "x$start_sshd" = "xyes" ] ; then if [ -f /mnt/etc/init.d/sshd ] ; then testmkd /mnt/var/run/sshd testmkd /mnt/var/lib/empty if ! strinfile "sshd:" /mnt/etc/passwd ; then echo -e "sshd:x:117:65534::/var/run/sshd:/usr/sbin/nologin" \ >>/mnt/etc/passwd echo -e "sshd:!:13099:0:99999:7:::" >>/mnt/etc/shadow fi # set permissions with userid #d_mkrlscript entry boot.slx "chown sshd:nogroup /var/run/sshd \ # /var/lib/empty 2>/dev/null" rllinker "sshd" 25 10 else error "$df_errsshd" nonfatal fi fi } # snmp agent for remote monitoring config_snmp () { if [ "x$start_snmp" = "xyes" ] ; then if [ -f /mnt/etc/init.d/snmpd ] ; then rllinker "snmpd" 24 2 testmkd /mnt/var/lib/net-snmp fi # fixme!! # write service monitor depending on services started fi } # configure print server (lpd or cups) config_printer () { if [ "x${start_printdaemon}" != "x" ] && \ [ "x${start_printdaemon}" != "xno" ]; then case ${start_printdaemon} in yes|cups*|CUPS*) rllinker "cups" 25 1 testmkd /mnt/var/spool/cups/tmp #chown -R lp:lp /var/spool/cups ;; lp*|LP*|PLP*) rllinker "lpd" 25 1 testmkd /mnt/var/spool/lpd #chown -R lp:lp /var/spool/lpd ;; *) #logwrite "Do not know print-server $start_printdaemon; \ #specify 'cups' or 'lpd'." ;; esac fi # configure cups printer client, avoid to overwrite admin provided printer # configuration file if [ "x$lpr_servers" != "x" ] && [ ! -e /rootfs/etc/cups/client.conf ] ; then echo -e "# /etc/cups/client.conf - file generated by\n#\t$0:\n\ #\t$date\n#\nServerName\t$lpr_servers" >/mnt/etc/cups/client.conf fi } # configure bluetooth services config_bt () { if [ -e /mnt/etc/sysconfig/bluetooth ] ; then sed -e "1i# /etc/sysconfig/bluetooth - file modified by $0" \ -e "s,START_SERVICES.*,START_SERVICES=\"yes\"," \ -i /mnt/etc/sysconfig/bluetooth else : # no bluetooth components installed fi } # set up localization like keytable and consolefont dlocale () { d_mkrlscript entry boot.slx "# entries added by $0: $date" sed -e "s,KEYTABLE=.*,KEYTABLE=\"${KEYTABLE}\"," \ -i /mnt/etc/sysconfig/keyboard d_mkrlscript entry boot.slx "#loadkeys ${KEYTABLE} >${LOGFILE} 2>&1" d_mkrlscript entry boot.slx "#setfont ${CONSOLE_FONT} >${LOGFILE} 2>&1" sed -e "s,RC_LANG=.*,RC_LANG=\"${LANG}\" # added in initrd," \ -i /mnt/etc/sysconfig/language } # acpi and powersave daemons, required e.g. to shutdown the machine via # power button, no need for early start config_acpi () { rllinker acpid 22 12 rllinker powersaved 23 11 # dbus is required to run acpid and powersaved start_dreshal="yes" } # configure dbus (inter application communication for kde and gnome), hal # (hardware abstraction layer - used e.g. by powersaved) and resmgr # (resource manager - the user gets permissions to devices when loggin on) # runlevel script for haldaemon is now haldaemon instead of hal config_dreshal () { local start=0 local stop=18 if [ "x$start_dreshal" = "xyes" ]; then for dir in /var/run/resmgr/classes /var/lib/PolicyKit; do testmkd /mnt/$dir done if [ -f /mnt/etc/init.d/dbus ] ; then strinfile "messagebus:" /mnt/etc/passwd || \ echo "messagebus:x:100:101:User for D-BUS:/var/run/dbus:/bin/false" \ >> /mnt/etc/passwd strinfile "messagebus:" /mnt/etc/group || \ echo "messagebus:!:101:" >> /mnt/etc/group # create directories and set permissions with user and group id testmkd /mnt/var/run/dbus messagebus:messagebus rllinker "dbus" $start $stop fi if [ -f /mnt/etc/init.d/consolekit ] ; then strinfile "polkituser:" /mnt/etc/passwd || \ echo "polkituser:x:104:106:PolicyKit:/var/run/PolicyKit:/bin/false" \ >> /mnt/etc/passwd start=$(($start + 1)) stop=$(($stop - 1)) rllinker "consolekit" $start $stop echo -n > /mnt/var/lib/misc/PolicyKit.reload chmod a+x /mnt/var/lib/misc/PolicyKit.reload fi if [ -f /mnt/etc/init.d/resmgr ] ; then start=$(($start + 1)) stop=$(($stop - 1)) rllinker "resmgr" $start $stop fi if [ -f /mnt/etc/init.d/haldaemon ] ; then strinfile "haldaemon:" /mnt/etc/passwd || \ echo "haldaemon:x:105:103:User for haldaemon:/var/run/hal:/bin/false" \ >> /mnt/etc/passwd strinfile "haldaemon:" /mnt/etc/group || \ echo "haldaemon:!:103:" >> /mnt/etc/group echo -n "" > /mnt/var/lib/PolicyKit.reload # create directories and set permissions with user and group id testmkd /mnt/var/run/hal haldaemon:haldaemon testmkd /mnt/var/cache/hald haldaemon:haldaemon start=$(($start + 1)) stop=$(($stop - 1)) rllinker "haldaemon" $start $stop fi fi } # configure automounter (fixme: to be moved into plugin) config_automount () { if [ -e /mnt/etc/sysconfig/autofs ] ; then testmkd /mnt/var/lock/subsys sed -e "1i# /etc/sysconfig/autofs - file modified by\n#\t$0:\n#" \ -e "s,AUTOFS_OPTIONS.*,AUTOFS_OPTIONS=\"--timeout 3\"," \ -i /mnt/etc/sysconfig/autofs rllinker "autofs" 18 4 # might be needed for autofs via NFS (start specific nfs related services) # echo 'NFS_START_SERVICES="no"' >>/mnt/etc/sysconfig/nfs else error "$df_erramt" nonfatal fi } # start name service caching daemon config_nscd () { if [ -e /mnt/etc/init.d/nscd ] ; then testmkd /mnt/var/run/nscd rllinker "nscd" 16 16 else error "$df_errnsc" nonfatal fi } # start portmapper (needed at least for nfs and nis services) config_portmap () { rllinker "portmap" 2 20 } # start NIS (mostly deprecated) config_nis () { if [ -f /mnt/etc/init.d/ypbind ] ; then rllinker "ypbind" 6 16 config_portmap testmkd /mnt/var/yp/nicknames else error "$df_erryp" nonfatal fi } # initialize runlevel skript to be executed during system startup # (before most of the normal boot init scripts) # this script should operate like a normal runlevel script d_mkrlscript () { local switch="$1" local name="$2" local info="$3" case "$1" in init) echo -e "#!/bin/sh\n# skeleton of /etc/init.d/${name} created \ by $0\n# after you applied changes to the creation scripts you have to \ rerun\n# the mkdxsinitrd script to get them applied\n\ . /etc/rc.status\n. /etc/sysconfig/logfile\nrc_reset\ncase \ \"\$1\" in\n start)\n\techo -n \"$info\"" >>/mnt/etc/init.d/${name} chmod u+x /mnt/etc/init.d/${name} touch /mnt/etc/sysconfig/logfile ;; entry) echo -e "\t${info}" >>/mnt/etc/init.d/${name} ;; close) echo -e "\trc_status -v\n\t;;\n stop)\n\t;;\nesac\nrc_exit" \ >>/mnt/etc/init.d/${name} ;; esac }