92468fb58d2e031a177eae7013efa768da17376c
[grml-autoconfig.git] / autoconfig.functions
1 #!/bin/zsh
2 # Filename:      autoconfig.functions
3 # Purpose:       basic system configuration and hardware setup for grml system
4 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 ################################################################################
8
9 # {{{ path, variables, signals, umask, zsh
10 export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin"
11 DEBUG="/dev/null"
12 KERNEL="$(uname -r)"
13 ARCH="$(uname -m)"
14 umask 022
15
16 # old linuxrc version:
17 [ -d /cdrom ]      && export LIVECD_PATH=/cdrom
18 # new initramfs layout:
19 [ -d /live/image ] && export LIVECD_PATH=/live/image
20
21 # Ignore these signals in non-interactive mode: INT, TERM, SEGV
22 [ -z "$PS1" ] && trap "" 2 3 11
23
24 # zsh stuff
25 iszsh(){
26 if [ -n "$ZSH_VERSION" ] ; then
27   return 0
28 else
29   return 1
30 fi
31 }
32 # avoid 'no matches found: ...'
33 iszsh && setopt no_nomatch # || echo "Warning: not running under zsh!"
34 # }}}
35
36 # {{{ Read in boot parameters
37 if [ -z "$CMDLINE" ]; then
38   # if CMDLINE was set from the outside, we're debugging.
39   # otherwise, take CMDLINE from Kernel and config files.
40   CMDLINE="$(cat /proc/cmdline)"
41   [ -d /cdrom/bootparams/ ]      && CMDLINE="$CMDLINE $(cat /cdrom/bootparams/* | tr '\n' ' ')"
42   [ -d /live/image/bootparams/ ] && CMDLINE="$CMDLINE $(cat /live/image/bootparams/* | tr '\n' ' ')"
43 fi
44 # }}}
45
46 ### {{{ Utility Functions
47
48 # Get a bootoption's parameter: read boot command line and either
49 # echo last parameter's argument or return false.
50 getbootparam(){
51   local line
52   local ws
53   ws='   '
54   line=" $CMDLINE "
55   case "$line" in
56     *[${ws}]"$1="*)
57       result="${line##*[$ws]$1=}"
58       result="${result%%[$ws]*}"
59       echo "$result"
60       return 0 ;;
61     *) # no match?
62       return 1 ;;
63   esac
64 }
65
66 # Check boot commandline for specified option
67 checkbootparam(){
68   [ -n "$1" ] || ( echo "Error: missing argument to checkbootparam()" ; return 1 )
69   local line
70   local ws
71   ws='   '
72   line=" $CMDLINE "
73   case "$line" in
74     *[${ws}]"$1"=*|*[${ws}]"$1"[${ws}]*)
75       return 0 ;;
76     *)
77       return 1 ;;
78   esac
79 }
80
81 # Check if currently using a framebuffer
82 hasfb() {
83     [ -e /dev/fb0 ] && return 0 || return 1
84 }
85
86 # Check wheter a configuration variable (like $CONFIG_TOHD) is
87 # enabled or not
88 checkvalue(){
89   case "$1" in
90     [yY][eE][sS])     return 0 ;; # it's set to 'yes'
91     [tT][rR][uU][eE]) return 0 ;; # it's set to 'true'
92                    *) return 1 ;; # default
93   esac
94 }
95
96 # Are we using grml-small?
97 checkgrmlsmall(){
98   grep -q small /etc/grml_version 2>>$DEBUG && return 0 || return 1
99 }
100
101 ### }}}
102
103 # {{{ filesystems (proc, pts, sys) and fixes
104 mount_proc(){
105   [ -f /proc/version ] || mount -t proc /proc /proc 2>/dev/null
106 }
107
108 mount_pts(){
109   grep -q "/dev/pts" /proc/mounts || mount -t devpts /dev/pts /dev/pts 2>/dev/null
110 }
111
112 mount_sys(){
113   [ -d /sys/devices ] || mount -t sysfs /sys /sys 2>/dev/null
114 }
115 # }}}
116
117 # {{{ Check if we are running in live mode or from HD
118 INSTALLED=""
119 [ -e /etc/grml_cd ] || INSTALLED="yes"
120
121 # testcd
122 TESTCD=""
123 checkbootparam 'testcd' >>$DEBUG 2>&1 && TESTCD="yes"
124 # }}}
125
126 # {{{ source lsb-functions , color handling
127 if checkbootparam 'nocolor'; then
128   RC_NOCOLOR=yes
129   . /etc/grml/lsb-functions
130   einfo "Disabling colors in bootsequence as requested on commandline." ; eend 0
131 else
132   . /etc/grml/lsb-functions
133   . /etc/grml_colors
134 fi
135 # }}}
136
137 # {{{ debug
138 config_debug(){
139  checkbootparam 'debug'            && BOOTDEBUG="yes"
140  checkbootparam "BOOT_IMAGE=debug" && BOOTDEBUG="yes"
141
142  rundebugshell(){
143   if [ -n "$BOOTDEBUG" ]; then
144      einfo "Starting intermediate shell stage $stage as requested by \"debug\" option."
145      if [ grep -q "debug=noscreen" "$CMDLINE" ] ; then
146         einfo "Notice that the shell does not provide job handling: ctrl-z, bg and fg won't work!"
147         einfo "Just exit the shell to continue boot process..."
148         /bin/zsh
149      else
150         eindent
151         if [ -r /etc/grml/screenrc ] ; then
152            einfo "Starting GNU screen to be able to use a full featured shell environment."
153            einfo "Just exit the shells (and therefore screen) to continue boot process..."
154            /bin/zsh -c "screen -c /etc/grml/screenrc"
155         else
156            einfo "Notice that the shell does not provide job handling: ctrl-z, bg and fg won't work!"
157            einfo "Just exit the shell to continue boot process..."
158            /bin/zsh
159         fi
160         eoutdent
161      fi
162   fi
163  }
164 }
165 # }}}
166
167 # {{{ log
168 config_log(){
169 if checkbootparam 'log' || checkbootparam 'debug' ; then
170    export DEBUG="/tmp/grml.log.`date +%Y%m%d`"
171    touch $DEBUG
172    einfo "Bootparameter log found. Log files: ${DEBUG} and /var/log/boot"
173    eindent
174      einfo "Starting bootlogd." # known to be *very* unreliable :(
175      bootlogd -r -c >>$DEBUG 2>&1 ; eend $?
176    eoutdent
177 else
178    DEBUG="/dev/null"
179 fi
180 }
181 # }}}
182
183 # {{{ set firmware timeout via bootparam
184 config_fwtimeout(){
185  if checkbootparam 'fwtimeout' ; then
186    TIMEOUT="$(getbootparam 'fwtimeout' 2>>$DEBUG)"
187    einfo "Bootoption fwtimeout found. (Re)Loading firmware_class module."
188    rmmod firmware_class >>$DEBUG 2>&1
189    modprobe firmware_class ; eend $?
190  fi
191  if [ -z "$TIMEOUT" ] ; then
192    TIMEOUT="100" # linux kernel default: 10
193  fi
194  if [ -f /sys/class/firmware/timeout ] ; then
195    einfo "Setting timeout for firmware loading to ${TIMEOUT}."
196    echo 100 > /sys/class/firmware/timeout ; eend $?
197  fi
198 }
199 # }}}
200
201 ### {{{ language configuration / localization
202 config_language(){
203
204  einfo "Activating language settings:"
205  eindent
206
207  # people can specify $LANGUAGE and $CONSOLEFONT in a config file
208  [ -r /etc/grml/autoconfig ] && . /etc/grml/autoconfig
209
210  # check for bootoption which overrides config from /etc/grml/autoconfig
211  BOOT_LANGUAGE="$(getbootparam 'lang' 2>>$DEBUG)"
212  [ -n "$BOOT_LANGUAGE" ] && LANGUAGE="$BOOT_LANGUAGE"
213
214  # set default to 'en' in live-cd mode iff $LANGUAGE is not set yet
215  if [ -z "$INSTALLED" ] ; then
216     [ -n "$LANGUAGE" ] || LANGUAGE='en'
217  fi
218
219  if [ -x /usr/sbin/grml-setlang ] ; then
220    # if bootoption lang is used update /etc/default/locale accordingly
221    if [ -n "$BOOT_LANGUAGE" ] ; then
222      checkgrmlsmall && /usr/sbin/grml-setlang "POSIX" || /usr/sbin/grml-setlang "$LANGUAGE"
223    # otherwise default to lang=en
224    else
225      checkgrmlsmall && /usr/sbin/grml-setlang "POSIX" || /usr/sbin/grml-setlang "en"
226    fi
227  fi
228
229  # set console font
230  if [ -z "$CONSOLEFONT" ] ; then
231     if ! checkbootparam 'nodefaultfont' >>$DEBUG 2>&1 ; then
232        if [ -r /usr/share/consolefonts/Uni3-Terminus16.psf.gz ] ; then
233           CONSOLEFONT='Uni3-Terminus16'
234        else
235           ewarn "/usr/share/consolefonts/Uni3-Terminus16.psf.gz not available. Please upgrade package console-terminus." ; eend 1
236        fi
237        if ! hasfb ; then
238           CONSOLEFONT='Lat15-Terminus16'
239        fi
240     fi
241  fi
242
243  # export it now, so error messages get translated, too
244  if checkgrmlsmall ; then
245     export LANG='C' # grml-small does not provide any further locales
246  else
247     [ -r /etc/default/locale ] && . /etc/default/locale
248     export LANG LANGUAGE
249  fi
250
251  # configure keyboard layout, read in already set values first:
252  [ -r /etc/sysconfig/keyboard ] && . /etc/sysconfig/keyboard
253
254  # now allow keyboard override by boot commandline for later use:
255  KKEYBOARD="$(getbootparam 'keyboard' 2>>$DEBUG)"
256  [ -n "$KKEYBOARD" ] && KEYTABLE="$KKEYBOARD"
257  # notce: de/at is a bad choice, so take de-latin1-nodeadkeys instead:
258  [[ "$KKEYBOARD" == 'de' ]] && KEYTABLE=de-latin1-nodeadkeys
259  [[ "$KKEYBOARD" == 'at' ]] && KEYTABLE=de-latin1-nodeadkeys
260
261  # modify /etc/sysconfig/keyboard only in live-cd mode:
262  if [ -z "$INSTALLED" ] ; then
263
264    local LANGUAGE="$BOOT_LANGUAGE"
265    . /etc/grml/language-functions
266    # allow setting xkeyboard explicitly different than console keyboard
267    KXKEYBOARD="$(getbootparam 'xkeyboard' 2>>$DEBUG)"
268    if [ -n "$KXKEYBOARD" ]; then
269       XKEYBOARD="$KXKEYBOARD"
270       KDEKEYBOARD="$KXKEYBOARD"
271    elif [ -n "$KKEYBOARD" ]; then
272       XKEYBOARD="$KKEYBOARD"
273       KDEKEYBOARD="$KKEYBOARD"
274    fi
275
276    # duplicate of previous code to make sure /etc/grml/language-functions
277    # does not overwrite our values....
278    # now allow keyboard override by boot commandline for later use:
279    KKEYBOARD="$(getbootparam 'keyboard' 2>>$DEBUG)"
280    [ -n "$KKEYBOARD" ] && KEYTABLE="$KKEYBOARD"
281    # notce: de/at is a bad choice, so take de-latin1-nodeadkeys instead:
282    [[ "$KKEYBOARD" == 'de' ]] && KEYTABLE=de-latin1-nodeadkeys
283    [[ "$KKEYBOARD" == 'at' ]] && KEYTABLE=de-latin1-nodeadkeys
284
285    # write keyboard related variables to file for later use
286    [ -d /etc/sysconfig ] || mkdir /etc/sysconfig
287    if ! [ -e /etc/sysconfig/keyboard ] ; then
288       echo "KEYTABLE=\"$KEYTABLE\""          > /etc/sysconfig/keyboard
289       echo "XKEYBOARD=\"$XKEYBOARD\""       >> /etc/sysconfig/keyboard
290       echo "KDEKEYBOARD=\"$KDEKEYBOARD\""   >> /etc/sysconfig/keyboard
291       echo "KDEKEYBOARDS=\"$KDEKEYBOARDS\"" >> /etc/sysconfig/keyboard
292    fi
293  fi
294
295  [ -r /etc/sysconfig/keyboard ] && . /etc/sysconfig/keyboard
296
297  # activate unicode console if running within utf8 environment
298  if [ -r /etc/default/locale ] ; then
299     if grep -q "LANG=.*UTF" /etc/default/locale ; then
300        einfo "Setting up unicode environment."
301        unicode_start >>$DEBUG 2>&1 ; eend $?
302     fi
303  fi
304
305  # Set default keyboard before interactive setup
306  if [ -n "$KEYTABLE" ] ; then
307     einfo "Running loadkeys for ${WHITE}${KEYTABLE}${NORMAL} in background"
308     loadkeys -q $KEYTABLE &
309     eend $?
310  fi
311
312  # we have to set up all consoles, therefore loop it over all ttys:
313  NUM_CONSOLES=$(fgconsole --next-available 2>/dev/null)
314  if [ -n "$NUM_CONSOLES" ] ; then
315     NUM_CONSOLES=$(expr ${NUM_CONSOLES} - 1)
316     [ ${NUM_CONSOLES} -eq 1 ] && NUM_CONSOLES=6
317  fi
318  CUR_CONSOLE=$(fgconsole 2>/dev/null)
319
320  if [ -x "$(which setfont)" ] ; then
321     use_setfont=true
322  elif [ -x "$(which consolechars)" ] ; then
323     use_consolechars=true
324  else
325     eerror "Neither setfont nor consolechars tool present, can not set font."
326     eend 1
327     return 1
328  fi
329
330  if [ -n "$CHARMAP" ] ; then
331     einfo "Setting font to ${CHARMAP}"
332     RC=0
333     for vc in $(seq 0 ${NUM_CONSOLES}) ; do
334         if $use_setfont ; then
335           setfont -C /dev/tty${vc} $CHARMAP ; RC=$?
336         elif $use_consolechars ; then
337           consolechars --tty=/dev/tty${vc} -m ${CHARMAP} ; RC=$?
338         fi
339     done
340     if [ -n "$CUR_CONSOLE" ] ; then
341        [ "$CUR_CONSOLE" != "serial" ] && chvt $CUR_CONSOLE
342     fi
343     eend $RC
344  fi
345
346  if checkbootparam 'noconsolefont' ; then
347     ewarn "Skipping setting console font as requested on boot commandline." ; eend 0
348  else
349     if [ -n "$CONSOLEFONT" ] ; then
350        einfo "Setting font to ${CONSOLEFONT}"
351        RC=0
352        for vc in $(seq 0 ${NUM_CONSOLES}) ; do
353            if $use_setfont ; then
354              setfont -C /dev/tty${vc} ${CONSOLEFONT} ; RC=$?
355            elif $use_consolechars ; then
356              consolechars --tty=/dev/tty${vc} -f ${CONSOLEFONT} ; RC=$?
357            fi
358        done
359        if [ -n "$CUR_CONSOLE" ] ; then
360           [ "$CUR_CONSOLE" != "serial" ] && chvt $CUR_CONSOLE
361        fi
362        eend $RC
363     fi
364  fi
365
366  eoutdent
367 }
368 # }}}
369
370 # {{{ Set hostname
371 config_hostname(){
372  if checkbootparam 'hostname' ; then
373   HOSTNAME="$(getbootparam 'hostname' 2>>$DEBUG)"
374   if [ -z "$HOSTNAME" ] && [ -x /usr/bin/random-hostname ] ; then
375      einfo "Generating random hostname as no hostname was specified."
376      HOSTNAME="$(/usr/bin/random-hostname)"
377      eend $?
378   fi
379   einfo "Setting hostname to $HOSTNAME as requested."
380   grml-hostname $HOSTNAME >>$DEBUG ; RC=$?
381   [ "$RC" = "0" ] && hostname $HOSTNAME
382   eend $RC
383  else
384   hostname --file /etc/hostname
385  fi
386 }
387 # }}}
388
389 # fstabuser (needed when running from harddisk with username != grml {{{
390 config_userfstab(){
391   [ -r /etc/grml/autoconfig ] && . /etc/grml/autoconfig
392   if [ -n "$CONFIG_FSTAB_USER" ] ; then
393      fstabuser="$CONFIG_FSTAB_USER"
394   else
395      fstabuser=$(getent passwd 1000 | cut -d: -f1)
396   fi
397   # if not yet set fall back to default 'grml' user
398   [ -n "$fstabuser" ] || fstabuser='grml'
399 }
400 # }}}
401
402 # {{{ Set clock (Local time is more often used than GMT, so it is default)
403 config_time(){
404  # don't touch the files if running from harddisk:
405  if [ -z "$INSTALLED" ]; then
406     # The default hardware clock timezone is stated as representing local time.
407     UTC="--localtime"
408     grep -q "^UTC=" /etc/default/rcS || echo "UTC=no" >> /etc/default/rcS
409     checkbootparam 'utc'       >>$DEBUG 2>&1 && sed -i "s|^UTC=.*$|UTC=yes|" /etc/default/rcS
410     checkbootparam 'gmt'       >>$DEBUG 2>&1 && sed -i "s|^UTC=.*$|UTC=yes|" /etc/default/rcS
411     checkbootparam 'localtime' >>$DEBUG 2>&1 && sed -i "s|^UTC=.*$|UTC=no|"  /etc/default/rcS
412     grep -q -i "^UTC=yes" /etc/default/rcS && UTC="-u"
413     # hwclock uses the TZ variable
414     KTZ="$(getbootparam 'tz' 2>>$DEBUG)"
415     [ -z "$KTZ" ] && [ -r /etc/timezone ] && KTZ=$(cat /etc/timezone)
416     if [ ! -f "/usr/share/zoneinfo/$KTZ" ] ; then
417        ewarn "Warning: unknown timezone $KTZ" ; eend 1
418        KTZ="Europe/Vienna"
419        ewarn "Falling back to timezone $KTZ" ; eend 0
420     fi
421
422     if ! [ -r /dev/rtc ] ; then
423       ewarn "Warning: realtime clock not available, trying to execute hwclock anyway." ; eend 0
424     fi
425
426     ERROR=$(TZ="$KTZ" hwclock $UTC -s 2>&1 | head -1) ; RC=$?
427     if [ -n "$ERROR" ] ; then
428        eindent
429        ERROR=$(TZ="$KTZ" hwclock $UTC -s --directisa 2>&1 | head -1)
430        if [ -n "$ERROR" ] ; then
431           eerror "Problem running hwclock: $ERROR" ; eend 1
432        fi
433        eoutdent
434     fi
435
436  fi
437 }
438 # }}}
439
440 # {{{ print kernel info
441 config_kernel(){
442   vmware-detect &>/dev/null && VMWARE="inside ${WHITE}VMware/Qemu${NORMAL}"
443   [ -d /proc/xen ] && VMWARE='' # vmware-detect returns '0' when running with a Xen-enabled kernel
444   einfo "Running Linux Kernel $KERNEL $VMWARE" ; eend 0
445   if [ -r /proc/cpuinfo ] ; then
446      if egrep -q '^flags.*(vmx|svm)' /proc/cpuinfo ; then
447        eindent
448        einfo 'CPU(s) featuring virtualization technology detected' ; eend 0
449        eoutdent
450      fi
451   fi
452   if [ -d /proc/xen ] ; then
453      eindent
454      einfo 'Running kernel featuring support for Xen detected' ; eend 0
455      eoutdent
456   fi
457 }
458 # }}}
459
460 # {{{ ld.so.cache + depmod
461 config_ld_mod(){
462 if [ -n "$INSTALLED" ]; then
463  if ! [ -r /etc/grml.first.boot ] ; then
464   einfo "Running from HD for the first time, regenerate ld.so.cache and modules.dep:"
465   eindent
466 # Regenerate ld.so.cache and module dependencies on HD
467     einfo "Running ldconfig" ; ldconfig  ; eend $?
468     einfo "Running depmod"   ; depmod -a ; eend $?
469     touch /etc/grml.first.boot
470     eend 0
471   eoutdent
472  fi
473 fi
474 }
475 # }}}
476
477 # {{{ timezone
478 config_timezone(){
479  # don't touch the files if running from harddisk:
480  if [ -z "$INSTALLED" ]; then
481     KTZ="$(getbootparam 'tz' 2>>$DEBUG)"
482     if [ -n "$KTZ" ] ; then
483        if [ ! -f "/usr/share/zoneinfo/$KTZ" ]
484        then
485           ewarn "Warning: unknown timezone $KTZ"; eend 0
486        else
487           einfo "Setting timezone."
488           # update debconf
489           area=$(echo $KTZ | cut -d '/' -f1)
490           zone=$(echo $KTZ | cut -d '/' -f2)
491           echo "tzdata tzdata/Areas       select $area" | debconf-set-selections
492           echo "tzdata tzdata/Zones/$area select $zone" | debconf-set-selections
493           # update files
494           echo $KTZ > /etc/timezone
495           rm -f /etc/localtime
496           cp "/usr/share/zoneinfo/$KTZ" /etc/localtime ; eend $?
497        fi
498     fi
499  fi
500 }
501 # }}}
502
503 # small computer / nearly no ram {{{
504 config_small(){
505
506 RAM=$(/usr/bin/gawk '/MemTotal/{print $2}' /proc/meminfo)
507 # MEM=$(/usr/bin/gawk 'BEGIN{m=0};/MemFree|Cached|SwapFree/{m+=$2};END{print m}' /proc/meminfo)
508 eindent
509
510 if checkbootparam 'small'; then
511   einfo "Information: ${RAM} kB of RAM available." ; eend 0
512   einfo "Bootoption small detected. Activating small system."
513   if [ -r /etc/inittab.small ] ; then
514     mv /etc/inittab /etc/inittab.normal
515     mv /etc/inittab.small /etc/inittab
516   else
517     sed -i 's/^9/#&/' /etc/inittab
518     sed -i 's/^10/#&/' /etc/inittab
519     sed -i 's/^11/#&/' /etc/inittab
520     sed -i 's/^12/#&/' /etc/inittab
521   fi
522   /sbin/telinit q ; eend $?
523 else
524   if checkgrmlsmall ; then
525     if [[ $RAM -lt 25000 ]] ; then
526       ewarn "Information: ${RAM} kB of RAM available." ; eend 1
527       ewarn "At least 32MB of RAM should be available for grml-small." ; eend 1
528       ewarn "Use the bootoption small to save some more MB of memory usage." ; eend 0
529       ewarn "Dropping you into a rescue shell. To continue booting exit the shell." ; eend 0
530       /bin/zsh --login
531     else
532       einfo "Information: ${RAM} kB of RAM available." ; eend 0
533     fi
534   else
535     if [[ $RAM -lt 58000 ]] ; then
536       ewarn "Information: ${RAM} kB of RAM available." ; eend 1
537       ewarn "At least 64MB of RAM should be available for grml." ; eend 1
538       ewarn "Use the bootoption small to save some more MB of memory usage." ; eend 0
539       ewarn "Dropping you into a rescue shell. To continue booting exit the shell." ; eend 0
540       /bin/zsh --login
541     else
542       einfo "Information: ${RAM} kB of RAM available." ; eend 0
543     fi
544   fi
545 fi
546 eoutdent
547 }
548 # }}}
549
550 # skip startup of w3m {{{
551 config_fast(){
552 if checkbootparam 'fast'; then
553   ewarn "Bootoption fast detected. Skipping startup of grml-quickconfig."
554     sed -i 's#^1:.*#1:12345:respawn:/usr/bin/openvt -f -c 1 -w -- /bin/zsh#' /etc/inittab
555   /sbin/telinit q ; eend $?
556 fi
557 }
558 # }}}
559
560 # activate serial console {{{
561 config_console(){
562 if checkbootparam 'console'; then
563   local line
564   local ws
565   ws='   '
566
567   einfo "Bootoption for serial console detected:"
568
569   line="$CMDLINE x "
570   this=""
571   line="${line#*[$ws]}"
572   local telinitq=""
573   while [ -n "$line" ]; do
574     case "$this" in
575       console=*)
576         local serial="$this"
577         local device="${this%%,*}"
578         local device="${device##*=}"
579         if echo $serial | grep -q ttyS ; then
580           local option="${serial##*,}"
581           # default (works for kvm & CO):
582           local speed="115200,57600,38400,19200,9600,4800,2400,1200";
583           # ... unless overriden by command line:
584           case "$option" in
585             115200*) speed=115200 ;;
586              57600*) speed=57600 ;;
587              38400*) speed=38400 ;;
588              19200*) speed=19200 ;;
589               9600*) speed=9600 ;;
590               4800*) speed=4800 ;;
591               2400*) speed=2400 ;;
592               1200*) speed=1200 ;;
593           esac
594           eindent
595             einfo "Activating console login on device ${device} with speed ${speed}."
596             local number="${device#ttyS}"
597             sed -i "/^T$number:/d;/^#grmlserial#/iT$number:23:respawn:/bin/bash -c \"/sbin/getty -L $device -l /usr/share/grml-scripts/run-welcome $speed vt100 || sleep 30\"" /etc/inittab
598             eend $?
599             telinitq="1"
600           eoutdent
601         fi
602         ;;
603     esac
604     this="${line%%[$ws]*}"
605     line="${line#*[$ws]}"
606   done
607
608   if [ -n "$telinitq" ]; then
609     /sbin/telinit q
610   fi
611   eend $?
612 fi
613 }
614 # }}}
615
616 # {{{ Bring up loopback interface now
617 config_local_net(){
618  if [ -z "$INSTALLED" ] ; then
619     if grep -q 'iface lo inet loopback' /etc/network/interfaces 2>/dev/null ; then
620        grep -q lo=lo /etc/network/run/ifstate 2>/dev/null || ifup lo
621     else
622        ifconfig lo up
623     fi
624  fi
625 }
626 # }}}
627
628 # {{{ copy passwd-lockfile to ramdisk (fix unionfs-behaviour)
629 # otherwise we will get: passwd: Authentication token lock busy
630 config_fix_passwd(){
631  if [ -z "$INSTALLED" ] ; then
632   touch /etc/.pwd.lock
633  fi
634 }
635 # }}}
636
637 # {{{ CD Checker
638 config_testcd(){
639 if [ -n "$TESTCD" ]; then
640    einfo "Checking CD data integrity as requested by '${WHITE}testcd${NORMAL}' boot option."
641    einfo "Reading files and checking against GRML/md5sums, this may take a while..."
642    echo -n "${RED}"
643
644    if [ -n "${LIVECD_PATH}"/GRML ] ; then
645       ( cd "${LIVECD_PATH}"/GRML ; rm -f /tmp/md5sum.log ; md5sum -c md5sums 2>&1 | tee /tmp/md5sum.log ; RC=$? )
646    else
647       echo "${RED} *** Error: Could not find md5sum file.                           ***"
648    fi
649
650    if [ "$RC" = "0" ]; then
651       einfo "Everything looks OK" ; eend 0
652    else
653       eerror 'Checksum failed for theses files:' ; eend 1
654       egrep -v '(^md5sum:|OK$)' /tmp/md5sum.log
655       eerror 'Data on the grml medium is possibly incomplete/damaged or...'
656       eerror '... RAM of your computer is broken.' ; eend 1
657       einfon "Hit return to continue, or press the reset button to quit."
658      read a
659    fi
660
661    eend 0
662 fi
663 }
664 # }}}
665
666 # {{{ blacklist specific module [ used in /etc/init.d/udev ]
667 config_blacklist(){
668 if checkbootparam 'blacklist' ; then
669  if [ -z "$INSTALLED" ]; then
670   einfo "Bootoption blacklist found."
671   BLACK="$(getbootparam 'blacklist' 2>>$DEBUG)"
672   BLACKLIST_FILE='/etc/modprobe.d/grml.conf'
673   if [ -n "$BLACK" ] ; then
674     for module in $(echo ${BLACK//,/ }) ; do
675         einfo "Blacklisting module ${module} via ${BLACKLIST_FILE}."
676         echo "# begin entry generated by config_blacklist of grml-autoconfig" >> "$BLACKLIST_FILE"
677         echo "blacklist $module"     >> "$BLACKLIST_FILE"
678         echo "alias     $module off" >> "$BLACKLIST_FILE"
679         echo "# end   entry generated by config_blacklist of grml-autoconfig" >> "$BLACKLIST_FILE" ; eend $?
680     done
681   else
682    eerror "No given module for blacklist found. Blacklisting will not work therefore."
683   fi
684  else
685   ewarn "Backlisting via bootoption is not intended for use on harddisk installations." ; eend 1
686   eindent
687    einfo "Please blacklist the module(s) manually using the 'blacklist' script."
688   eoutdent
689  fi
690 fi
691 }
692 # }}}
693
694 # {{{ ACPI
695 config_acpi_apm(){
696 if [ -d /proc/acpi ]; then
697   if checkbootparam 'noacpi'; then
698     ewarn "Skipping ACPI Bios detection as requested via noacpi on boot commandline." ; eend 0
699   elif checkbootparam 'nogrmlacpi' ; then
700     ewarn "Skipping ACPI Bios detection as requested via nogrmlacpi on boot commandline." ; eend 0
701   else
702     einfo "ACPI Bios found, activating modules (disable via bootoption noacpi / nogrmlacpi): "
703     eindent
704     found=""
705     for a in /lib/modules/$KERNEL/kernel/drivers/acpi/*; do
706       basename="${a##*/}"
707       basename="${basename%%.*}"
708       case "$basename" in *_acpi)
709        egrep -qi "${basename%%_acpi}" /proc/acpi/dsdt 2>>$DEBUG || continue ;;
710       esac
711       modprobe $basename >>$DEBUG 2>&1 && found="yes"
712       local BASE="$BASE $basename"
713     done
714     if [ -n "$found" ] ; then
715       einfo "$BASE"  ; eend 0
716     else
717       ewarn "(none)" ; eend 1
718     fi
719     if ! ps x 2>>$DEBUG | grep -q /usr/sbin/acpid ; then
720       einfo "Starting acpi daemon."
721       /etc/init.d/acpid start >>$DEBUG 2>&1 ; eend $?
722     else
723       ewarn "acpi daemon already running."
724       eend 0
725     fi
726     eoutdent
727   fi
728 else
729 # APM
730   if checkbootparam 'noapm'; then
731     ewarn "Skipping APM Bios detection as requested on boot commandline." ; eend 0
732   else
733     modprobe apm power_off=1 >>$DEBUG 2>&1
734     if [ "$?" = "0" ] ; then
735        if [ -x /etc/init.d/apmd ] ;then
736           einfo "APM Bios found, enabling power management functions."
737           /etc/init.d/apmd start ; eend $?
738        fi
739     else
740       eerror "Loading apm module failed." ; eend 1
741     fi
742   fi
743 fi
744 }
745 # }}}
746
747 # {{{ AGP
748 config_agp(){
749 if checkbootparam 'forceagp' ; then
750 # Probe for AGP. Hope this can fail safely
751   grep -q "AGP" "/proc/pci" 2>>$DEBUG && { modprobe agpgart || modprobe agpgart agp_try_unsupported=1; } >>$DEBUG 2>&1 && einfo "AGP bridge detected." ; eend 0
752 fi
753 }
754 # }}}
755
756 # {{{ Collect partitions from /proc/partitions first for enabling DMA
757 check_partitions(){
758 partitions=""
759 IDEDISKS=""
760 while read major minor blocks partition relax; do
761   partition="${partition##*/}"
762   [ -z "$partition" -o ! -e "/dev/$partition" ] && continue
763   case "$partition" in
764     hd?) IDEDISKS="$IDEDISKS $partition";;                # IDE  Harddisk, entire disk
765     sd?) ;;                                               # SCSI Harddisk, entire disk
766 #    [hs]d*) partitions="$partitions /dev/$partition";;    # IDE or SCSI disk partition
767     [hs]d*|ub*) partitions="$partitions /dev/$partition";;    # IDE, USB or SCSI disk partition
768   esac
769 done <<EOT
770 $(awk 'BEGIN{old="__start"}{if($0==old){exit}else{old=$0;if($4&&$4!="name"){print $0}}}' /proc/partitions)
771 EOT
772 }
773 check_partitions >/dev/null 2>&1 # avoid output "check_partitions:3: read-only file system"
774 # }}}
775
776 # {{{ Enable DMA for all IDE drives now if not disabled
777 # Notice: Already done by linuxrc, but make sure it's done also on harddisk-installed systems
778 config_dma(){
779 if checkbootparam 'nodma'; then
780   ewarn "Skipping DMA accelleration as requested on boot commandline." ; eend 0
781 else
782   for d in $(cd /proc/ide 2>>$DEBUG && echo hd[a-z]); do
783     if test -d /proc/ide/$d; then
784       if egrep -q 'using_dma[ \t]+0' /proc/ide/$d/settings 2>>$DEBUG; then
785         MODEL="$(cat /proc/ide/$d/model 2>>$DEBUG)"
786         test -z "$MODEL" && MODEL="[GENERIC IDE DEVICE]"
787         einfo "Enabling DMA acceleration for: ${WHITE}$d        ${YELLOW}[${MODEL}]${NORMAL}"
788         echo "using_dma:1" >/proc/ide/$d/settings
789         eend 0
790       fi
791     fi
792   done
793 fi
794 }
795 # }}}
796
797 # {{{ Start creating /etc/fstab with HD partitions and USB SCSI devices now
798 config_fstab(){
799
800 NOSWAP="yes" # we do not use swap by default!
801 if checkbootparam 'swap' || checkbootparam 'anyswap' ; then
802    NOSWAP=''
803    checkbootparam 'anyswap' && export ANYSWAP='yes' || export ANYSWAP=""
804 fi
805
806 # Scan for swap, config, homedir - but only in live-mode
807 if [ -z "$INSTALLED" ] ; then
808    [ -z "$NOSWAP" ] && einfo "Searching for swap partition(s) as requested."
809    GRML_IMG=""
810    GRML_SWP=""
811    HOMEDIR="$(getbootparam 'home')"
812    if [ -n "$partitions" ]; then
813       while read p m f relax; do
814         case "$p" in *fd0*|*proc*|*sys*|*\#*) continue;; esac
815         partoptions="users,exec"
816         fnew=""
817         # it's a swap partition?
818         case "$f" in swap)
819           eindent
820           if [ -n "$NOSWAP" ]; then
821              ewarn "Ignoring swap partition ${WHITE}$p${NORMAL}. (Force usage via boot option 'swap', or execute grml-swapon)"
822              eend 0
823           else
824              case "$(dd if=$p bs=1 count=6 skip=4086 2>/dev/null)" in
825                    S1SUSP|S2SUSP|pmdisk|[zZ]*)
826                      if [ -n "$ANYSWAP" ] ; then
827                         einfo "Using swap partition ${WHITE}${p}${NORMAL} [bootoption anyswap found]."
828                         swapon $p 2>>$DEBUG ; eend $?
829                      else
830                         ewarn "Suspend signature on ${WHITE}${p}${NORMAL} found, not using as swap. (Force usage via boot option: anyswap)"
831                      fi
832                      ;;
833                    *)
834                      if [[ "$p" == LABEL* ]] ; then
835                         p=$(blkid -t $p | awk -F: '{print $1}')
836                      fi
837                      if grep -q $p /proc/swaps ; then
838                         ewarn "Not using swap partition ${WHITE}${p}${NORMAL} as it is already in use." ; eend 0
839                      else
840                         if [ -b "$p" ] ; then
841                         einfo "Using swap partition ${WHITE}${p}${NORMAL}."
842                         swapon $p 2>>$DEBUG ; eend $?
843                         else
844                         ewarn "$p is not a valid block device - not using it therefore." ; eend 0
845                         fi
846                      fi
847                      ;;
848              esac # dd-check
849           fi # -n "$NOSWAP
850           eoutdent
851           continue
852           ;;
853         esac # it's a swap partition?
854
855         # mount read-only
856         MOUNTOPTS="ro"
857         case "$f" in
858           vfat|msdos|ntfs) MOUNTOPTS="$MOUNTOPTS,uid=${fstabuser},gid=${fstabuser}" ;;
859           ext2|ext3|reiserfs|jfs|reiser4|xfs) MOUNTOPTS="$MOUNTOPTS,noatime" ;;
860           *) continue ;;
861           # *) NONEFOUND='1'; continue ;;
862         esac
863
864         # use a swapfile
865         if [ -z "$NOSWAP" ] ; then
866            mount -o "$MOUNTOPTS" -t $f $p $m 2>>$DEBUG && MOUNTED=1 || continue
867            # Activate swapfile, if exists
868            SWAPFILE="$(/bin/ls -1d $m/[Gg][Rr][Mm][Ll].[Ss][Ww][Pp] 2>/dev/null)"
869         fi
870         if [ -z "$NOSWAP" -a -n "$SWAPFILE" -a -f "$SWAPFILE" ]; then
871            mount -o remount,rw $m && MOUNTED=1
872            if swapon "$SWAPFILE" 2>>$DEBUG ; then
873               eindent
874                 einfo "Using GRML swapfile ${WHITE}${SWAPFILE}${NORMAL}."
875               eoutdent
876               fnew="$SWAPFILE swap swap defaults 0 0"
877               grep -q "$fnew" "/etc/fstab" || echo "$fnew" >> /etc/fstab
878               GRML_SWP="$GRML_SWP $SWAPFILE"
879               eend 0
880            fi
881            mount -o remount,ro $m 2>>$DEBUG && MOUNTED=1
882         fi
883
884         # use a image as home
885         IMAGE="$(/bin/ls -1d $m/[Gg][Rr][Mm][Ll].[Ii][Mm][Gg] 2>/dev/null)"
886         if [ -z "$GRML_IMG" -a -n "$IMAGE" -a -f "$IMAGE" ]; then
887            if [ -n "$HOMEDIR" ]; then
888               if [ "$HOMEDIR" != "scan" -a "$HOMEDIR" != "$IMAGE" -a "$HOMEDIR" != "${IMAGE%/*.*}" ]; then
889                  continue
890               fi
891            fi
892            if type -a grml-image >/dev/null 2>&1 && grml-image "$IMAGE" </dev/console >/dev/console 2>&1; then
893               GRML_IMG="$IMAGE"
894               mount -o remount,ro $m 2>>$DEBUG && MOUNTED=1
895            fi
896         fi
897         eend 0
898
899         # Umount, if not in use
900         [ -n "$MOUNTED" ] && umount -r $m 2>/dev/null
901
902       done <<EOT
903       $(cat /etc/fstab)
904 EOT
905    fi # -n $partitions
906 fi # -z $INSTALLED
907 }
908 # }}}
909
910 # {{{ Mouse
911 config_mouse(){
912 if [ -n "$MOUSE_DEVICE" ] ; then
913   einfo "Detecting mouse: ${MOUSE_FULLNAME} at ${MOUSE_DEVICE}" ; eend $?
914 fi
915 }
916 # }}}
917
918 # {{{ IPv6 configuration
919 # Load IPv6 kernel module and print IP adresses
920 config_ipv6(){
921 if checkbootparam 'ipv6'; then
922   einfo "Enabling IPv6 as requested on boot commandline (sleeping for 2 seconds)"
923   modprobe ipv6
924   # we probably need some time until stateless autoconfiguration has happened
925   sleep 2
926   NETDEVICES="$(awk -F: '/eth.:|tr.:|wlan.:/{print $1}' /proc/net/dev 2>>$DEBUG)"
927   for DEVICE in `echo "$NETDEVICES"`; do
928     eindent
929       einfo "$DEVICE:"
930       ADDRESSES="$(ifconfig $DEVICE | awk '/.*inet6 addr:.*/{print $3}')"
931       COUNT="$(ifconfig $DEVICE | awk '/.*inet6 addr:.*/{ sum += 1};END {print sum }')"
932       eindent
933         for ADDR in `echo "$ADDRESSES"` ; do
934             einfo "$ADDR"
935         done
936         if [ "$COUNT" -eq "0" ] ; then
937            einfo "(none)" ; eend 1
938         fi
939       eoutdent
940     eoutdent
941   done
942   eend 0
943 fi
944 }
945 # }}}
946
947 # {{{ CPU-detection
948 config_cpu(){
949 if checkbootparam 'nocpu'; then
950   ewarn "Skipping CPU detection as requested on boot commandline." ; eend 0
951   return 0
952 fi
953
954 if [[ $(grep -c processor /proc/cpuinfo) -gt 1 ]] ; then
955    einfo "Detecting CPU:"
956    CPU=$(awk -F: '/^processor/{printf " Processor"$2" is"};/^model name/{printf $2};/^vendor_id/{printf vendor};/^cpu MHz/{printf " %dMHz",int($2)};/^cache size/{printf ","$2" Cache"};/^$/{print ""}' /proc/cpuinfo 2>>$DEBUG)
957    echo $CPU | sed 's/ \{1,\}/ /g'
958    eend 0
959 else
960    einfo "Detecting CPU: `awk -F: '/^processor/{printf " Processor"$2" is"};/^model name/{printf $2};/^vendor_id/{printf vendor};/^cpu MHz/{printf " %dMHz",int($2)};/^cache size/{printf ","$2" Cache"};/^$/{print ""}' /proc/cpuinfo 2>>$DEBUG` " ; eend 0
961 fi
962
963 # no cpufreq setup inside VirtualBox
964 if [ -r /proc/acpi/battery/BAT0/info ] && grep -q 'OEM info:.*innotek' /proc/acpi/battery/BAT0/info ; then
965    einfo 'Virtual Box detected, skipping cpufreq setup.' ; eend 0
966    return 0
967 fi
968
969 if [ -x /etc/init.d/loadcpufreq ] ; then
970    einfo "Trying to set up cpu frequency scaling:"
971    eindent
972    SKIP_CPU_GOVERNOR=''
973    LOADCPUFREQ=$(mktemp)
974    /etc/init.d/loadcpufreq start >"$LOADCPUFREQ" 2>&1 ; RC=$?
975    if grep -q FATAL "$LOADCPUFREQ" ; then
976       eindent
977         SKIP_CPU_GOVERNOR=1
978         oldIFS="$IFS"
979         IFS="
980 "
981          for line in $(grep FATAL "$LOADCPUFREQ" | sed 's/.*FATAL: //; s/ (.*)//') ; do
982              eerror "$line" ; eend $RC
983          done
984          IFS="$oldIFS"
985       eoutdent
986    elif grep -q done "$LOADCPUFREQ" ; then
987       MODULE=$(grep done "$LOADCPUFREQ" | sed 's/.*done (\(.*\))./\1/')
988       if [ -n "$MODULE" -a "$MODULE" != none ]; then
989          einfo "Loading cpufreq kernel module $MODULE" ; eend 0
990       else
991          ewarn "Could not find an appropriate kernel module for cpu frequency scaling." ; eend 1
992       fi
993    fi
994
995    rm -f $LOADCPUFREQ
996
997    if [ -z "$SKIP_CPU_GOVERNOR" ] ; then
998       einfo "Loading cpufreq_ondemand, setting ondemand governor"
999       RC=0
1000       if modprobe cpufreq_ondemand ; RC=$? ; then
1001          for file in $(find /sys/devices/system/cpu/ -name scaling_governor 2>/dev/null) ; do
1002             echo ondemand > $file
1003          done
1004       fi
1005       eend $RC
1006    fi # cpu-governor
1007
1008    eoutdent
1009 fi
1010 }
1011 # }}}
1012
1013 # {{{ autostart of ssh
1014 config_ssh(){
1015 if checkbootparam 'ssh' ; then
1016    SSH_PASSWD=''
1017    SSH_PASSWD="$(getbootparam 'ssh' 2>>$DEBUG)"
1018    einfo "Bootoption ssh found, trying to set password for user grml."
1019    eindent
1020    if [ -z "$SSH_PASSWD" ] ; then
1021       if [ -x /usr/bin/apg ] ; then
1022          SSH_PASSWD="$(apg -M NL -a 0 -m 8 -x 12 -n 1)"
1023       elif [ -x /usr/bin/gpw ] ; then
1024          SSH_PASSWD="$(gpw 1)"
1025       elif [ -x /usr/bin/pwgen ] ; then
1026          SSH_PASSWD="$(pwgen -1 8)"
1027       elif [ -x /usr/bin/hexdump ] ; then
1028          SSH_PASSWD="$(dd if=/dev/urandom bs=14 count=1 2>/dev/null | hexdump | awk '{print $3 $4}')"
1029       elif [ -n "$RANDOM" ] ; then
1030          SSH_PASSWD="grml${RANDOM}"
1031       else
1032          SSH_PASSWD=''
1033          eerror "Empty passphrase and neither pwgen nor hexdump nor \$RANDOM found. Skipping."
1034          eend 1
1035       fi
1036
1037       if [ -n "$SSH_PASSWD" ] ; then
1038          ewarn "No given password for ssh found. Using random password: $SSH_PASSWD" ; eend 0
1039       fi
1040    fi
1041    eoutdent
1042
1043    # finally check if we have a password we can use:
1044    if [ -n "$SSH_PASSWD" ] ; then
1045       # chpasswd sucks, seriously.
1046       if chpasswd --help 2>&1 | grep -q -- '-m,' ; then
1047         echo "grml:$SSH_PASSWD" | chpasswd -m
1048       else
1049         echo "grml:$SSH_PASSWD" | chpasswd
1050       fi
1051    fi
1052
1053    einfo 'Starting secure shell server in background.'
1054    /etc/init.d/rmnologin start >>$DEBUG 2>>$DEBUG
1055    /etc/init.d/ssh start >>$DEBUG 2>>$DEBUG &
1056    eend $?
1057
1058    eindent
1059    ewarn 'Warning: please change the password for user grml as soon as possible!'
1060    eoutdent
1061 fi
1062 }
1063 # }}}
1064
1065 # {{{ autostart of x11vnc
1066 config_vnc(){
1067
1068 USER=grml # TODO: make it dynamically configurable
1069 if checkbootparam 'vnc' ; then
1070    VNC_PASSWD=''
1071    VNC_PASSWD="$(getbootparam 'vnc' 2>>$DEBUG)"
1072    einfo "Bootoption vnc found, trying to set password for user $USER."
1073    eindent
1074    if [ -z "$VNC_PASSWD" ] ; then
1075       if [ -x /usr/bin/apg ] ; then
1076          VNC_PASSWD="$(apg -M NL -a 0 -m 8 -x 12 -n 1)"
1077       elif [ -x /usr/bin/gpw ] ; then
1078          VNC_PASSWD="$(gpw 1)"
1079       elif [ -x /usr/bin/pwgen ] ; then
1080          VNC_PASSWD="$(pwgen -1 8)"
1081       elif [ -x /usr/bin/hexdump ] ; then
1082          VNC_PASSWD="$(dd if=/dev/urandom bs=14 count=1 2>/dev/null | hexdump | awk '{print $3 $4}')"
1083       elif [ -n "$RANDOM" ] ; then
1084          VNC_PASSWD="${USER}${RANDOM}"
1085       else
1086          VNC_PASSWD=''
1087          eerror "Empty passphrase and neither pwgen nor hexdump nor \$RANDOM found. Skipping."
1088          eend 1
1089       fi
1090
1091       if [ -n "$VNC_PASSWD" ] ; then
1092          ewarn "No given password for vnc found. Using random password: $VNC_PASSWD" ; eend 0
1093       fi
1094    fi
1095    eoutdent
1096
1097    # finally check if we have a password we can use:
1098    if [ -n "$VNC_PASSWD" ] ; then
1099
1100       VNCDIR="/home/${USER}/.vnc"
1101       [ -d "$VNCDIR" ] || mkdir "$VNCDIR"
1102
1103       if [ ! -x /usr/bin/x11vnc ] ; then
1104          eerror "Error: x11vnc not found - can not set up vnc. Please make sure to install the x11vnc package."
1105          eend 1
1106       else
1107          /usr/bin/x11vnc -storepasswd "$VNC_PASSWD" "$VNCDIR"/passwd ; eend $?
1108          /bin/chown -R "$USER": "$VNCDIR"
1109       fi
1110    fi
1111    if checkbootparam 'vnc_connect' ; then
1112       VNC_CONNECT=''
1113       VNC_CONNECT="$(getbootparam 'vnc_connect' 2>>$DEBUG)"
1114       einfo "Bootoption vnc_connect found, will start vnc with connect to $VNC_CONNECT."
1115       #store the options in a file
1116       VNCDIR="/home/${USER}/.vnc"
1117       [ -d "$VNCDIR" ] || mkdir "$VNCDIR"
1118       echo " --connect $VNC_CONNECT " >> $VNCDIR/options
1119    fi
1120 fi
1121 }
1122 # }}}
1123
1124 # {{{ set password for user grml
1125 config_passwd(){
1126 if checkbootparam 'passwd' >>$DEBUG 2>&1; then
1127   einfo "Bootoption passwd found."
1128   PASSWD="$(getbootparam 'passwd' 2>>$DEBUG)"
1129   if [ -n "$PASSWD" ] ; then
1130     echo "grml:$PASSWD" | chpasswd -m ; eend $?
1131   else
1132     eerror "No given password for ssh found. Autostart of SSH will not work." ; eend 1
1133   fi
1134   eindent
1135     ewarn "Warning: please change the password for user grml set via bootparameter as soon as possible!"
1136   eoutdent
1137 fi
1138 }
1139 # }}}
1140
1141 # {{{ Sound
1142 config_mixer () {
1143    if ! [ -x /usr/bin/amixer ] ; then
1144       eerror "amixer binary not available. Can not set sound volumes therefore."
1145       eend 1
1146    else
1147       if ! [ -r /proc/asound/cards ] ; then
1148          ewarn "No soundcard present, skipping mixer settings therefore."
1149          eend 0
1150          return
1151       fi
1152
1153       for card in $(cat /proc/asound/cards| grep -e '^\s*[0-9]' | awk '{print $1}') ; do
1154          einfo "Configuring soundcard \"$(awk -F\[ '/^ *'$card' \[/{ FS=" "; $0=$2; print $1}' < /proc/asound/cards)\""
1155          eindent
1156
1157          if checkbootparam 'vol' ; then
1158             VOL="$(getbootparam 'vol' 2>>$DEBUG)"
1159             if [ -z "$VOL" ] ; then
1160                eerror "Bootoption vol found but no volume level/parameter given. Using defaults (75%)."
1161                VOL='75'
1162                eend 1
1163             fi
1164          else
1165             VOL='75'
1166          fi
1167
1168          if checkbootparam 'nosound' ; then
1169             einfo "Muting sound devices on request."
1170             ERROR=$(amixer -q set Master mute)
1171             RC=$?
1172             if [ -n "$ERROR" ] ; then
1173                eindent
1174                eerror "Problem muting sound devices: $ERROR"
1175                eoutdent
1176             fi
1177             eend $RC
1178          elif [ -z "$INSTALLED" ] ; then
1179             einfo "Setting mixer volumes to level ${WHITE}${VOL}${NORMAL}."
1180
1181             if checkbootparam 'micvol' ; then
1182                MICVOL="$(getbootparam 'micvol' 2>>$DEBUG)"
1183             else
1184                MICVOL=0
1185             fi
1186
1187             for CONTROL in Master PCM ; do
1188                if amixer -q | grep -q "Simple mixer control '$CONTROL'" ; then
1189                   amixer -q set "${CONTROL}" "${VOL}"%
1190                   eend $?
1191                fi
1192             done
1193
1194             if [ ${MICVOL} -ne 0 ] ; then
1195                einfo "Setting microphone to ${WHITE}${MICVOL}${NORMAL}."
1196                amixer -q set "Mic" $MICVOL &> /dev/null
1197                eend $?
1198             fi
1199          fi # checkbootparam 'nosound'
1200          eoutdent
1201       done
1202    fi
1203 }
1204 # }}}
1205
1206 # {{{ modem detection
1207 config_modem(){
1208 if checkbootparam 'nomodem'; then
1209   ewarn "Skipping check for AC97 modem controller as requested on boot commandline." ; eend 0
1210 else
1211   if [ -x /etc/init.d/sl-modem-daemon ] ; then
1212      if lspci | grep Intel | grep -q "AC'97 Modem Controller" ; then
1213         einfo "AC97 modem controller detected. Start it running 'Start sl-modem-daemon'."
1214         eend 0
1215      fi
1216   fi
1217 fi
1218 }
1219 # }}}
1220
1221 # {{{ wondershaper
1222 config_wondershaper(){
1223  if checkbootparam 'wondershaper' ; then
1224     WONDER="$(getbootparam 'wondershaper' 2>>$DEBUG)"
1225     CMD=wondershaper
1226     DEVICE=""
1227     DOWNSTREAM=""
1228     UPSTREAM=""
1229     if [ -n "$WONDER" ]; then
1230       # Extra options
1231       DEVICE="${WONDER%%,*}"
1232       R="${WONDER#*,}"
1233       if [ -n "$R" -a "$R" != "$WONDER" ]; then
1234         WONDER="$R"
1235         DOWNSTREAM="${WONDER%%,*}"
1236         R="${WONDER#*,}"
1237         if [ -n "$R" -a "$R" != "$WONDER" ]; then
1238           WONDER="$R"
1239           UPSTREAM="${WONDER%%,*}"
1240           R="${WONDER#*,}"
1241         fi
1242       fi
1243     fi
1244     [ -n "$DEVICE" ]     && CMD="$CMD $DEVICE"
1245     [ -n "$DOWNSTREAM" ] && CMD="$CMD $DOWNSTREAM"
1246     [ -n "$UPSTREAM" ]   && CMD="$CMD $UPSTREAM"
1247     einfo "Starting wondershaper (${CMD}) in background."
1248     ( sh -c $CMD & ) && eend 0
1249  fi
1250 }
1251 # }}}
1252
1253 # {{{ syslog-ng
1254 config_syslog(){
1255  if checkbootparam 'nosyslog'; then
1256     ewarn "Not starting syslog daemon as requested on boot commandline." ; eend 0
1257  else
1258     SYSLOGD=''
1259     [ -x /etc/init.d/syslog-ng ] && SYSLOGD='syslog-ng'
1260     [ -x /etc/init.d/rsyslog   ] && SYSLOGD='rsyslog'
1261     [ -x /etc/init.d/dsyslog   ] && SYSLOGD='dsyslog'
1262     [ -x /etc/init.d/sysklogd  ] && SYSLOGD='sysklogd'
1263     [ -x /etc/init.d/inetutils-syslogd ] && SYSLOGD='inetutils-syslogd'
1264
1265     if [ -z "$SYSLOGD" ] ; then
1266        eerror "No syslog daemon found." ; eend 1
1267     else
1268        einfo "Starting $SYSLOGD in background."
1269        /etc/init.d/$SYSLOGD start >>$DEBUG &
1270        eend 0
1271     fi
1272  fi
1273 }
1274 # }}}
1275
1276 # {{{ gpm
1277 config_gpm(){
1278  if checkbootparam 'nogpm'; then
1279   ewarn "Not starting GPM as requested on boot commandline." ; eend 0
1280  else
1281    if ! [ -r /dev/input/mice ] ; then
1282       eerror "No mouse found - not starting GPM." ; eend 1
1283    else
1284       einfo "Starting gpm in background."
1285       /etc/init.d/gpm start >>$DEBUG &
1286       # ( while [ ! -e /dev/psaux ]; do sleep 5; done; /etc/init.d/gpm start >>$DEBUG ) &
1287       eend 0
1288    fi
1289  fi
1290 }
1291 # }}}
1292
1293 # {{{ services
1294 config_services(){
1295  if checkbootparam 'services' ; then
1296     SERVICE="$(getbootparam 'services' 2>>$DEBUG)"
1297     SERVICELIST=$(echo "$SERVICE" | sed 's/,/\\n/g')
1298     SERVICENL=$(echo "$SERVICE" | sed 's/,/ /g')
1299     for service in $(echo -e $SERVICELIST) ; do
1300       # support running (custom) init scripts in non-blocking mode
1301       # if they contain the keyword "DO_NO_RUN_IN_BACKGROUND".
1302       if grep -q 'DO_NO_RUN_IN_BACKGROUND' "/etc/init.d/${service}" 2>>$DEBUG ; then
1303         einfo "Starting service ${service}."
1304         /etc/init.d/${service} start >>$DEBUG
1305       else
1306         einfo "Starting service ${service} in background."
1307         /etc/init.d/${service} start >>$DEBUG &
1308       fi
1309     done
1310     eend $?
1311  fi
1312 }
1313 # }}}
1314
1315 # {{{ remote files
1316 get_remote_file() {
1317   [ "$#" -eq 2 ] || ( echo "Error: wrong parameter for get_remote_file()" ; return 1 )
1318   SOURCE=$(eval echo "$1")
1319   TARGET="$2"
1320   getconfig() {
1321   wget --timeout=10 --dns-timeout=10  --connect-timeout=10 --tries=1 \
1322        --read-timeout=10 ${SOURCE} -O ${TARGET} && return 0 || return 1
1323   }
1324   einfo "Trying to get ${WHITE}${TARGET}${NORMAL}"
1325   counter=10
1326   while ! getconfig && [[ "$counter" != 0 ]] ; do
1327     echo -n "Sleeping for 1 second and trying to get config again... "
1328     counter=$(( counter-1 ))
1329     echo "$counter tries left" ; sleep 1
1330   done
1331   if [ -s "$TARGET" ] ; then
1332     einfo "Downloading was successfull." ; eend 0
1333     einfo "md5sum of ${WHITE}${TARGET}${NORMAL}: "
1334     md5sum ${TARGET} ; eend 0
1335     return 0;
1336   else
1337     einfo "Sorry, could not fetch ${SOURCE}" ; eend 1
1338     return 1;
1339  fi
1340 }
1341 # }}}
1342
1343 # {{{ config files
1344 config_netconfig(){
1345  if checkbootparam 'netconfig' ; then
1346   CONFIG="$(getbootparam 'netconfig' 2>>$DEBUG)"
1347   CONFIGFILE='/tmp/netconfig.grml'
1348
1349   if get_remote_file ${CONFIG} ${CONFIGFILE} ; then
1350     cd / && einfo "Unpacking ${WHITE}${CONFIGFILE}${NORMAL}:" && /usr/bin/unp $CONFIGFILE $EXTRACTOPTIONS ; eend $?
1351   fi
1352
1353  fi
1354 }
1355 # }}}
1356
1357 # {{{ remote scripts
1358 config_netscript() {
1359  if checkbootparam 'netscript' ; then
1360   CONFIG="$(getbootparam 'netscript' 2>>$DEBUG)"
1361   SCRIPTFILE='/tmp/netscript.grml'
1362
1363   if get_remote_file ${CONFIG} ${SCRIPTFILE} ; then
1364     chmod +x ${SCRIPTFILE}
1365     einfo "Running ${WHITE}${SCRIPTFILE}${NORMAL}:" && NETSCRIPT=${CONFIG} ${SCRIPTFILE} ; eend $?
1366   fi
1367
1368  fi
1369 }
1370 # }}}
1371
1372 # {{{ fix/workaround for unionfs
1373 fix_unionfs(){
1374   if [ -z "$INSTALLED" ]; then
1375    touch /var/cache/apt/*cache.bin
1376   fi
1377 }
1378 # }}}
1379
1380 # {{{ start X window system via grml-x
1381 config_x_startup(){
1382 # make sure we start X only if startx is used *before* a nostartx option
1383 # so it's possible to disable automatic X startup using nostart
1384 if checkbootparam 'startx' && ! echo "$CMDLINE" | grep -q 'startx.*nostartx' ; then
1385  if [ -x "$(which X)" ] ; then
1386   if [ -z "$INSTALLED" ] ; then
1387    WINDOWMANAGER="$(getbootparam 'startx' 2>>$DEBUG)"
1388    if [ -z "$WINDOWMANAGER" ] ; then
1389      einfo "No window manager specified. Taking ${WHITE}wm-ng${NORMAL} as default." && eend 0
1390      WINDOWMANAGER="wm-ng"
1391    else
1392      einfo "Window manager ${WHITE}${WINDOWMANAGER}${NORMAL} found as bootoption." && eend 0
1393    fi
1394    einfo "Setting up and invoking grml-x ${WINDOWMANAGER}. Just exit X windows system to get full featured consoles."
1395    config_userfstab || fstabuser='grml'
1396  cat>|/etc/init.d/xstartup<<EOF
1397 #!/bin/sh
1398 su $fstabuser -c "/usr/bin/grml-x $WINDOWMANAGER"
1399 EOF
1400    chmod 755 /etc/init.d/xstartup
1401
1402    # adjust inittab for xstartup
1403    if grep -q '^6:' /etc/inittab ; then
1404       sed -i 's|^6:.*|6:2345:respawn:/bin/zsh --login -c "/etc/init.d/xstartup ; /usr/share/grml-scripts/run-welcome" >/dev/tty6 2>\&1 </dev/tty6|' /etc/inittab
1405    else # just append tty6 to inittab if no definition is present:
1406       echo '6:2345:respawn:/bin/zsh --login -c "/etc/init.d/xstartup ; /usr/share/grml-scripts/run-welcome" >/dev/tty6 2>&1 < /dev/tty6' >> /etc/inittab
1407    fi
1408
1409    /sbin/telinit q ; eend $?
1410
1411    if grep -q '^allowed_users=' /etc/X11/Xwrapper.config ; then
1412       sed -i 's/^allowed_users=.*/allowed_users=anybody/' /etc/X11/Xwrapper.config
1413    else
1414       echo 'allowed_users=anybody' >> /etc/X11/Xwrapper.config
1415    fi
1416
1417   else
1418     eerror "We are not running in live mode - startx will not work, skipping it."
1419     eerror " -> Please use something like xdm, gdm or kdm for starting X on a harddisk system!" ; eend 1
1420   fi
1421  else
1422    eerror "/usr/X11R6/bin/X is not present on this grml flavour."
1423    eerror "  -> Boot parameter startx does not work therefore." ; eend 1
1424  fi
1425 fi
1426 }
1427 # }}}
1428
1429 # {{{ configuration framework
1430 config_extract(){
1431 if checkbootparam 'extract' ; then
1432  EXTRACT="$(getbootparam 'extract' 2>>$DEBUG)"
1433  EXTRACTOPTIONS="-- -x $EXTRACT"
1434 fi
1435 }
1436
1437 config_finddcsdir() {
1438 #  - If no GRMLCFG partition is found and noautoconfig is _not_ given
1439 #    on the command line, nothing is changed and the dcs files are
1440 #    searched within the .iso, $dcs-dir is set to the root directory
1441 #    within the .iso
1442 #  - If a GRMLCFG partition is found, $dcs-dir is set to the root of
1443 #    the GRMLCFG partition unless noautoconfig is set. If noautoconfig is
1444 #    set, $dcs-dir is set to the root directory within the .iso.
1445 #  - If myconfig=foo is set on the command line, $dcs-dir is set to
1446 #    foo, even if a GRMLCFG partition is present.
1447 DCSDIR=""
1448 DCSMP="/mnt/grml"
1449 # autoconfig, see issue673
1450 GRMLCFG="$(getbootparam 'autoconfig' 2>>$DEBUG)"
1451 [ -n "$GRMLCFG" ] || GRMLCFG="GRMLCFG"
1452 if checkbootparam 'noautoconfig' || checkbootparam 'forensic' ; then
1453   ewarn "Skipping running automount of device(s) labeled $GRMLCFG as requested." ; eend 0
1454 else
1455   if [ -z "$INSTALLED" ] ; then
1456     if checkbootparam 'myconfig' ; then
1457       DCSDEVICE="$(getbootparam 'myconfig' 2>>$DEBUG)"
1458       if [ -z "$DCSDEVICE" ]; then
1459         eerror "Error: No device for bootoption myconfig provided." ; eend 1
1460       fi # [ -z "$DCSDEVICE" ]
1461     elif checkvalue $CONFIG_MYCONFIG; then # checkbootparam myconfig
1462       einfo "Searching for device(s) labeled with $GRMLCFG. (Disable this via boot option: noautoconfig)" ; eend 0
1463       eindent
1464       # We do need the following fix so floppy disk is available to blkid in any case :-/
1465       if [ -r /dev/fd0 ] ; then
1466         einfo "Floppy device detected. Trying to access floppy disk."
1467         if timeout 4 dd if=/dev/fd0 of=/dev/null bs=512 count=1 >>$DEBUG 2>&1 ; then
1468            blkid /dev/fd0 >>$DEBUG 2>&1
1469         fi
1470       fi
1471       DCSDEVICE=$(blkid -t LABEL=$GRMLCFG | head -1 | awk -F: '{print $1}')
1472       if [ -n "$DCSDEVICE" ]; then
1473         DCSMP="/mnt/grmlcfg"
1474       fi
1475       eoutdent
1476     fi
1477
1478     # if not specified/present then assume default:
1479     if [ -z "$DCSDEVICE" ]; then
1480       DCSDIR="/live/image"
1481     else
1482       eindent
1483       einfo "debs, config, scripts are read from $DCSDEVICE." ; eend 0
1484       DCSDIR="$(< /proc/mounts awk -v DCSDEV=$DCSDEVICE '{if ($1 == DCSDEV) { print $2 }}')"
1485       if [ -n "$DCSDIR" ]; then
1486         ewarn "$DCSDEVICE already mounted on $DCSDIR"; eend 0
1487       else
1488         [ -d $DCSMP ] || mkdir $DCSMP
1489         umount $DCSMP >>$DEBUG 2>&1 # make sure it is not mounted
1490         mount -o ro -t auto $DCSDEVICE  $DCSMP ; RC="$?"
1491         if [[ $RC == 0 ]]; then
1492           einfo "Successfully mounted $DCSDEVICE to $DCSMP (readonly)." ; eend 0
1493         else
1494           eerror "Error: mounting $DCSDEVICE to $DCSMP (readonly) failed." ; eend 1
1495         fi
1496         DCSDIR="$DCSMP"
1497       fi
1498       eoutdent
1499     fi
1500   fi
1501 fi
1502
1503 if [ -n "$DCSDIR" -a "$DCSDIR" != "/live/image" ] ; then
1504   einfo "Debs, config, scripts (if present) will be read from $DCSDIR." ; eend 0
1505 elif checkbootparam 'debs' || checkbootparam 'config' || checkbootparam 'scripts'; then
1506   einfo "Debs, config, scripts will be read from the live image directly." ; eend 0
1507 fi
1508 }
1509
1510
1511 config_partconf() {
1512 if checkbootparam 'partconf' ; then
1513  MOUNTDEVICE="$(getbootparam 'partconf' 2>>$DEBUG)"
1514  if [ -n "$MOUNTDEVICE" ]; then
1515    [ -d /mnt/grml ] || mkdir /mnt/grml
1516    mount -o ro -t auto $MOUNTDEVICE /mnt/grml ; RC="$?"
1517     if [[ $RC == 0 ]]; then
1518       einfo "Successfully mounted $MOUNTDEVICE to /mnt/grml (readonly)." ; eend 0
1519       einfo "Copying files from $MOUNTDEVICE over grml system."
1520       for file in `cat /etc/grml/partconf` ; do
1521         [ -d /mnt/grml/$file ] && cp -a /mnt/grml/${file}* ${file} && echo "copied: $file"
1522         [ -f /mnt/grml/$file ] && cp -a /mnt/grml/${file}  ${file} && echo "copied: $file"
1523       done && eend 0
1524     else
1525       einfo "Could not mount $MOUNTDEVICE to /mnt/grml - sorry." ; eend 1
1526     fi # mount $MOUNTDEVICE
1527    grep -q '/mnt/grml' /proc/mounts && umount /mnt/grml
1528  else
1529    einfo "Sorry, no device for bootoption partconf provided. Skipping." ; eend 1
1530  fi # [ -n "$MOUNTDEVICE" ]
1531 fi
1532 }
1533 # }}}
1534
1535 # {{{ /cdrom/.*-options
1536 config_debs(){
1537 if checkbootparam 'debs' ; then
1538    iszsh && setopt localoptions shwordsplit
1539    DEBS="$(getbootparam 'debs' 2>>$DEBUG)"
1540    if [ -z "$DEBS" ] ; then
1541       DEBS="*.deb"
1542    fi
1543    if ! echo $DEBS | grep -q '/'; then
1544      # backwards compatibility: if no path is given get debs from debs/
1545      DEBS="debs/$DEBS"
1546    fi
1547    einfo "Tring to install debian package(s) ${DEBS}"
1548    DEBS="$(eval echo ${DCSDIR}/$DEBS)"
1549    dpkg -i $DEBS ; eend $?
1550 fi
1551 }
1552
1553 config_scripts(){
1554 if checkbootparam 'scripts' || [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1555    SCRIPTS="$(getbootparam 'scripts' 2>>$DEBUG)"
1556    if [ -d ${DCSDIR}/scripts ] && [ -z "$SCRIPTS" ]; then
1557      SCRIPTS="$(cd ${DCSDIR}/scripts; /bin/ls -1d [Gg][Rr][Mm][Ll].[Ss][Hh] 2>>$DEBUG)"
1558    fi
1559    if ! echo $SCRIPTS | grep -q '/'; then
1560      # backwards compatibility: if no path is given get scripts from scripts/
1561      SCRIPTS="scripts/$SCRIPTS"
1562    fi
1563    if [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1564      # we are executing from a GRMLCFG labeled fs
1565      # kick everything we have done before and start over
1566      SCRIPTS="$(cd ${DCSDIR}; /bin/ls -1d [Gg][Rr][Mm][Ll].[Ss][Hh] 2>>$DEBUG)"
1567    fi
1568    if [ -n "$SCRIPTS" ]; then
1569      SCRIPTS="${DCSDIR}/$SCRIPTS"
1570      if [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1571        einfo "Trying to execute ${SCRIPTS}"
1572        sh -c $SCRIPTS
1573      elif [ -d "$SCRIPTS" ]; then
1574        einfo "Bootparameter scripts found. Trying to execute from directory ${SCRIPTS}:"
1575        run-parts $SCRIPTS
1576      else
1577        einfo "Bootparameter scripts found. Trying to execute ${SCRIPTS}:"
1578        sh -c $SCRIPTS
1579      fi
1580    fi
1581 fi
1582 }
1583
1584 config_config(){
1585 if checkbootparam 'config' || [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1586   CONFIG="$(getbootparam 'config' 2>>$DEBUG)"
1587   if [ -z "$CONFIG" ]; then
1588     CONFIG="$(cd ${DCSDIR}; ls -1d [Cc][Oo][Nn][Ff][Ii][Gg].[Tt][Bb][Zz] 2>>$DEBUG)"
1589   fi
1590   if [ -n "$CONFIG" ]; then
1591     if [ -d "${DCSDIR}/${CONFIG}" ] ; then
1592       einfo "Taking configuration from directory ${DCSDIR}/${CONFIG}"
1593
1594       cp -a ${DCSDIR}/${CONFIG}/* /
1595     elif [ -f "${DCSDIR}/${CONFIG}" ]; then
1596       einfo "Extracting configuration from file ${DCSDIR}/${CONFIG}"
1597
1598       cd /
1599       unp ${DCSDIR}/${CONFIG} $EXTRACTOPTIONS ; eend $?
1600     else
1601       ewarn "Sorry, could not find configuration file or directory ${DCSDIR}/${FILENAME}." ; eend 1
1602     fi
1603   fi
1604 fi
1605 }
1606 # }}}
1607
1608 # {{{ confing_umount_dcsdir
1609 config_umount_dcsdir(){
1610    # umount $DCSMP if it was mounted by finddcsdir
1611    grep -q "$DCSMP" /proc/mounts && umount "$DCSMP"
1612 }
1613 # }}}
1614
1615 # {{{ mypath
1616 config_mypath(){
1617 if checkbootparam 'mypath' ; then
1618    MY_PATH="$(getbootparam 'mypath' 2>>$DEBUG)"
1619    einfo "Bootparameter mypath found, adding ${MY_PATH} to /etc/grml/my_path"
1620    touch /etc/grml/my_path
1621    chmod 644 /etc/grml/my_path
1622    # make sure the directories exist:
1623    eindent
1624    for i in $(echo $MY_PATH | sed 's/:/\n/g') ; do
1625        if ! [ -d "$i" ] ; then
1626           einfo "Creating directory $i"
1627           mkdir -p "$i" ; eend $?
1628        fi
1629    done
1630    grep -q "${MY_PATH}" /etc/grml/my_path || echo "${MY_PATH}" >> /etc/grml/my_path ; eend $?
1631    eoutdent
1632 fi
1633 }
1634 # }}}
1635
1636 # {{{ distcc
1637 config_distcc(){
1638 if checkbootparam 'distcc' ; then
1639  OPTIONS="$(getbootparam 'distcc' 2>>$DEBUG)"
1640  if [ -n "$OPTIONS" ]; then
1641     NET=""
1642     INTERFACE=""
1643     if [ -n "$OPTIONS" ]; then
1644       NET="${OPTIONS%%,*}"
1645       R="${OPTIONS#*,}"
1646       if [ -n "$R" -a "$R" != "$OPTIONS" ]; then
1647         OPTIONS="$R"
1648         INTERFACE="${OPTIONS%%,*}"
1649         R="${OPTIONS#*,}"
1650       fi
1651     fi
1652  fi
1653  CONFIG=/etc/default/distcc
1654  sed -i "s#^STARTDISTCC=.*#STARTDISTCC=YES#"  $CONFIG
1655  sed -i "s#^ALLOWEDNETS=.*#ALLOWEDNETS=$NET#" $CONFIG
1656
1657  if [ -n "$INTERFACE" ] ; then
1658    IP=$(LANG=C ifconfig $INTERFACE | gawk -F: /"inet addr"/'{print $2}' | gawk '{print $1}')
1659
1660    counter=10
1661    while [ -z "$IP" ] && [[ "$counter" != 0 ]] ; do
1662      counter=$(( counter-1 ))
1663      ewarn "No ip address for $INTERFACE found. Sleeping for 3 seconds. $counter tries left."
1664      sleep 3
1665      IP=$(LANG=C ifconfig $INTERFACE | gawk -F: /"inet addr"/'{print $2}' | gawk '{print $1}')
1666    done
1667  fi
1668
1669  if [ -n "$IP" ] ; then
1670    sed -i "s#^LISTENER=.*#LISTENER=$IP#"      $CONFIG
1671
1672    einfo "Bootoption distcc found. Preparing setup for distcc daemon."
1673    eindent
1674     id distccd >/dev/null 2>&1 || \
1675     (
1676       einfo "Creating distcc user" ; \
1677       adduser --quiet --system --ingroup nogroup --home / --no-create-home distccd ; eend $?
1678     )
1679
1680     einfo "Starting distcc for network ${NET}, listening on ${IP}."
1681    /etc/init.d/distcc start >/dev/null ; eend $?
1682    eoutdent
1683  else
1684    eerror "No ip address for $INTERFACE found. distcc can not be used without it." ; eend 1
1685  fi
1686 fi
1687
1688 if checkbootparam 'gcc'; then
1689  GCC="$(getbootparam 'gcc' 2>>$DEBUG)"
1690  eindent
1691  einfo "Pointing /usr/bin/gcc to /usr/bin/gcc-${GCC}."
1692  eoutdent
1693  rm -f /usr/bin/gcc
1694  ln -s /usr/bin/gcc-${GCC} /usr/bin/gcc ; eend $?
1695 fi
1696
1697 if checkbootparam 'gpp'; then
1698  GPP="$(getbootparam 'gpp' 2>>$DEBUG)"
1699  eindent
1700   einfo "Pointing /usr/bin/g++ to /usr/bin/g++-${GPP}."
1701   if [ -x /usr/bin/g++-${GPP} ] ; then
1702      rm -f /usr/bin/g++
1703      ln -s /usr/bin/g++-${GPP} /usr/bin/g++ ; eend $?
1704   fi
1705   einfo "Pointing /usr/bin/cpp to /usr/bin/cpp-${GPP}."
1706   if [ -x /usr/bin/cpp-${GPP} ] ; then
1707      rm -f /usr/bin/cpp
1708      ln -s /usr/bin/cpp-${GPP} /usr/bin/cpp ; eend $?
1709   fi
1710  eoutdent
1711 fi
1712
1713 }
1714 # }}}
1715
1716 # {{{ load modules
1717 # Notice: use it only on live-cd system, if running from harddisk please
1718 # add modules to /etc/modules and activate /etc/init.d/module-init-tools
1719 # in /etc/runlevel.conf
1720 config_modules(){
1721 MODULES_FILE=/etc/grml/modules
1722 if checkbootparam 'nomodules' ; then
1723   ewarn "Skipping loading of modules defined in ${MODULES_FILE} as requested." ; eend 0
1724 elif [ -z "$INSTALLED" ]; then
1725  if [ -r $MODULES_FILE ] ; then
1726   einfo "Loading modules specified in ${MODULES_FILE}:"
1727   eindent
1728   grep '^[^#]' $MODULES_FILE | \
1729   while read module args; do
1730     [ "$module" ] || continue
1731       einfo "${module}"
1732       modprobe $module $args ; eend $?
1733   done
1734   eoutdent
1735  else
1736   ewarn "File $MODULES_FILE does not exist. Skipping loading of specific modules." ; eend 1
1737  fi
1738 fi
1739 }
1740 # }}}
1741
1742 # {{{ 915resolution
1743 config_915resolution(){
1744 if checkbootparam '915resolution' ; then
1745  OPTIONS="$(getbootparam '915resolution' 2>>$DEBUG)"
1746   if [ -x /usr/sbin/915resolution ]; then
1747     CMD=915resolution
1748     MODE=""
1749     XRESO=""
1750     YRESO=""
1751     if [ -n "$OPTIONS" ]; then
1752       # Extra options
1753       MODE="${OPTIONS%%,*}"
1754       R="${OPTIONS#*,}"
1755       if [ -n "$R" -a "$R" != "$OPTIONS" ]; then
1756         OPTIONS="$R"
1757         XRESO="${OPTIONS%%,*}"
1758         R="${OPTIONS#*,}"
1759         if [ -n "$R" -a "$R" != "$OPTIONS" ]; then
1760           OPTIONS="$R"
1761           YRESO="${OPTIONS%%,*}"
1762           R="${OPTIONS#*,}"
1763         fi
1764       fi
1765     fi
1766     einfo "Running 915resolution with options ${MODE} ${XRESO} ${YRESO}."
1767     [ -n "$MODE" ] && [ -n "$XRESO"  ] && [ -n "$YRESO" ]  && ( sh -c "$CMD $MODE $XRESO $YRESO" & )
1768     eend 0
1769   fi
1770 fi
1771 }
1772 # }}}
1773
1774 # {{{ SW-RAID
1775 config_swraid(){
1776   [ -n "$INSTALLED" ] && return 0
1777
1778   # notice: checkbootparam "forensic" is just for users who don't know how to really use the bootoption
1779   if checkbootparam 'noraid'   || checkbootparam 'noswraid' || \
1780      checkbootparam 'forensic' || checkbootparam 'raid=noautodetect' ; then
1781      ewarn "Skipping SW-RAID code as requested on boot commandline." ; eend 0
1782   else
1783     if ! [ -x /sbin/mdadm ] ; then
1784        eerror "mdadm not available, can not execute it." ; eend 1
1785     else
1786
1787        # if ! egrep -qv '^(MAILADDR.*|#.*|)$' /etc/mdadm/mdadm.conf 2>>$DEBUG ; then
1788        # find out whether we have a valid configuration file already
1789        if ! grep -q ARRAY /etc/mdadm/mdadm.conf 2>>$DEBUG ; then
1790           einfo "Creating /etc/mdadm/mdadm.conf for use with mdadm."
1791           [ -r /etc/mdadm/mdadm.conf ] && mv /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.old
1792           MDADM_MAILADDR__='root' /usr/share/mdadm/mkconf > /etc/mdadm/mdadm.conf ; eend $?
1793         else
1794           ewarn "/etc/mdadm/mdadm.conf looks like a configured mdadm setup, will not touch it." ; eend 0
1795        fi
1796
1797        if ! checkbootparam 'swraid' ; then
1798           eindent
1799           einfo "Just run 'Start mdadm-raid' to assemble md arrays or boot using 'swraid' as bootoption for autostart."
1800           eoutdent
1801        else
1802           einfo "Bootoption swraid found. Searching for software RAID arrays:"
1803           eindent
1804            IFSOLD=${IFS:-}
1805            IFS='
1806 '
1807            for line in $(mdadm --assemble --scan --auto=yes --symlink=no 2>&1) ; do
1808                case $line in
1809                  *'No arrays found'*)
1810                    ewarn "$line" ; eend 0
1811                    ;;
1812                  *)
1813                    einfo "$line" ; eend 0
1814                    ;;
1815                esac
1816            done
1817            IFS=$IFSOLD
1818          eoutdent
1819
1820          if [ -r /proc/mdstat ] ; then
1821             eindent
1822             MDSTAT=$(grep '^md[0-9]' /proc/mdstat)
1823             if [ -z "$MDSTAT" ] ; then
1824                ewarn "No active arrays found" ; eend 0
1825             else
1826                IFSOLD=${IFS:-}
1827                IFS='
1828 '
1829                for line in $(grep '^md[0-9]' /proc/mdstat) ; do
1830                    einfo "active arrays: $line" ; eend 0
1831                done
1832                IFS=$IFSOLD
1833             fi
1834             eoutdent
1835          fi # /proc/mdstat
1836        fi # bootoption swraid
1837
1838      fi # is /sbin/mdadm executable?
1839   fi # check for bootoptions
1840 }
1841 # }}}
1842
1843 # {{{ dmraid
1844 config_dmraid(){
1845   [ -n "$INSTALLED" ] && return 0
1846
1847   if checkbootparam 'nodmraid' ; then
1848     ewarn "Skipping dmraid code as requested on boot commandline." ; eend 0
1849     return 0
1850   fi
1851
1852   if ! [ -x /sbin/dmraid ] ; then
1853     eerror "dmraid not available, can not execute it." ; eend 1
1854     return
1855   fi
1856
1857   dmraid_wrapper() {
1858     # usage: dmraid_wrapper <dmraid_option>
1859     [ -n "$1" ] || return 1
1860
1861     IFSOLD=${IFS:-}
1862     IFS='
1863 '
1864     eindent
1865
1866     for line in $(dmraid $1 ; echo errcode:$?); do
1867       case $line in
1868         *'no block devices found'*)
1869           einfo "No block devices found" ; eend 0
1870           break
1871           ;;
1872         *'no raid disks'*)
1873           einfo "No active dmraid devices found" ; eend 0
1874           break
1875           ;;
1876         errcode:0)
1877           eend 0;
1878           ;;
1879         errcode:1)
1880           eend 1
1881           ;;
1882         *)
1883           einfo "$line"
1884           ;;
1885       esac
1886     done
1887
1888     eoutdent
1889     IFS=$IFSOLD
1890   }
1891
1892   if checkbootparam 'dmraid' ; then
1893     local ACTION="$(getbootparam 'dmraid' 2>>$DEBUG)"
1894     if [ "$ACTION" = "off" ] ; then
1895       # Deactivates all active software RAID sets:
1896       einfo "Deactivating present dmraid sets (as requested via dmraid=off):"
1897       dmraid_wrapper -an
1898     else
1899       # Activate all software RAID sets discovered:
1900       einfo "Activating present dmraid sets (as requested via dmraid):"
1901       dmraid_wrapper -ay
1902     fi
1903
1904     return
1905   fi
1906
1907   # by default (no special bootoptions) discover all software RAID devices:
1908   einfo "Searching for any present dmraid sets:"
1909   dmraid_wrapper -r
1910 }
1911 # }}}
1912
1913 # {{{ LVM (Logical Volumes)
1914 config_lvm(){
1915   [ -n "$INSTALLED" ] && return 0
1916
1917   if checkbootparam 'nolvm' ; then
1918      ewarn "Skipping LVM code as requested on boot commandline." ; eend 0
1919   else
1920     # Debian etch provides /etc/init.d/lvm only, newer suites provide /etc/init.d/lvm2
1921     if ! [ -x /sbin/lvm -a -x /sbin/lvdisplay ] || ! [ -x /etc/init.d/lvm2 -o -x /etc/init.d/lvm ] ; then
1922        eerror "LVM not available, can not execute it." ; eend 1
1923     else
1924        if lvdisplay 2>&1 | grep -v 'No volume groups found' >/dev/null 2>&1 ; then
1925           einfo "You seem to have logical volumes (LVM) on your system."
1926           eindent
1927           einfo "Just run 'Start lvm2' to activate them or boot using 'lvm' as bootoption for autostart."
1928           eend 0
1929           if checkbootparam 'lvm' ; then
1930              einfo "Bootoption LVM found. Searching for logical volumes:"
1931              /etc/init.d/lvm2 start ; eend $?
1932           fi
1933           eoutdent
1934        fi
1935     fi # check for lvm binary
1936   fi # check for bootoption nolvm
1937 }
1938 # }}}
1939
1940 # {{{ debnet: setup network based on an existing one found on a partition
1941 config_debnet(){
1942 if checkbootparam 'debnet' ; then
1943  einfo "Bootoption 'debnet' found. Searching for Debian network configuration: "
1944  /usr/sbin/debnet
1945 fi
1946 }
1947 # }}}
1948
1949 # {{{ disable console blanking
1950 config_blanking(){
1951 if checkbootparam 'noblank' ; then
1952   einfo "Bootoption noblank found. Disabling monitor blanking."
1953   setterm -blank 0 ; eend $?
1954 fi
1955 }
1956 # }}}
1957
1958 # {{{ tohd= bootoption
1959 config_tohd()
1960 {
1961   if checkbootparam 'tohd' ; then
1962      local TARGET="$(getbootparam 'tohd' 2>>$DEBUG)"
1963      if [ -z "$TARGET" ] ; then
1964         eerror "Error: tohd specified without any partition, can not continue." ; eend 1
1965         eerror "Please use something like tohd=/dev/sda9." ; eend 1
1966         return 1
1967      fi
1968
1969      if ! [ -b "$TARGET" ] ; then
1970         eerror "Error: $TARGET is not a valid block device, sorry." ; eend 1
1971         return 1
1972      fi
1973
1974      if grep -q $TARGET /proc/mounts ; then
1975         eerror "$TARGET already mounted, skipping execution of tohd therefore."
1976         eend 1
1977         return 1
1978      fi
1979
1980      local MOUNTDIR=$(mktemp -d)
1981
1982      if mount -o rw "$TARGET" "$MOUNTDIR" ; then
1983         einfo "Copyring live system to $TARGET - this might take a while"
1984         rsync -a --progress /live/image/live $MOUNTDIR
1985         sync
1986         umount "$MOUNTDIR"
1987         eend $?
1988         einfo "Booting with \"grml bootfrom=$TARGET\" should work now." ; eend 0
1989      else
1990         eerror "Error when trying to mount $TARGET, sorry."; eend 1
1991         return 1
1992      fi
1993
1994      rmdir "$MOUNTDIR"
1995   fi
1996 }
1997 # }}}
1998
1999 # {{{ grml2hd: automatic installation
2000 config_grml2hd(){
2001
2002 if checkbootparam "grml2hd" || checkbootparam "BOOT_IMAGE=grml2hd" ; then
2003
2004 if checkbootparam 'user' ; then
2005    NEWUSER=''
2006    NEWUSER="$(getbootparam 'user' 2>>$DEBUG)"
2007    sed -i "s/^NEWUSER=.*/NEWUSER=$NEWUSER/" /etc/grml2hd/config || export GRML2HD_FAIL=1
2008 fi
2009
2010 if checkbootparam 'filesystem' ; then
2011    FILESYSTEM=''
2012    FILESYSTEM="$(getbootparam 'filesystem' 2>>$DEBUG)"
2013    sed -i "s/^FILESYSTEM=.*/FILESYSTEM=$FILESYSTEM/" /etc/grml2hd/config || export GRML2HD_FAIL=1
2014 fi
2015
2016 if checkbootparam 'partition' ; then
2017    PARTITION=''
2018    PARTITION="$(getbootparam 'partition' 2>>$DEBUG)"
2019    # notice: the following checks whether the given partition is available, if not the skip
2020    # execution of grml2hd as it might result in data loss...
2021    if [ -r $PARTITION ] ; then
2022       sed -i "s#^PARTITION=.*#PARTITION=$PARTITION#" /etc/grml2hd/config || export GRML2HD_FAIL=1
2023    else
2024       ewarn "Partition $PARTITION does not exist. Skipping execution of grml2hd therefore." ; eend 1
2025    fi
2026 fi
2027
2028 if checkbootparam 'mbr' ; then
2029    BOOT_PARTITION=''
2030    BOOT_PARTITION="$(getbootparam 'mbr' 2>>$DEBUG)"
2031    sed -i "s#^BOOT_PARTITION=.*#BOOT_PARTITION=$BOOT_PARTITION#" /etc/grml2hd/config || export GRML2HD_FAIL=1
2032 fi
2033
2034 cat>|/usr/bin/grml2hd_noninteractive<<EOF
2035 #!/bin/sh
2036 GRML2HD_NONINTERACTIVE='yes' grml2hd
2037 EOF
2038
2039 chmod 755 /usr/bin/grml2hd_noninteractive
2040 einfo "Bootoption grml2hd found. Running automatic installation via grml2hd using /etc/grml2hd/config." && eend 0
2041 if [ -z "$GRML2HD_FAIL" ] ; then
2042    screen /usr/bin/grml2hd_noninteractive ; einfo "Invoking a shell, just exit to continue booting..." ; /bin/zsh
2043 else
2044    ewarn "There was an error adjusting /etc/grml2hd/config. Skipping execution of grml2hd for security reasons." ; eend 1
2045 fi
2046
2047 fi # if checkbootparam "BOOT_IMAGE=grml2hd ...
2048 }
2049 # }}}
2050
2051 # {{{ debootstrap: automatic installation
2052 config_debootstrap(){
2053
2054 if checkbootparam "BOOT_IMAGE=debian2hd" || checkbootparam "debian2hd" ; then
2055
2056 einfo "Bootoption debian2hd found. Setting up environment for automatic installation via grml-debootstrap." ; eend 0
2057
2058 if ! [ -x /usr/sbin/grml-debootstrap ] ; then
2059    eindent
2060    eerror "Bootoption debian2hd found, but grml-debootstrap is not available." ; eend 1
2061    eoutdent
2062    exit 1
2063 fi
2064
2065 if checkbootparam 'target' ; then
2066   TARGET=''
2067   TARGET="$(getbootparam 'target' 2>>$DEBUG)"
2068   # notice: the following checks whether the given partition is available, if not the skip
2069   # execution of grml-debootstrap as it might result in data loss...
2070   if ! [ -r "$TARGET" ] ; then
2071      eerror "Target $TARGET does not exist. Skipping execution of grml-debootstrap therefore." ; eend 1
2072   fi
2073 else
2074   eindent
2075   eerror "No bootoption named target found, can not continue execution of grml-debootstrap." ; eend 1
2076   eoutdent
2077   exit 1
2078 fi
2079
2080 if checkbootparam 'grub' ; then
2081   GRUB=''
2082   GRUB="$(getbootparam 'grub' 2>>$DEBUG)"
2083 fi
2084
2085 if checkbootparam 'groot' ; then
2086   GROOT=''
2087   GROOT="$(getbootparam 'groot' 2>>$DEBUG)"
2088 fi
2089
2090 if checkbootparam 'release' ; then
2091   RELEASE=''
2092   RELEASE="$(getbootparam 'release' 2>>$DEBUG)"
2093 fi
2094
2095 if checkbootparam 'mirror' ; then
2096   MIRROR=''
2097   MIRROR="$(getbootparam 'mirror' 2>>$DEBUG)"
2098 fi
2099
2100 if checkbootparam 'boot_append' ; then
2101   BOOT_APPEND=''
2102   BOOT_APPEND="$(getbootparam 'boot_append' 2>>$DEBUG)"
2103 fi
2104
2105 if checkbootparam 'password' ; then
2106   PASSWORD=''
2107   PASSWORD="$(getbootparam 'password' 2>>$DEBUG)"
2108 fi
2109
2110 # now check which options are available
2111 if [ -n "TARGET" ] ; then
2112    TARGETCMD="--target $TARGET"
2113 else
2114    TARGETCMD=''
2115    eindent
2116    eerror "Target not set via bootoption. Skipping execution of grml-debootstrap therefore."; eend 1
2117    eoutdent
2118    exit 1
2119 fi
2120 [ -n "$GRUB" ]     && GRUBCMD="--grub $GRUB"               || GRUBCMD=''
2121 [ -n "$GROOT" ]    && GROOTCMD="--groot $GROOT"            || GROOTCMD=''
2122 [ -n "$RELEASE" ]  && RELEASECMD="--release $RELEASE"      || RELEASECMD=''
2123 [ -n "$MIRROR" ]   && MIRRORCMD="--mirror $MIRROR"         || MIRRORCMD=''
2124 [ -n "$PASSWORD" ] && PASSWORDCMD="--password $PASSWORD"   || PASSWORDCMD=''
2125 [ -n "$BOOT_APPEND" ] && BOOT_APPEND="--boot_append $BOOT_APPEND" || BOOT_APPEND=''
2126
2127 # and finally write script and execute it
2128 cat>|/usr/bin/grml-debootstrap_noninteractive<<EOF
2129 #!/bin/sh
2130 AUTOINSTALL='yes' grml-debootstrap $TARGETCMD $GRUBCMD $GROOTCMD $RELEASECMD $MIRRORCMD $PASSWORDCMD $BOOT_APPEND
2131 EOF
2132
2133 chmod 750  /usr/bin/grml-debootstrap_noninteractive
2134
2135 screen /usr/bin/grml-debootstrap_noninteractive
2136 einfo "Invoking a shell, just exit to continue booting..."
2137 /bin/zsh
2138
2139 fi # checkbootparam "BOOT_IMAGE=debian2hd
2140 }
2141 # }}}
2142
2143 config_virtualbox_shared_folders() {
2144 if [ -r /proc/acpi/battery/BAT0/info ] && grep -q 'OEM info:.*innotek' /proc/acpi/battery/BAT0/info ; then
2145   einfo "VirtualBox detected, trying to set up Shared Folders."
2146   if ! modprobe -l | grep -q vboxsf.ko ; then
2147     ewarn "vboxsf driver not present, not setting up VirtualBox Shared Folders."
2148     eend 0
2149   elif ! [ -x /usr/sbin/VBoxService ] ; then
2150     ewarn "virtualbox-guest-utils not installed, not setting up VirtualBox Shared Folders."
2151     eend 0
2152   else
2153     eindent
2154
2155       einfo "Loading vboxsf driver."
2156       lsmod | grep -q vboxsf || modprobe vboxsf
2157       eend $?
2158
2159       einfo "Adjusting /dev/vboxguest."
2160       chown root:vboxsf /dev/vboxguest
2161       chmod 660 /dev/vboxguest
2162       eend $?
2163
2164       if [ -n "$CONFIG_FSTAB_USER" ] ; then
2165         fstabuser="$CONFIG_FSTAB_USER"
2166       else
2167         fstabuser=$(getent passwd 1000 | cut -d: -f1)
2168       fi
2169       einfo "Adding $fstabuser to group vboxsf."
2170       adduser grml vboxsf &>/dev/null
2171       eend $?
2172
2173       einfo "Starting VBoxService."
2174       VBoxService >/dev/null &
2175       eend $?
2176
2177     eoutdent
2178   fi
2179 fi
2180 }
2181
2182 # {{{ Support customization
2183 config_distri(){
2184 if checkbootparam 'distri'; then
2185   DISTRI="$(getbootparam 'distri' 2>>$DEBUG)"
2186   if [ -r "${LIVECD_PATH}"/desktop/"$DISTRI".jpg ] ; then
2187      [ -n "$BOOTDEBUG" ] && einfo "Debug: bootoption distri found and file ${LIVECD_PATH}/desktop/${DISTRI} present" && eend 0
2188      # make sure the desktop.jpg file is not a symlink, so copying does not file then
2189      [ -L /usr/share/grml/desktop.jpg ] && rm /usr/share/grml/desktop.jpg
2190      cp "${LIVECD_PATH}"/desktop/"$DISTRI".jpg /usr/share/grml/desktop.jpg
2191   fi
2192 fi
2193 }
2194 # }}}
2195
2196 ## END OF FILE #################################################################
2197 # vim:foldmethod=marker expandtab ai ft=zsh shiftwidth=3