Release new version v0.9.44.
[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"
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 $TIMEOUT > /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 # {{{ mount configfs
403 config_configfs() {
404   einfo "Mounting configfs"
405   CONFIGFS_DIR=/sys/kernel/config/
406   modprobe configfs 2>/dev/null 1>&2
407   if ! [  -d "$CONFIGFS_DIR" ] ; then
408     eindent
409     einfo "$CONFIGFS_DIR does not exist, can't mount directory"
410     eend 1
411     eoutdent
412   else
413     mount -t configfs configfs "$CONFIGFS_DIR" 2>/dev/null 1>&2
414     eend $?
415   fi
416 }
417 # }}}
418
419 # {{{ Set clock (Local time is more often used than GMT, so it is default)
420 config_time(){
421  # don't touch the files if running from harddisk:
422  if [ -z "$INSTALLED" ]; then
423     # The default hardware clock timezone is stated as representing local time.
424     UTC="--localtime"
425     grep -q "^UTC=" /etc/default/rcS || echo "UTC=no" >> /etc/default/rcS
426     checkbootparam 'utc'       >>$DEBUG 2>&1 && sed -i "s|^UTC=.*$|UTC=yes|" /etc/default/rcS
427     checkbootparam 'gmt'       >>$DEBUG 2>&1 && sed -i "s|^UTC=.*$|UTC=yes|" /etc/default/rcS
428     checkbootparam 'localtime' >>$DEBUG 2>&1 && sed -i "s|^UTC=.*$|UTC=no|"  /etc/default/rcS
429     grep -q -i "^UTC=yes" /etc/default/rcS && UTC="-u"
430     # hwclock uses the TZ variable
431     KTZ="$(getbootparam 'tz' 2>>$DEBUG)"
432     [ -z "$KTZ" ] && [ -r /etc/timezone ] && KTZ=$(cat /etc/timezone)
433     if [ ! -f "/usr/share/zoneinfo/$KTZ" ] ; then
434        ewarn "Warning: unknown timezone $KTZ" ; eend 1
435        KTZ="Europe/Vienna"
436        ewarn "Falling back to timezone $KTZ" ; eend 0
437     fi
438
439     if ! [ -r /dev/rtc ] ; then
440       ewarn "Warning: realtime clock not available, trying to execute hwclock anyway." ; eend 0
441     fi
442
443     ERROR=$(TZ="$KTZ" hwclock $UTC -s 2>&1 | head -1) ; RC=$?
444     if [ -n "$ERROR" ] ; then
445        eindent
446        ERROR=$(TZ="$KTZ" hwclock $UTC -s --directisa 2>&1 | head -1)
447        if [ -n "$ERROR" ] ; then
448           eerror "Problem running hwclock: $ERROR" ; eend 1
449        fi
450        eoutdent
451     fi
452
453  fi
454 }
455 # }}}
456
457 # {{{ print kernel info
458 config_kernel(){
459   vmware-detect &>/dev/null && VMWARE="inside ${WHITE}VMware/Qemu${NORMAL}"
460   [ -d /proc/xen ] && VMWARE='' # vmware-detect returns '0' when running with a Xen-enabled kernel
461   einfo "Running Linux Kernel $KERNEL $VMWARE" ; eend 0
462   if [ -r /proc/cpuinfo ] ; then
463      if egrep -q '^flags.*(vmx|svm)' /proc/cpuinfo ; then
464        eindent
465        einfo 'CPU(s) featuring virtualization technology detected' ; eend 0
466        eoutdent
467      fi
468   fi
469   if [ -d /proc/xen ] ; then
470      eindent
471      einfo 'Running kernel featuring support for Xen detected' ; eend 0
472      eoutdent
473   fi
474 }
475 # }}}
476
477 # {{{ ld.so.cache + depmod
478 config_ld_mod(){
479 if [ -n "$INSTALLED" ]; then
480  if ! [ -r /etc/grml.first.boot ] ; then
481   einfo "Running from HD for the first time, regenerate ld.so.cache and modules.dep:"
482   eindent
483 # Regenerate ld.so.cache and module dependencies on HD
484     einfo "Running ldconfig" ; ldconfig  ; eend $?
485     einfo "Running depmod"   ; depmod -a ; eend $?
486     touch /etc/grml.first.boot
487     eend 0
488   eoutdent
489  fi
490 fi
491 }
492 # }}}
493
494 # {{{ timezone
495 config_timezone(){
496  # don't touch the files if running from harddisk:
497  if [ -z "$INSTALLED" ]; then
498     KTZ="$(getbootparam 'tz' 2>>$DEBUG)"
499     if [ -n "$KTZ" ] ; then
500        if [ ! -f "/usr/share/zoneinfo/$KTZ" ]
501        then
502           ewarn "Warning: unknown timezone $KTZ"; eend 0
503        else
504           einfo "Setting timezone."
505           # update debconf
506           area=$(echo $KTZ | cut -d '/' -f1)
507           zone=$(echo $KTZ | cut -d '/' -f2)
508           echo "tzdata tzdata/Areas       select $area" | debconf-set-selections
509           echo "tzdata tzdata/Zones/$area select $zone" | debconf-set-selections
510           # update files
511           echo $KTZ > /etc/timezone
512           rm -f /etc/localtime
513           cp "/usr/share/zoneinfo/$KTZ" /etc/localtime ; eend $?
514        fi
515     fi
516  fi
517 }
518 # }}}
519
520 # small computer / nearly no ram {{{
521 config_small(){
522
523 RAM=$(/usr/bin/gawk '/MemTotal/{print $2}' /proc/meminfo)
524 # MEM=$(/usr/bin/gawk 'BEGIN{m=0};/MemFree|Cached|SwapFree/{m+=$2};END{print m}' /proc/meminfo)
525 eindent
526
527 if checkbootparam 'small'; then
528   einfo "Information: ${RAM} kB of RAM available." ; eend 0
529   einfo "Bootoption small detected. Activating small system."
530   if [ -r /etc/inittab.small ] ; then
531     mv /etc/inittab /etc/inittab.normal
532     mv /etc/inittab.small /etc/inittab
533   else
534     sed -i 's/^9/#&/' /etc/inittab
535     sed -i 's/^10/#&/' /etc/inittab
536     sed -i 's/^11/#&/' /etc/inittab
537     sed -i 's/^12/#&/' /etc/inittab
538   fi
539   /sbin/telinit q ; eend $?
540 else
541   if checkgrmlsmall ; then
542     if [[ $RAM -lt 25000 ]] ; then
543       ewarn "Information: ${RAM} kB of RAM available." ; eend 1
544       ewarn "At least 32MB of RAM should be available for grml-small." ; eend 1
545       ewarn "Use the bootoption small to save some more MB of memory usage." ; eend 0
546       ewarn "Dropping you into a rescue shell. To continue booting exit the shell." ; eend 0
547       /bin/zsh --login
548     else
549       einfo "Information: ${RAM} kB of RAM available." ; eend 0
550     fi
551   else
552     if [[ $RAM -lt 58000 ]] ; then
553       ewarn "Information: ${RAM} kB of RAM available." ; eend 1
554       ewarn "At least 64MB of RAM should be available for grml." ; eend 1
555       ewarn "Use the bootoption small to save some more MB of memory usage." ; eend 0
556       ewarn "Dropping you into a rescue shell. To continue booting exit the shell." ; eend 0
557       /bin/zsh --login
558     else
559       einfo "Information: ${RAM} kB of RAM available." ; eend 0
560     fi
561   fi
562 fi
563 eoutdent
564 }
565 # }}}
566
567 # skip startup of w3m {{{
568 config_fast(){
569 if checkbootparam 'fast'; then
570   ewarn "Bootoption fast detected. Skipping startup of grml-quickconfig."
571     sed -i '/1:/s#/usr/share/grml-scripts/run-welcome#/bin/zsh#' /etc/inittab
572   /sbin/telinit q ; eend $?
573 fi
574 }
575 # }}}
576
577 # activate serial console {{{
578 config_console(){
579 if checkbootparam 'console'; then
580   local line
581   local ws
582   ws='   '
583
584   einfo "Bootoption for serial console detected:"
585
586   line="$CMDLINE x "
587   this=""
588   line="${line#*[$ws]}"
589   local telinitq=""
590   while [ -n "$line" ]; do
591     case "$this" in
592       console=*)
593         local serial="$this"
594         local device="${this%%,*}"
595         local device="${device##*=}"
596         if echo $serial | grep -q ttyS ; then
597           local option="${serial##*,}"
598           # default (works for kvm & CO):
599           local speed="115200,57600,38400,19200,9600,4800,2400,1200";
600           # ... unless overriden by command line:
601           case "$option" in
602             115200*) speed=115200 ;;
603              57600*) speed=57600 ;;
604              38400*) speed=38400 ;;
605              19200*) speed=19200 ;;
606               9600*) speed=9600 ;;
607               4800*) speed=4800 ;;
608               2400*) speed=2400 ;;
609               1200*) speed=1200 ;;
610           esac
611           eindent
612             einfo "Activating console login on device ${device} with speed ${speed}."
613             local number="${device#ttyS}"
614             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
615             eend $?
616             telinitq="1"
617           eoutdent
618         fi
619         ;;
620     esac
621     this="${line%%[$ws]*}"
622     line="${line#*[$ws]}"
623   done
624
625   if [ -n "$telinitq" ]; then
626     /sbin/telinit q
627   fi
628   eend $?
629 fi
630 }
631 # }}}
632
633 # {{{ copy passwd-lockfile to ramdisk (fix unionfs-behaviour)
634 # otherwise we will get: passwd: Authentication token lock busy
635 config_fix_passwd(){
636  if [ -z "$INSTALLED" ] ; then
637   touch /etc/.pwd.lock
638  fi
639 }
640 # }}}
641
642 # {{{ CD Checker
643 config_testcd(){
644 if [ -n "$TESTCD" ]; then
645    einfo "Checking CD data integrity as requested by '${WHITE}testcd${NORMAL}' boot option."
646    einfo "Reading files and checking against GRML/md5sums, this may take a while..."
647    echo -n "${RED}"
648
649    if [ -n "${LIVECD_PATH}"/GRML ] ; then
650       ( cd "${LIVECD_PATH}"/GRML ; rm -f /tmp/md5sum.log ; md5sum -c md5sums 2>&1 | tee /tmp/md5sum.log ; RC=$? )
651    else
652       echo "${RED} *** Error: Could not find md5sum file.                           ***"
653    fi
654
655    if [ "$RC" = "0" ]; then
656       einfo "Everything looks OK" ; eend 0
657    else
658       eerror 'Checksum failed for theses files:' ; eend 1
659       egrep -v '(^md5sum:|OK$)' /tmp/md5sum.log
660       eerror 'Data on the grml medium is possibly incomplete/damaged or...'
661       eerror '... RAM of your computer is broken.' ; eend 1
662       einfon "Hit return to continue, or press the reset button to quit."
663      read a
664    fi
665
666    eend 0
667 fi
668 }
669 # }}}
670
671 # {{{ blacklist specific module [ used in /etc/init.d/udev ]
672 config_blacklist(){
673 if checkbootparam 'blacklist' ; then
674  if [ -z "$INSTALLED" ]; then
675   einfo "Bootoption blacklist found."
676   BLACK="$(getbootparam 'blacklist' 2>>$DEBUG)"
677   BLACKLIST_FILE='/etc/modprobe.d/grml.conf'
678   if [ -n "$BLACK" ] ; then
679     for module in $(echo ${BLACK//,/ }) ; do
680         einfo "Blacklisting module ${module} via ${BLACKLIST_FILE}."
681         echo "# begin entry generated by config_blacklist of grml-autoconfig" >> "$BLACKLIST_FILE"
682         echo "blacklist $module"     >> "$BLACKLIST_FILE"
683         echo "alias     $module off" >> "$BLACKLIST_FILE"
684         echo "# end   entry generated by config_blacklist of grml-autoconfig" >> "$BLACKLIST_FILE" ; eend $?
685     done
686   else
687    eerror "No given module for blacklist found. Blacklisting will not work therefore."
688   fi
689  else
690   ewarn "Backlisting via bootoption is not intended for use on harddisk installations." ; eend 1
691   eindent
692    einfo "Please blacklist the module(s) manually using the 'blacklist' script."
693   eoutdent
694  fi
695 fi
696 }
697 # }}}
698
699 # {{{ ACPI
700 config_acpi(){
701 if checkbootparam 'noacpi'; then
702   ewarn "ACPI: Not loading modules as requested by boot option \"noacpi\"." ; eend 0
703 elif checkbootparam 'nogrmlacpi' ; then
704   ewarn "ACPI: Not loading modules as requested by boot option \"nogrmlacpi\"." ; eend 0
705 elif [ ! -d /proc/acpi ] ; then
706   ewarn "ACPI: Kernel support not present." ; eend 0
707 else
708   einfo "ACPI: Loading modules (disable with boot option noacpi / nogrmlacpi): "
709   eindent
710   found=""
711   for a in /lib/modules/$KERNEL/kernel/drivers/acpi/*; do
712     basename="${a##*/}"
713     basename="${basename%%.*}"
714     case "$basename" in *_acpi)
715      egrep -qi "${basename%%_acpi}" /proc/acpi/dsdt 2>>$DEBUG || continue ;;
716     esac
717     modprobe $basename >>$DEBUG 2>&1 && found="yes"
718     local BASE="$BASE $basename"
719   done
720   if [ -n "$found" ] ; then
721     einfo "$BASE"  ; eend 0
722   else
723     ewarn "(none)" ; eend 1
724   fi
725   if ! pgrep acpid >/dev/null ; then
726     einfo "Starting acpi daemon."
727     /etc/init.d/acpid start >>$DEBUG 2>&1 ; eend $?
728   else
729     ewarn "acpi daemon already running."
730     eend 0
731   fi
732   eoutdent
733 fi
734 }
735 # }}}
736
737 # {{{ Collect partitions from /proc/partitions first for enabling DMA
738 check_partitions(){
739 partitions=""
740 IDEDISKS=""
741 while read major minor blocks partition relax; do
742   partition="${partition##*/}"
743   [ -z "$partition" -o ! -e "/dev/$partition" ] && continue
744   case "$partition" in
745     hd?) IDEDISKS="$IDEDISKS $partition";;                # IDE  Harddisk, entire disk
746     sd?) ;;                                               # SCSI Harddisk, entire disk
747 #    [hs]d*) partitions="$partitions /dev/$partition";;    # IDE or SCSI disk partition
748     [hs]d*|ub*) partitions="$partitions /dev/$partition";;    # IDE, USB or SCSI disk partition
749   esac
750 done <<EOT
751 $(awk 'BEGIN{old="__start"}{if($0==old){exit}else{old=$0;if($4&&$4!="name"){print $0}}}' /proc/partitions)
752 EOT
753 }
754 check_partitions >/dev/null 2>&1 # avoid output "check_partitions:3: read-only file system"
755 # }}}
756
757 # {{{ Enable DMA for all IDE drives now if not disabled
758 # Notice: Already done by linuxrc, but make sure it's done also on harddisk-installed systems
759 config_dma(){
760 if checkbootparam 'nodma'; then
761   ewarn "Skipping DMA accelleration as requested on boot commandline." ; eend 0
762 else
763   for d in $(cd /proc/ide 2>>$DEBUG && echo hd[a-z]); do
764     if test -d /proc/ide/$d; then
765       if egrep -q 'using_dma[ \t]+0' /proc/ide/$d/settings 2>>$DEBUG; then
766         MODEL="$(cat /proc/ide/$d/model 2>>$DEBUG)"
767         test -z "$MODEL" && MODEL="[GENERIC IDE DEVICE]"
768         einfo "Enabling DMA acceleration for: ${WHITE}$d        ${YELLOW}[${MODEL}]${NORMAL}"
769         echo "using_dma:1" >/proc/ide/$d/settings
770         eend 0
771       fi
772     fi
773   done
774 fi
775 }
776 # }}}
777
778 # {{{ Start creating /etc/fstab with HD partitions and USB SCSI devices now
779 config_fstab(){
780
781 NOSWAP="yes" # we do not use swap by default!
782 if checkbootparam 'swap' || checkbootparam 'anyswap' ; then
783    NOSWAP=''
784    checkbootparam 'anyswap' && export ANYSWAP='yes' || export ANYSWAP=""
785 fi
786
787 # Scan for swap, config, homedir - but only in live-mode
788 if [ -z "$INSTALLED" ] ; then
789    [ -z "$NOSWAP" ] && einfo "Searching for swap partition(s) as requested."
790    GRML_IMG=""
791    GRML_SWP=""
792    HOMEDIR="$(getbootparam 'home')"
793    if [ -n "$partitions" ]; then
794       while read p m f relax; do
795         case "$p" in *fd0*|*proc*|*sys*|*\#*) continue;; esac
796         partoptions="users,exec"
797         fnew=""
798         # it's a swap partition?
799         case "$f" in swap)
800           eindent
801           if [ -n "$NOSWAP" ]; then
802              ewarn "Ignoring swap partition ${WHITE}$p${NORMAL}. (Force usage via boot option 'swap', or execute grml-swapon)"
803              eend 0
804           else
805              case "$(dd if=$p bs=1 count=6 skip=4086 2>/dev/null)" in
806                    S1SUSP|S2SUSP|pmdisk|[zZ]*)
807                      if [ -n "$ANYSWAP" ] ; then
808                         einfo "Using swap partition ${WHITE}${p}${NORMAL} [bootoption anyswap found]."
809                         swapon $p 2>>$DEBUG ; eend $?
810                      else
811                         ewarn "Suspend signature on ${WHITE}${p}${NORMAL} found, not using as swap. (Force usage via boot option: anyswap)"
812                      fi
813                      ;;
814                    *)
815                      if [[ "$p" == LABEL* ]] ; then
816                         p=$(blkid -t $p | awk -F: '{print $1}')
817                      fi
818                      if grep -q $p /proc/swaps ; then
819                         ewarn "Not using swap partition ${WHITE}${p}${NORMAL} as it is already in use." ; eend 0
820                      else
821                         if [ -b "$p" ] ; then
822                         einfo "Using swap partition ${WHITE}${p}${NORMAL}."
823                         swapon $p 2>>$DEBUG ; eend $?
824                         else
825                         ewarn "$p is not a valid block device - not using it therefore." ; eend 0
826                         fi
827                      fi
828                      ;;
829              esac # dd-check
830           fi # -n "$NOSWAP
831           eoutdent
832           continue
833           ;;
834         esac # it's a swap partition?
835
836         # mount read-only
837         MOUNTOPTS="ro"
838         case "$f" in
839           vfat|msdos|ntfs) MOUNTOPTS="$MOUNTOPTS,uid=${fstabuser},gid=${fstabuser}" ;;
840           ext2|ext3|reiserfs|jfs|reiser4|xfs) MOUNTOPTS="$MOUNTOPTS,noatime" ;;
841           *) continue ;;
842           # *) NONEFOUND='1'; continue ;;
843         esac
844
845         # use a swapfile
846         if [ -z "$NOSWAP" ] ; then
847            mount -o "$MOUNTOPTS" -t $f $p $m 2>>$DEBUG && MOUNTED=1 || continue
848            # Activate swapfile, if exists
849            SWAPFILE="$(/bin/ls -1d $m/[Gg][Rr][Mm][Ll].[Ss][Ww][Pp] 2>/dev/null)"
850         fi
851         if [ -z "$NOSWAP" -a -n "$SWAPFILE" -a -f "$SWAPFILE" ]; then
852            mount -o remount,rw $m && MOUNTED=1
853            if swapon "$SWAPFILE" 2>>$DEBUG ; then
854               eindent
855                 einfo "Using GRML swapfile ${WHITE}${SWAPFILE}${NORMAL}."
856               eoutdent
857               fnew="$SWAPFILE swap swap defaults 0 0"
858               grep -q "$fnew" "/etc/fstab" || echo "$fnew" >> /etc/fstab
859               GRML_SWP="$GRML_SWP $SWAPFILE"
860               eend 0
861            fi
862            mount -o remount,ro $m 2>>$DEBUG && MOUNTED=1
863         fi
864
865         # use a image as home
866         IMAGE="$(/bin/ls -1d $m/[Gg][Rr][Mm][Ll].[Ii][Mm][Gg] 2>/dev/null)"
867         if [ -z "$GRML_IMG" -a -n "$IMAGE" -a -f "$IMAGE" ]; then
868            if [ -n "$HOMEDIR" ]; then
869               if [ "$HOMEDIR" != "scan" -a "$HOMEDIR" != "$IMAGE" -a "$HOMEDIR" != "${IMAGE%/*.*}" ]; then
870                  continue
871               fi
872            fi
873            if type -a grml-image >/dev/null 2>&1 && grml-image "$IMAGE" </dev/console >/dev/console 2>&1; then
874               GRML_IMG="$IMAGE"
875               mount -o remount,ro $m 2>>$DEBUG && MOUNTED=1
876            fi
877         fi
878         eend 0
879
880         # Umount, if not in use
881         [ -n "$MOUNTED" ] && umount -r $m 2>/dev/null
882
883       done <<EOT
884       $(cat /etc/fstab)
885 EOT
886    fi # -n $partitions
887 fi # -z $INSTALLED
888 }
889 # }}}
890
891 # {{{ Mouse
892 config_mouse(){
893 if [ -n "$MOUSE_DEVICE" ] ; then
894   einfo "Detecting mouse: ${MOUSE_FULLNAME} at ${MOUSE_DEVICE}" ; eend $?
895 fi
896 }
897 # }}}
898
899 # {{{ IPv6 configuration
900 # Load IPv6 kernel module and print IP adresses
901 config_ipv6(){
902 if checkbootparam 'ipv6'; then
903   einfo "Enabling IPv6 as requested on boot commandline (sleeping for 2 seconds)"
904   modprobe ipv6
905   # we probably need some time until stateless autoconfiguration has happened
906   sleep 2
907   NETDEVICES="$(awk -F: '/eth.:|tr.:|wlan.:/{print $1}' /proc/net/dev 2>>$DEBUG)"
908   for DEVICE in `echo "$NETDEVICES"`; do
909     eindent
910       einfo "$DEVICE:"
911       ADDRESSES="$(ifconfig $DEVICE | awk '/.*inet6 addr:.*/{print $3}')"
912       COUNT="$(ifconfig $DEVICE | awk '/.*inet6 addr:.*/{ sum += 1};END {print sum }')"
913       eindent
914         for ADDR in `echo "$ADDRESSES"` ; do
915             einfo "$ADDR"
916         done
917         if [ "$COUNT" -eq "0" ] ; then
918            einfo "(none)" ; eend 1
919         fi
920       eoutdent
921     eoutdent
922   done
923   eend 0
924 fi
925 }
926 # }}}
927
928 # {{{ CPU-detection
929 config_cpu(){
930 if checkbootparam 'nocpu'; then
931   ewarn "Skipping CPU detection as requested on boot commandline." ; eend 0
932   return 0
933 fi
934
935 if [[ $(grep -c processor /proc/cpuinfo) -gt 1 ]] ; then
936    einfo "Found CPU:"
937    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)
938    echo $CPU | sed 's/ \{1,\}/ /g'
939    eend 0
940 else
941    einfo "Found 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
942 fi
943
944 # no cpufreq setup inside VirtualBox
945 if [ -r /proc/acpi/battery/BAT0/info ] && grep -q 'OEM info:.*innotek' /proc/acpi/battery/BAT0/info ; then
946    einfo 'Virtual Box detected, skipping cpufreq setup.' ; eend 0
947    return 0
948 fi
949
950 if [ -x /etc/init.d/loadcpufreq ] ; then
951    einfo "Trying to set up cpu frequency scaling:"
952    eindent
953    SKIP_CPU_GOVERNOR=''
954    LOADCPUFREQ=$(mktemp)
955    /etc/init.d/loadcpufreq start >"$LOADCPUFREQ" 2>&1 ; RC=$?
956    if grep -q FATAL "$LOADCPUFREQ" ; then
957       eindent
958         SKIP_CPU_GOVERNOR=1
959         oldIFS="$IFS"
960         IFS="
961 "
962          for line in $(grep FATAL "$LOADCPUFREQ" | sed 's/.*FATAL: //; s/ (.*)//') ; do
963              eerror "$line" ; eend $RC
964          done
965          IFS="$oldIFS"
966       eoutdent
967    elif grep -q done "$LOADCPUFREQ" ; then
968       MODULE=$(grep done "$LOADCPUFREQ" | sed 's/.*done (\(.*\))./\1/')
969       if [ -n "$MODULE" -a "$MODULE" != none ]; then
970          einfo "Loading cpufreq kernel module $MODULE" ; eend 0
971       else
972          SKIP_CPU_GOVERNOR=1
973          ewarn "Could not find an appropriate kernel module for cpu frequency scaling." ; eend 1
974       fi
975    fi
976
977    rm -f $LOADCPUFREQ
978
979    if [ -z "$SKIP_CPU_GOVERNOR" ] ; then
980      if grep -vq ondemand /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors; then
981        einfo "Loading cpufreq_ondemand"
982        modprobe cpufreq_ondemand
983        eend $?
984      fi
985
986      einfo "Setting ondemand governor"
987      RC=0
988      for file in $(find /sys/devices/system/cpu/ -name scaling_governor 2>/dev/null) ; do
989        echo ondemand > $file || RC=1
990      done
991      eend $RC
992    fi # cpu-governor
993
994    eoutdent
995 fi
996 }
997 # }}}
998
999 # {{{ autostart of ssh
1000 config_ssh(){
1001 if checkbootparam 'ssh' ; then
1002    SSH_PASSWD=''
1003    SSH_PASSWD="$(getbootparam 'ssh' 2>>$DEBUG)"
1004    einfo "Bootoption ssh found, trying to set password for user grml."
1005    eindent
1006    if [ -z "$SSH_PASSWD" ] ; then
1007       if [ -x /usr/bin/apg ] ; then
1008          SSH_PASSWD="$(apg -M NL -a 0 -m 8 -x 12 -n 1)"
1009       elif [ -x /usr/bin/gpw ] ; then
1010          SSH_PASSWD="$(gpw 1)"
1011       elif [ -x /usr/bin/pwgen ] ; then
1012          SSH_PASSWD="$(pwgen -1 8)"
1013       elif [ -x /usr/bin/hexdump ] ; then
1014          SSH_PASSWD="$(dd if=/dev/urandom bs=14 count=1 2>/dev/null | hexdump | awk '{print $3 $4}')"
1015       elif [ -n "$RANDOM" ] ; then
1016          SSH_PASSWD="grml${RANDOM}"
1017       else
1018          SSH_PASSWD=''
1019          eerror "Empty passphrase and neither pwgen nor hexdump nor \$RANDOM found. Skipping."
1020          eend 1
1021       fi
1022
1023       if [ -n "$SSH_PASSWD" ] ; then
1024          ewarn "No given password for ssh found. Using random password: $SSH_PASSWD" ; eend 0
1025       fi
1026    fi
1027    eoutdent
1028
1029    # finally check if we have a password we can use:
1030    if [ -n "$SSH_PASSWD" ] ; then
1031       # chpasswd sucks, seriously.
1032       if chpasswd --help 2>&1 | grep -q -- '-m,' ; then
1033         echo "grml:$SSH_PASSWD" | chpasswd -m
1034       else
1035         echo "grml:$SSH_PASSWD" | chpasswd
1036       fi
1037    fi
1038
1039    einfo 'Starting secure shell server in background.'
1040    /etc/init.d/rmnologin start >>$DEBUG 2>>$DEBUG
1041    /etc/init.d/ssh start >>$DEBUG 2>>$DEBUG &
1042    eend $?
1043
1044    eindent
1045    ewarn 'Warning: please change the password for user grml as soon as possible!'
1046    eoutdent
1047 fi
1048 }
1049 # }}}
1050
1051 # {{{ autostart of x11vnc
1052 config_vnc(){
1053
1054 USER=grml # TODO: make it dynamically configurable
1055 if checkbootparam 'vnc' ; then
1056    VNC_PASSWD=''
1057    VNC_PASSWD="$(getbootparam 'vnc' 2>>$DEBUG)"
1058    einfo "Bootoption vnc found, trying to set password for user $USER."
1059    eindent
1060    if [ -z "$VNC_PASSWD" ] ; then
1061       if [ -x /usr/bin/apg ] ; then
1062          VNC_PASSWD="$(apg -M NL -a 0 -m 8 -x 12 -n 1)"
1063       elif [ -x /usr/bin/gpw ] ; then
1064          VNC_PASSWD="$(gpw 1)"
1065       elif [ -x /usr/bin/pwgen ] ; then
1066          VNC_PASSWD="$(pwgen -1 8)"
1067       elif [ -x /usr/bin/hexdump ] ; then
1068          VNC_PASSWD="$(dd if=/dev/urandom bs=14 count=1 2>/dev/null | hexdump | awk '{print $3 $4}')"
1069       elif [ -n "$RANDOM" ] ; then
1070          VNC_PASSWD="${USER}${RANDOM}"
1071       else
1072          VNC_PASSWD=''
1073          eerror "Empty passphrase and neither pwgen nor hexdump nor \$RANDOM found. Skipping."
1074          eend 1
1075       fi
1076
1077       if [ -n "$VNC_PASSWD" ] ; then
1078          ewarn "No given password for vnc found. Using random password: $VNC_PASSWD" ; eend 0
1079       fi
1080    fi
1081    eoutdent
1082
1083    # finally check if we have a password we can use:
1084    if [ -n "$VNC_PASSWD" ] ; then
1085
1086       VNCDIR="/home/${USER}/.vnc"
1087       [ -d "$VNCDIR" ] || mkdir "$VNCDIR"
1088
1089       if [ ! -x /usr/bin/x11vnc ] ; then
1090          eerror "Error: x11vnc not found - can not set up vnc. Please make sure to install the x11vnc package."
1091          eend 1
1092       else
1093          /usr/bin/x11vnc -storepasswd "$VNC_PASSWD" "$VNCDIR"/passwd ; eend $?
1094          /bin/chown -R "$USER": "$VNCDIR"
1095       fi
1096    fi
1097    if checkbootparam 'vnc_connect' ; then
1098       VNC_CONNECT=''
1099       VNC_CONNECT="$(getbootparam 'vnc_connect' 2>>$DEBUG)"
1100       einfo "Bootoption vnc_connect found, will start vnc with connect to $VNC_CONNECT."
1101       #store the options in a file
1102       VNCDIR="/home/${USER}/.vnc"
1103       [ -d "$VNCDIR" ] || mkdir "$VNCDIR"
1104       echo " --connect $VNC_CONNECT " >> $VNCDIR/options
1105    fi
1106 fi
1107 }
1108 # }}}
1109
1110 # {{{ set password for user grml
1111 config_passwd(){
1112 if checkbootparam 'passwd' >>$DEBUG 2>&1; then
1113   einfo "Bootoption passwd found."
1114   PASSWD="$(getbootparam 'passwd' 2>>$DEBUG)"
1115   if [ -n "$PASSWD" ] ; then
1116     echo "grml:$PASSWD" | chpasswd -m ; eend $?
1117   else
1118     eerror "No given password for ssh found. Autostart of SSH will not work." ; eend 1
1119   fi
1120   eindent
1121     ewarn "Warning: please change the password for user grml set via bootparameter as soon as possible!"
1122   eoutdent
1123 fi
1124 }
1125 # }}}
1126
1127 # {{{ Sound
1128 config_mixer () {
1129    if ! [ -x /usr/bin/amixer ] ; then
1130       eerror "amixer binary not available. Can not set sound volumes therefore."
1131       eend 1
1132    else
1133       if ! [ -r /proc/asound/cards ] ; then
1134          ewarn "No soundcard present, skipping mixer settings therefore."
1135          eend 0
1136          return
1137       fi
1138
1139       for card in $(cat /proc/asound/cards| grep -e '^\s*[0-9]' | awk '{print $1}') ; do
1140          einfo "Configuring soundcard \"$(awk -F\[ '/^ *'$card' \[/{ FS=" "; $0=$2; print $1}' < /proc/asound/cards)\""
1141          eindent
1142
1143          if checkbootparam 'vol' ; then
1144             VOL="$(getbootparam 'vol' 2>>$DEBUG)"
1145             if [ -z "$VOL" ] ; then
1146                eerror "Bootoption vol found but no volume level/parameter given. Using defaults (75%)."
1147                VOL='75'
1148                eend 1
1149             fi
1150          else
1151             VOL='75'
1152          fi
1153
1154          if checkbootparam 'nosound' ; then
1155             einfo "Muting sound devices on request."
1156             ERROR=$(amixer -q set Master mute)
1157             RC=$?
1158             if [ -n "$ERROR" ] ; then
1159                eindent
1160                eerror "Problem muting sound devices: $ERROR"
1161                eoutdent
1162             fi
1163             eend $RC
1164          elif [ -z "$INSTALLED" ] ; then
1165             einfo "Setting mixer volumes to level ${WHITE}${VOL}${NORMAL}."
1166
1167             if checkbootparam 'micvol' ; then
1168                MICVOL="$(getbootparam 'micvol' 2>>$DEBUG)"
1169                einfo "Setting microphone to ${WHITE}${MICVOL}${NORMAL}."
1170             else
1171                MICVOL=0
1172             fi
1173
1174             CONTROLS=$(amixer -c $card scontrols | awk -F"Simple mixer control " '{print $2}')
1175             IFSOLD=${IFS:-}
1176             IFS='
1177 '
1178             for CONTROL in ${=CONTROLS} ; do
1179                if $(amixer -c $card sget ${CONTROL} | grep -q 'Capabilities:.*pswitch') ; then
1180                   amixer -c $card -q set "${CONTROL}" unmute
1181                fi
1182                if $(amixer -c $card sget ${CONTROL} | grep -q -P 'Capabilities:.*(pvolume| volume)') ; then
1183                   amixer -c $card -q set "${CONTROL}" "${VOL}"%
1184                fi
1185
1186                if [ ${MICVOL} -ne 0 ] ; then
1187                   if $(amixer -c $card sget ${CONTROL} | grep -q 'Capabilities:.*cswitch') ; then
1188                      amixer -c $card -q set "${CONTROL}" unmute
1189                   fi
1190                   if $(amixer -c $card sget ${CONTROL} | grep -q 'Capabilities:.*cvolume') ; then
1191                      amixer -c $card -q set "${CONTROL}" $MICVOL%
1192                   fi
1193                   eend $?
1194                fi
1195             done
1196             IFS=$IFSOLD
1197          fi # checkbootparam 'nosound'
1198          eoutdent
1199       done
1200    fi
1201 }
1202 # }}}
1203
1204 # {{{ modem detection
1205 config_modem(){
1206 if checkbootparam 'nomodem'; then
1207   ewarn "Skipping check for AC97 modem controller as requested on boot commandline." ; eend 0
1208 else
1209   if [ -x /etc/init.d/sl-modem-daemon ] ; then
1210      if lspci | grep Intel | grep -q "AC'97 Modem Controller" ; then
1211         einfo "AC97 modem controller detected. Start it running 'Start sl-modem-daemon'."
1212         eend 0
1213      fi
1214   fi
1215 fi
1216 }
1217 # }}}
1218
1219 # {{{ wondershaper
1220 config_wondershaper(){
1221  if checkbootparam 'wondershaper' ; then
1222     WONDER="$(getbootparam 'wondershaper' 2>>$DEBUG)"
1223     CMD=wondershaper
1224     DEVICE=""
1225     DOWNSTREAM=""
1226     UPSTREAM=""
1227     if [ -n "$WONDER" ]; then
1228       # Extra options
1229       DEVICE="${WONDER%%,*}"
1230       R="${WONDER#*,}"
1231       if [ -n "$R" -a "$R" != "$WONDER" ]; then
1232         WONDER="$R"
1233         DOWNSTREAM="${WONDER%%,*}"
1234         R="${WONDER#*,}"
1235         if [ -n "$R" -a "$R" != "$WONDER" ]; then
1236           WONDER="$R"
1237           UPSTREAM="${WONDER%%,*}"
1238           R="${WONDER#*,}"
1239         fi
1240       fi
1241     fi
1242     [ -n "$DEVICE" ]     && CMD="$CMD $DEVICE"
1243     [ -n "$DOWNSTREAM" ] && CMD="$CMD $DOWNSTREAM"
1244     [ -n "$UPSTREAM" ]   && CMD="$CMD $UPSTREAM"
1245     einfo "Starting wondershaper (${CMD}) in background."
1246     ( sh -c $CMD & ) && eend 0
1247  fi
1248 }
1249 # }}}
1250
1251 # {{{ syslog-ng
1252 config_syslog(){
1253  if checkbootparam 'nosyslog'; then
1254     ewarn "Not starting syslog daemon as requested on boot commandline." ; eend 0
1255  else
1256     SYSLOGD=''
1257     [ -x /etc/init.d/syslog-ng ] && SYSLOGD='syslog-ng'
1258     [ -x /etc/init.d/rsyslog   ] && SYSLOGD='rsyslog'
1259     [ -x /etc/init.d/dsyslog   ] && SYSLOGD='dsyslog'
1260     [ -x /etc/init.d/sysklogd  ] && SYSLOGD='sysklogd'
1261     [ -x /etc/init.d/inetutils-syslogd ] && SYSLOGD='inetutils-syslogd'
1262
1263     if [ -z "$SYSLOGD" ] ; then
1264        eerror "No syslog daemon found." ; eend 1
1265     else
1266        einfo "Starting $SYSLOGD in background."
1267        /etc/init.d/$SYSLOGD start >>$DEBUG &
1268        eend 0
1269     fi
1270  fi
1271 }
1272 # }}}
1273
1274 # {{{ gpm
1275 config_gpm(){
1276  if checkbootparam 'nogpm'; then
1277   ewarn "Not starting GPM as requested on boot commandline." ; eend 0
1278  else
1279    if ! [ -r /dev/input/mice ] ; then
1280       eerror "No mouse found - not starting GPM." ; eend 1
1281    else
1282       einfo "Starting gpm in background."
1283       /etc/init.d/gpm start >>$DEBUG &
1284       # ( while [ ! -e /dev/psaux ]; do sleep 5; done; /etc/init.d/gpm start >>$DEBUG ) &
1285       eend 0
1286    fi
1287  fi
1288 }
1289 # }}}
1290
1291 # {{{ services
1292 config_services(){
1293  if checkbootparam 'services' ; then
1294     SERVICE="$(getbootparam 'services' 2>>$DEBUG)"
1295     SERVICELIST=$(echo "$SERVICE" | sed 's/,/\\n/g')
1296     SERVICENL=$(echo "$SERVICE" | sed 's/,/ /g')
1297     for service in $(echo -e $SERVICELIST) ; do
1298       # support running (custom) init scripts in non-blocking mode
1299       # if they contain the keyword "DO_NO_RUN_IN_BACKGROUND".
1300       if grep -q 'DO_NO_RUN_IN_BACKGROUND' "/etc/init.d/${service}" 2>>$DEBUG ; then
1301         einfo "Starting service ${service}."
1302         /etc/init.d/${service} start >>$DEBUG
1303       else
1304         einfo "Starting service ${service} in background."
1305         /etc/init.d/${service} start >>$DEBUG &
1306       fi
1307     done
1308     eend $?
1309  fi
1310 }
1311 # }}}
1312
1313 # {{{ remote files
1314 get_remote_file() {
1315   [ "$#" -eq 2 ] || ( echo "Error: wrong parameter for get_remote_file()" ; return 1 )
1316   SOURCE=$(eval echo "$1")
1317   TARGET="$2"
1318   getconfig() {
1319   wget --timeout=10 --dns-timeout=10  --connect-timeout=10 --tries=1 \
1320        --read-timeout=10 ${SOURCE} -O ${TARGET} && return 0 || return 1
1321   }
1322   einfo "Trying to get ${WHITE}${TARGET}${NORMAL}"
1323   counter=10
1324   while ! getconfig && [[ "$counter" != 0 ]] ; do
1325     echo -n "Sleeping for 1 second and trying to get config again... "
1326     counter=$(( counter-1 ))
1327     echo "$counter tries left" ; sleep 1
1328   done
1329   if [ -s "$TARGET" ] ; then
1330     einfo "Downloading was successfull." ; eend 0
1331     einfo "md5sum of ${WHITE}${TARGET}${NORMAL}: "
1332     md5sum ${TARGET} ; eend 0
1333     return 0;
1334   else
1335     einfo "Sorry, could not fetch ${SOURCE}" ; eend 1
1336     return 1;
1337  fi
1338 }
1339 # }}}
1340
1341 # {{{ config files
1342 config_netconfig(){
1343  if checkbootparam 'netconfig' ; then
1344   CONFIG="$(getbootparam 'netconfig' 2>>$DEBUG)"
1345   CONFIGFILE='/tmp/netconfig.grml'
1346
1347   if get_remote_file ${CONFIG} ${CONFIGFILE} ; then
1348     cd / && einfo "Unpacking ${WHITE}${CONFIGFILE}${NORMAL}:" && /usr/bin/unp $CONFIGFILE $EXTRACTOPTIONS ; eend $?
1349   fi
1350
1351  fi
1352 }
1353 # }}}
1354
1355 # {{{ remote scripts
1356 config_netscript() {
1357  if checkbootparam 'netscript' ; then
1358   CONFIG="$(getbootparam 'netscript' 2>>$DEBUG)"
1359   SCRIPTFILE='/tmp/netscript.grml'
1360
1361   if get_remote_file ${CONFIG} ${SCRIPTFILE} ; then
1362     chmod +x ${SCRIPTFILE}
1363     einfo "Running ${WHITE}${SCRIPTFILE}${NORMAL}:" && NETSCRIPT=${CONFIG} ${SCRIPTFILE} ; eend $?
1364   fi
1365
1366  fi
1367 }
1368 # }}}
1369
1370 # {{{ stats
1371 config_stats() {
1372  if ! checkbootparam 'nostats' ; then
1373    BASE_URL="http://stats.grml.org/report/"
1374    ACTION_NAME=Boot
1375
1376    HOST_ID=$(cat /proc/sys/kernel/random/boot_id)
1377
1378    grep -q " lm " /proc/cpuinfo && HAS_64BIT="1" || HAS_64BIT="0"
1379    DATE_STRING=$(date +'h=%H&m=%M&s=%S')
1380    [ -e /etc/grml_version ] && VERSION=$(cat /etc/grml_version) || \
1381      VERSION=$(lsb_release -d | awk -F: '{gsub(/^[ \t]+/, "", $2); print $2}')
1382
1383    PARAMS="$( echo "$CMDLINE" | sed -e 's/=[^ ]*/=x/g' | tr " " "\n"|sort|tr "\n" " " )"
1384
1385    echo "$CMDLINE" | grep -q -e "fetch" -e "nfsroot" && BOOT="remote"
1386    [ -z "$BOOT" ] && BOOT="local"
1387
1388    ADDITIONAL_PARAMS=""
1389    ( [ -n "$COLUMNS" ] && [ -n "$LINES" ] ) && \
1390      ADDITIONAL_PARAMS="$ADDITIONAL_PARAMS&res=$((COLUMNS * 8))x$((LINES * 16))"
1391
1392    URI='$BASE_URL?action=${ACTION_NAME}\&$DATE_STRING\&unique_id=${HOST_ID}\&support_64bit=$HAS_64BIT\&version=$VERSION\&bootup=$BOOT\&params=$PARAMS$ADDITIONAL_PARAMS'
1393
1394    get_remote_file "$URI" "/dev/null"  >/dev/null 2>&1 &!
1395  fi
1396 }
1397 # }}}
1398 # {{{ fix/workaround for unionfs
1399 fix_unionfs(){
1400   if [ -z "$INSTALLED" ]; then
1401    touch /var/cache/apt/*cache.bin
1402   fi
1403 }
1404 # }}}
1405
1406 # {{{ start X window system via grml-x
1407 config_x_startup(){
1408 # make sure we start X only if startx is used *before* a nostartx option
1409 # so it's possible to disable automatic X startup using nostart
1410 if checkbootparam 'startx' && ! echo "$CMDLINE" | grep -q 'startx.*nostartx' ; then
1411  if [ -x "$(which X)" ] ; then
1412   if [ -z "$INSTALLED" ] ; then
1413    WINDOWMANAGER="$(getbootparam 'startx' 2>>$DEBUG)"
1414    if [ -z "$WINDOWMANAGER" ] ; then
1415      einfo "No window manager specified. Using default one." && eend 0
1416    else
1417      einfo "Window manager ${WHITE}${WINDOWMANAGER}${NORMAL} found as bootoption." && eend 0
1418    fi
1419    einfo "Setting up and invoking grml-x ${WINDOWMANAGER}. Just exit X windows system to get full featured consoles."
1420    config_userfstab || fstabuser='grml'
1421  cat>|/etc/init.d/xstartup<<EOF
1422 #!/bin/sh
1423 su $fstabuser -c "/usr/bin/grml-x"
1424 EOF
1425    chmod 755 /etc/init.d/xstartup
1426
1427    # adjust inittab for xstartup
1428    if grep -q '^6:' /etc/inittab ; then
1429       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
1430    else # just append tty6 to inittab if no definition is present:
1431       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
1432    fi
1433
1434    /sbin/telinit q ; eend $?
1435
1436    if grep -q '^allowed_users=' /etc/X11/Xwrapper.config ; then
1437       sed -i 's/^allowed_users=.*/allowed_users=anybody/' /etc/X11/Xwrapper.config
1438    else
1439       echo 'allowed_users=anybody' >> /etc/X11/Xwrapper.config
1440    fi
1441
1442   else
1443     eerror "We are not running in live mode - startx will not work, skipping it."
1444     eerror " -> Please use something like xdm, gdm or kdm for starting X on a harddisk system!" ; eend 1
1445   fi
1446  else
1447    eerror "/usr/bin/X is not present on this grml flavour."
1448    eerror "  -> Boot parameter startx does not work therefore." ; eend 1
1449  fi
1450 fi
1451 }
1452 # }}}
1453
1454 # {{{ configuration framework
1455 config_extract(){
1456 if checkbootparam 'extract' ; then
1457  EXTRACT="$(getbootparam 'extract' 2>>$DEBUG)"
1458  EXTRACTOPTIONS="-- -x $EXTRACT"
1459 fi
1460 }
1461
1462 config_finddcsdir() {
1463 #  - If no GRMLCFG partition is found and noautoconfig is _not_ given
1464 #    on the command line, nothing is changed and the dcs files are
1465 #    searched within the .iso, $dcs-dir is set to the root directory
1466 #    within the .iso
1467 #  - If a GRMLCFG partition is found, $dcs-dir is set to the root of
1468 #    the GRMLCFG partition unless noautoconfig is set. If noautoconfig is
1469 #    set, $dcs-dir is set to the root directory within the .iso.
1470 #  - If myconfig=foo is set on the command line, $dcs-dir is set to
1471 #    foo, even if a GRMLCFG partition is present.
1472 DCSDIR=""
1473 DCSMP="/mnt/grml"
1474 # autoconfig, see issue673
1475 GRMLCFG="$(getbootparam 'autoconfig' 2>>$DEBUG)"
1476 [ -n "$GRMLCFG" ] || GRMLCFG="GRMLCFG"
1477 if checkbootparam 'noautoconfig' || checkbootparam 'forensic' ; then
1478   ewarn "Skipping running automount of device(s) labeled $GRMLCFG as requested." ; eend 0
1479 else
1480   if [ -z "$INSTALLED" ] ; then
1481     if checkbootparam 'myconfig' ; then
1482       DCSDEVICE="$(getbootparam 'myconfig' 2>>$DEBUG)"
1483       if [ -z "$DCSDEVICE" ]; then
1484         eerror "Error: No device for bootoption myconfig provided." ; eend 1
1485       fi # [ -z "$DCSDEVICE" ]
1486     elif checkvalue $CONFIG_MYCONFIG; then # checkbootparam myconfig
1487       einfo "Searching for device(s) labeled with $GRMLCFG. (Disable this via boot option: noautoconfig)" ; eend 0
1488       eindent
1489       # We do need the following fix so floppy disk is available to blkid in any case :-/
1490       if [ -r /dev/fd0 ] ; then
1491         einfo "Floppy device detected. Trying to access floppy disk."
1492         if timeout 4 dd if=/dev/fd0 of=/dev/null bs=512 count=1 >>$DEBUG 2>&1 ; then
1493            blkid /dev/fd0 >>$DEBUG 2>&1
1494         fi
1495       fi
1496       DCSDEVICE=$(blkid -t LABEL=$GRMLCFG | head -1 | awk -F: '{print $1}')
1497       if [ -n "$DCSDEVICE" ]; then
1498         DCSMP="/mnt/grmlcfg"
1499       fi
1500       eoutdent
1501     fi
1502
1503     # if not specified/present then assume default:
1504     if [ -z "$DCSDEVICE" ]; then
1505       DCSDIR="/live/image"
1506     else
1507       eindent
1508       einfo "debs, config, scripts are read from $DCSDEVICE." ; eend 0
1509       DCSDIR="$(< /proc/mounts awk -v DCSDEV=$DCSDEVICE '{if ($1 == DCSDEV) { print $2 }}')"
1510       if [ -n "$DCSDIR" ]; then
1511         ewarn "$DCSDEVICE already mounted on $DCSDIR"; eend 0
1512       else
1513         [ -d $DCSMP ] || mkdir $DCSMP
1514         umount $DCSMP >>$DEBUG 2>&1 # make sure it is not mounted
1515         mount -o ro -t auto $DCSDEVICE  $DCSMP ; RC="$?"
1516         if [[ $RC == 0 ]]; then
1517           einfo "Successfully mounted $DCSDEVICE to $DCSMP (readonly)." ; eend 0
1518         else
1519           eerror "Error: mounting $DCSDEVICE to $DCSMP (readonly) failed." ; eend 1
1520         fi
1521         DCSDIR="$DCSMP"
1522       fi
1523       eoutdent
1524     fi
1525   fi
1526 fi
1527
1528 if [ -n "$DCSDIR" -a "$DCSDIR" != "/live/image" ] ; then
1529   einfo "Debs, config, scripts (if present) will be read from $DCSDIR." ; eend 0
1530 elif checkbootparam 'debs' || checkbootparam 'config' || checkbootparam 'scripts'; then
1531   einfo "Debs, config, scripts will be read from the live image directly." ; eend 0
1532 fi
1533 }
1534
1535
1536 config_partconf() {
1537 if checkbootparam 'partconf' ; then
1538  MOUNTDEVICE="$(getbootparam 'partconf' 2>>$DEBUG)"
1539  if [ -n "$MOUNTDEVICE" ]; then
1540    [ -d /mnt/grml ] || mkdir /mnt/grml
1541    mount -o ro -t auto $MOUNTDEVICE /mnt/grml ; RC="$?"
1542     if [[ $RC == 0 ]]; then
1543       einfo "Successfully mounted $MOUNTDEVICE to /mnt/grml (readonly)." ; eend 0
1544       einfo "Copying files from $MOUNTDEVICE over grml system."
1545       for file in `cat /etc/grml/partconf` ; do
1546         [ -d /mnt/grml/$file ] && cp -a /mnt/grml/${file}* ${file} && echo "copied: $file"
1547         [ -f /mnt/grml/$file ] && cp -a /mnt/grml/${file}  ${file} && echo "copied: $file"
1548       done && eend 0
1549     else
1550       einfo "Could not mount $MOUNTDEVICE to /mnt/grml - sorry." ; eend 1
1551     fi # mount $MOUNTDEVICE
1552    grep -q '/mnt/grml' /proc/mounts && umount /mnt/grml
1553  else
1554    einfo "Sorry, no device for bootoption partconf provided. Skipping." ; eend 1
1555  fi # [ -n "$MOUNTDEVICE" ]
1556 fi
1557 }
1558 # }}}
1559
1560 # {{{ /cdrom/.*-options
1561 config_debs(){
1562 if checkbootparam 'debs' ; then
1563    iszsh && setopt localoptions shwordsplit
1564    DEBS="$(getbootparam 'debs' 2>>$DEBUG)"
1565    if [ -z "$DEBS" ] ; then
1566       DEBS="*.deb"
1567    fi
1568    if ! echo $DEBS | grep -q '/'; then
1569      # backwards compatibility: if no path is given get debs from debs/
1570      DEBS="debs/$DEBS"
1571    fi
1572    einfo "Tring to install debian package(s) ${DEBS}"
1573    DEBS="$(eval echo ${DCSDIR}/$DEBS)"
1574    dpkg -i $DEBS ; eend $?
1575 fi
1576 }
1577
1578 config_scripts(){
1579 if checkbootparam 'scripts' || [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1580    SCRIPTS="$(getbootparam 'scripts' 2>>$DEBUG)"
1581    if [ -d ${DCSDIR}/scripts ] && [ -z "$SCRIPTS" ]; then
1582      SCRIPTS="$(cd ${DCSDIR}/scripts; /bin/ls -1d [Gg][Rr][Mm][Ll].[Ss][Hh] 2>>$DEBUG)"
1583    fi
1584    if ! echo $SCRIPTS | grep -q '/'; then
1585      # backwards compatibility: if no path is given get scripts from scripts/
1586      SCRIPTS="scripts/$SCRIPTS"
1587    fi
1588    if [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1589      # we are executing from a GRMLCFG labeled fs
1590      # kick everything we have done before and start over
1591      SCRIPTS="$(cd ${DCSDIR}; /bin/ls -1d [Gg][Rr][Mm][Ll].[Ss][Hh] 2>>$DEBUG)"
1592    fi
1593    if [ -n "$SCRIPTS" ]; then
1594      SCRIPTS="${DCSDIR}/$SCRIPTS"
1595      if [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1596        einfo "Trying to execute ${SCRIPTS}"
1597        sh -c $SCRIPTS
1598      elif [ -d "$SCRIPTS" ]; then
1599        einfo "Bootparameter scripts found. Trying to execute from directory ${SCRIPTS}:"
1600        run-parts $SCRIPTS
1601      else
1602        einfo "Bootparameter scripts found. Trying to execute ${SCRIPTS}:"
1603        sh -c $SCRIPTS
1604      fi
1605    fi
1606 fi
1607 }
1608
1609 config_config(){
1610 if checkbootparam 'config' || [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1611   CONFIG="$(getbootparam 'config' 2>>$DEBUG)"
1612   if [ -z "$CONFIG" ]; then
1613     CONFIG="$(cd ${DCSDIR}; ls -1d [Cc][Oo][Nn][Ff][Ii][Gg].[Tt][Bb][Zz] 2>>$DEBUG)"
1614   fi
1615   if [ -n "$CONFIG" ]; then
1616     if [ -d "${DCSDIR}/${CONFIG}" ] ; then
1617       einfo "Taking configuration from directory ${DCSDIR}/${CONFIG}"
1618
1619       cp -a ${DCSDIR}/${CONFIG}/* /
1620     elif [ -f "${DCSDIR}/${CONFIG}" ]; then
1621       einfo "Extracting configuration from file ${DCSDIR}/${CONFIG}"
1622
1623       cd /
1624       unp ${DCSDIR}/${CONFIG} $EXTRACTOPTIONS ; eend $?
1625     else
1626       ewarn "Sorry, could not find configuration file or directory ${DCSDIR}/${FILENAME}." ; eend 1
1627     fi
1628   fi
1629 fi
1630 }
1631 # }}}
1632
1633 # {{{ confing_umount_dcsdir
1634 config_umount_dcsdir(){
1635    # umount $DCSMP if it was mounted by finddcsdir
1636    grep -q "$DCSMP" /proc/mounts && umount "$DCSMP"
1637 }
1638 # }}}
1639
1640 # {{{ mypath
1641 config_mypath(){
1642 if checkbootparam 'mypath' ; then
1643    MY_PATH="$(getbootparam 'mypath' 2>>$DEBUG)"
1644    einfo "Bootparameter mypath found, adding ${MY_PATH} to /etc/grml/my_path"
1645    touch /etc/grml/my_path
1646    chmod 644 /etc/grml/my_path
1647    # make sure the directories exist:
1648    eindent
1649    for i in $(echo $MY_PATH | sed 's/:/\n/g') ; do
1650        if ! [ -d "$i" ] ; then
1651           einfo "Creating directory $i"
1652           mkdir -p "$i" ; eend $?
1653        fi
1654    done
1655    grep -q "${MY_PATH}" /etc/grml/my_path || echo "${MY_PATH}" >> /etc/grml/my_path ; eend $?
1656    eoutdent
1657 fi
1658 }
1659 # }}}
1660
1661 # {{{ distcc
1662 config_distcc(){
1663 if checkbootparam 'distcc' ; then
1664  OPTIONS="$(getbootparam 'distcc' 2>>$DEBUG)"
1665  if [ -n "$OPTIONS" ]; then
1666     NET=""
1667     INTERFACE=""
1668     if [ -n "$OPTIONS" ]; then
1669       NET="${OPTIONS%%,*}"
1670       R="${OPTIONS#*,}"
1671       if [ -n "$R" -a "$R" != "$OPTIONS" ]; then
1672         OPTIONS="$R"
1673         INTERFACE="${OPTIONS%%,*}"
1674         R="${OPTIONS#*,}"
1675       fi
1676     fi
1677  fi
1678  CONFIG=/etc/default/distcc
1679  sed -i "s#^STARTDISTCC=.*#STARTDISTCC=YES#"  $CONFIG
1680  sed -i "s#^ALLOWEDNETS=.*#ALLOWEDNETS=$NET#" $CONFIG
1681
1682  if [ -n "$INTERFACE" ] ; then
1683    IP=$(LANG=C ifconfig $INTERFACE | gawk -F: /"inet addr"/'{print $2}' | gawk '{print $1}')
1684
1685    counter=10
1686    while [ -z "$IP" ] && [[ "$counter" != 0 ]] ; do
1687      counter=$(( counter-1 ))
1688      ewarn "No ip address for $INTERFACE found. Sleeping for 3 seconds. $counter tries left."
1689      sleep 3
1690      IP=$(LANG=C ifconfig $INTERFACE | gawk -F: /"inet addr"/'{print $2}' | gawk '{print $1}')
1691    done
1692  fi
1693
1694  if [ -n "$IP" ] ; then
1695    sed -i "s#^LISTENER=.*#LISTENER=$IP#"      $CONFIG
1696
1697    einfo "Bootoption distcc found. Preparing setup for distcc daemon."
1698    eindent
1699     id distccd >/dev/null 2>&1 || \
1700     (
1701       einfo "Creating distcc user" ; \
1702       adduser --quiet --system --ingroup nogroup --home / --no-create-home distccd ; eend $?
1703     )
1704
1705     einfo "Starting distcc for network ${NET}, listening on ${IP}."
1706    /etc/init.d/distcc start >/dev/null ; eend $?
1707    eoutdent
1708  else
1709    eerror "No ip address for $INTERFACE found. distcc can not be used without it." ; eend 1
1710  fi
1711 fi
1712
1713 if checkbootparam 'gcc'; then
1714  GCC="$(getbootparam 'gcc' 2>>$DEBUG)"
1715  eindent
1716  einfo "Pointing /usr/bin/gcc to /usr/bin/gcc-${GCC}."
1717  eoutdent
1718  rm -f /usr/bin/gcc
1719  ln -s /usr/bin/gcc-${GCC} /usr/bin/gcc ; eend $?
1720 fi
1721
1722 if checkbootparam 'gpp'; then
1723  GPP="$(getbootparam 'gpp' 2>>$DEBUG)"
1724  eindent
1725   einfo "Pointing /usr/bin/g++ to /usr/bin/g++-${GPP}."
1726   if [ -x /usr/bin/g++-${GPP} ] ; then
1727      rm -f /usr/bin/g++
1728      ln -s /usr/bin/g++-${GPP} /usr/bin/g++ ; eend $?
1729   fi
1730   einfo "Pointing /usr/bin/cpp to /usr/bin/cpp-${GPP}."
1731   if [ -x /usr/bin/cpp-${GPP} ] ; then
1732      rm -f /usr/bin/cpp
1733      ln -s /usr/bin/cpp-${GPP} /usr/bin/cpp ; eend $?
1734   fi
1735  eoutdent
1736 fi
1737
1738 }
1739 # }}}
1740
1741 # {{{ load modules
1742 # Notice: use it only on live-cd system, if running from harddisk please
1743 # add modules to /etc/modules and activate /etc/init.d/module-init-tools
1744 # in /etc/runlevel.conf
1745 config_modules(){
1746 MODULES_FILE=/etc/grml/modules
1747 if checkbootparam 'nomodules' ; then
1748   ewarn "Skipping loading of modules defined in ${MODULES_FILE} as requested." ; eend 0
1749 elif [ -z "$INSTALLED" ]; then
1750  if [ -r $MODULES_FILE ] ; then
1751   einfo "Loading modules specified in ${MODULES_FILE}:"
1752   eindent
1753   grep '^[^#]' $MODULES_FILE | \
1754   while read module args; do
1755     [ "$module" ] || continue
1756       einfo "${module}"
1757       modprobe $module $args ; eend $?
1758   done
1759   eoutdent
1760  else
1761   ewarn "File $MODULES_FILE does not exist. Skipping loading of specific modules." ; eend 1
1762  fi
1763 fi
1764 }
1765 # }}}
1766
1767 # {{{ SW-RAID
1768 config_swraid(){
1769   [ -n "$INSTALLED" ] && return 0
1770
1771   # notice: checkbootparam "forensic" is just for users who don't know how to really use the bootoption
1772   if checkbootparam 'noraid'   || checkbootparam 'noswraid' || \
1773      checkbootparam 'forensic' || checkbootparam 'raid=noautodetect' ; then
1774      ewarn "Skipping SW-RAID code as requested on boot commandline." ; eend 0
1775   else
1776     [ -e /proc/mdstat ] || modprobe md_mod
1777     if ! [ -x /sbin/mdadm ] ; then
1778        eerror "mdadm not available, can not execute it." ; eend 1
1779     else
1780
1781        # if ! egrep -qv '^(MAILADDR.*|#.*|)$' /etc/mdadm/mdadm.conf 2>>$DEBUG ; then
1782        # find out whether we have a valid configuration file already
1783        if ! grep -q ARRAY /etc/mdadm/mdadm.conf 2>>$DEBUG ; then
1784           einfo "Creating /etc/mdadm/mdadm.conf for use with mdadm."
1785           [ -r /etc/mdadm/mdadm.conf ] && mv /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.old
1786           MDADM_MAILADDR__='root' /usr/share/mdadm/mkconf > /etc/mdadm/mdadm.conf ; eend $?
1787         else
1788           ewarn "/etc/mdadm/mdadm.conf looks like a configured mdadm setup, will not touch it." ; eend 0
1789        fi
1790
1791        if ! checkbootparam 'swraid' ; then
1792           eindent
1793           einfo "Just run 'Start mdadm-raid' to assemble md arrays or boot using 'swraid' as bootoption for autostart."
1794           eoutdent
1795        else
1796           einfo "Bootoption swraid found. Searching for software RAID arrays:"
1797           eindent
1798            IFSOLD=${IFS:-}
1799            IFS='
1800 '
1801            for line in $(mdadm --assemble --scan --auto=yes --symlink=no 2>&1) ; do
1802                case $line in
1803                  *'No arrays found'*)
1804                    ewarn "$line" ; eend 0
1805                    ;;
1806                  *)
1807                    einfo "$line" ; eend 0
1808                    ;;
1809                esac
1810            done
1811            IFS=$IFSOLD
1812          eoutdent
1813
1814          if [ -r /proc/mdstat ] ; then
1815             eindent
1816             MDSTAT=$(grep '^md[0-9]' /proc/mdstat)
1817             if [ -z "$MDSTAT" ] ; then
1818                ewarn "No active arrays found" ; eend 0
1819             else
1820                IFSOLD=${IFS:-}
1821                IFS='
1822 '
1823                for line in $(grep '^md[0-9]' /proc/mdstat) ; do
1824                    einfo "active arrays: $line" ; eend 0
1825                done
1826                IFS=$IFSOLD
1827             fi
1828             eoutdent
1829          fi # /proc/mdstat
1830        fi # bootoption swraid
1831
1832      fi # is /sbin/mdadm executable?
1833   fi # check for bootoptions
1834 }
1835 # }}}
1836
1837 # {{{ dmraid
1838 config_dmraid(){
1839   [ -n "$INSTALLED" ] && return 0
1840
1841   if checkbootparam 'nodmraid' ; then
1842     ewarn "Skipping dmraid code as requested on boot commandline." ; eend 0
1843     return 0
1844   fi
1845
1846   if ! [ -x /sbin/dmraid ] ; then
1847     eerror "dmraid not available, can not execute it." ; eend 1
1848     return
1849   fi
1850
1851   dmraid_wrapper() {
1852     # usage: dmraid_wrapper <dmraid_option>
1853     [ -n "$1" ] || return 1
1854
1855     IFSOLD=${IFS:-}
1856     IFS='
1857 '
1858     eindent
1859
1860     for line in $(dmraid $1 ; echo errcode:$?); do
1861       case $line in
1862         *'no block devices found'*)
1863           einfo "No block devices found" ; eend 0
1864           break
1865           ;;
1866         *'no raid disks'*)
1867           einfo "No active dmraid devices found" ; eend 0
1868           break
1869           ;;
1870         errcode:0)
1871           eend 0;
1872           ;;
1873         errcode:1)
1874           eend 1
1875           ;;
1876         *)
1877           einfo "$line"
1878           ;;
1879       esac
1880     done
1881
1882     eoutdent
1883     IFS=$IFSOLD
1884   }
1885
1886   if checkbootparam 'dmraid' ; then
1887     local ACTION="$(getbootparam 'dmraid' 2>>$DEBUG)"
1888     if [ "$ACTION" = "off" ] ; then
1889       # Deactivates all active software RAID sets:
1890       einfo "Deactivating present dmraid sets (as requested via dmraid=off):"
1891       dmraid_wrapper -an
1892     else
1893       # Activate all software RAID sets discovered:
1894       einfo "Activating present dmraid sets (as requested via dmraid):"
1895       dmraid_wrapper -ay
1896     fi
1897
1898     return
1899   fi
1900
1901   # by default (no special bootoptions) discover all software RAID devices:
1902   einfo "Searching for any present dmraid sets:"
1903   dmraid_wrapper -r
1904 }
1905 # }}}
1906
1907 # {{{ LVM (Logical Volumes)
1908 config_lvm(){
1909   [ -n "$INSTALLED" ] && return 0
1910
1911   if checkbootparam 'nolvm' ; then
1912      ewarn "Skipping LVM code as requested on boot commandline." ; eend 0
1913   else
1914     # Debian etch provides /etc/init.d/lvm only, newer suites provide /etc/init.d/lvm2
1915     if ! [ -x /sbin/lvm -a -x /sbin/lvdisplay ] || ! [ -x /etc/init.d/lvm2 -o -x /etc/init.d/lvm ] ; then
1916        eerror "LVM not available, can not execute it." ; eend 1
1917     else
1918        if lvdisplay 2>&1 | grep -v 'No volume groups found' >/dev/null 2>&1 ; then
1919           einfo "You seem to have logical volumes (LVM) on your system."
1920           eindent
1921           einfo "Just run 'Start lvm2' to activate them or boot using 'lvm' as bootoption for autostart."
1922           eend 0
1923           if checkbootparam 'lvm' ; then
1924              einfo "Bootoption LVM found. Searching for logical volumes:"
1925              /etc/init.d/lvm2 start ; eend $?
1926           fi
1927           eoutdent
1928        fi
1929     fi # check for lvm binary
1930   fi # check for bootoption nolvm
1931 }
1932 # }}}
1933
1934 # {{{ debnet: setup network based on an existing one found on a partition
1935 config_debnet(){
1936 if checkbootparam 'debnet' ; then
1937  einfo "Bootoption 'debnet' found. Searching for Debian network configuration: "
1938  /usr/sbin/debnet
1939 fi
1940 }
1941 # }}}
1942
1943 # {{{ disable console blanking
1944 config_blanking(){
1945 if checkbootparam 'noblank' ; then
1946   einfo "Bootoption noblank found. Disabling monitor blanking."
1947   setterm -blank 0 ; eend $?
1948 fi
1949 }
1950 # }}}
1951
1952 # {{{ tohd= bootoption
1953 config_tohd()
1954 {
1955   if checkbootparam 'tohd' ; then
1956      local TARGET="$(getbootparam 'tohd' 2>>$DEBUG)"
1957      if [ -z "$TARGET" ] ; then
1958         eerror "Error: tohd specified without any partition, can not continue." ; eend 1
1959         eerror "Please use something like tohd=/dev/sda9." ; eend 1
1960         return 1
1961      fi
1962
1963      if ! [ -b "$TARGET" ] ; then
1964         eerror "Error: $TARGET is not a valid block device, sorry." ; eend 1
1965         return 1
1966      fi
1967
1968      if grep -q $TARGET /proc/mounts ; then
1969         eerror "$TARGET already mounted, skipping execution of tohd therefore."
1970         eend 1
1971         return 1
1972      fi
1973
1974      local MOUNTDIR=$(mktemp -d)
1975
1976      if mount -o rw "$TARGET" "$MOUNTDIR" ; then
1977         einfo "Copyring live system to $TARGET - this might take a while"
1978         rsync -a --progress /live/image/live $MOUNTDIR
1979         sync
1980         umount "$MOUNTDIR"
1981         eend $?
1982         einfo "Booting with \"grml bootfrom=$TARGET\" should work now." ; eend 0
1983      else
1984         eerror "Error when trying to mount $TARGET, sorry."; eend 1
1985         return 1
1986      fi
1987
1988      rmdir "$MOUNTDIR"
1989   fi
1990 }
1991 # }}}
1992
1993 # {{{ debootstrap: automatic installation
1994 config_debootstrap(){
1995
1996 if checkbootparam "BOOT_IMAGE=debian2hd" || checkbootparam "debian2hd" ; then
1997
1998 einfo "Bootoption debian2hd found. Setting up environment for automatic installation via grml-debootstrap." ; eend 0
1999
2000 if ! [ -x /usr/sbin/grml-debootstrap ] ; then
2001    eindent
2002    eerror "Bootoption debian2hd found, but grml-debootstrap is not available." ; eend 1
2003    eoutdent
2004    exit 1
2005 fi
2006
2007 if checkbootparam 'target' ; then
2008   TARGET=''
2009   TARGET="$(getbootparam 'target' 2>>$DEBUG)"
2010   # notice: the following checks whether the given partition is available, if not the skip
2011   # execution of grml-debootstrap as it might result in data loss...
2012   if ! [ -r "$TARGET" ] ; then
2013      eerror "Target $TARGET does not exist. Skipping execution of grml-debootstrap therefore." ; eend 1
2014   fi
2015 else
2016   eindent
2017   eerror "No bootoption named target found, can not continue execution of grml-debootstrap." ; eend 1
2018   eoutdent
2019   exit 1
2020 fi
2021
2022 if checkbootparam 'grub' ; then
2023   GRUB=''
2024   GRUB="$(getbootparam 'grub' 2>>$DEBUG)"
2025 fi
2026
2027 if checkbootparam 'groot' ; then
2028   GROOT=''
2029   GROOT="$(getbootparam 'groot' 2>>$DEBUG)"
2030 fi
2031
2032 if checkbootparam 'release' ; then
2033   RELEASE=''
2034   RELEASE="$(getbootparam 'release' 2>>$DEBUG)"
2035 fi
2036
2037 if checkbootparam 'mirror' ; then
2038   MIRROR=''
2039   MIRROR="$(getbootparam 'mirror' 2>>$DEBUG)"
2040 fi
2041
2042 if checkbootparam 'boot_append' ; then
2043   BOOT_APPEND=''
2044   BOOT_APPEND="$(getbootparam 'boot_append' 2>>$DEBUG)"
2045 fi
2046
2047 if checkbootparam 'password' ; then
2048   PASSWORD=''
2049   PASSWORD="$(getbootparam 'password' 2>>$DEBUG)"
2050 fi
2051
2052 # now check which options are available
2053 if [ -n "TARGET" ] ; then
2054    TARGETCMD="--target $TARGET"
2055 else
2056    TARGETCMD=''
2057    eindent
2058    eerror "Target not set via bootoption. Skipping execution of grml-debootstrap therefore."; eend 1
2059    eoutdent
2060    exit 1
2061 fi
2062 [ -n "$GRUB" ]     && GRUBCMD="--grub $GRUB"               || GRUBCMD=''
2063 [ -n "$GROOT" ]    && GROOTCMD="--groot $GROOT"            || GROOTCMD=''
2064 [ -n "$RELEASE" ]  && RELEASECMD="--release $RELEASE"      || RELEASECMD=''
2065 [ -n "$MIRROR" ]   && MIRRORCMD="--mirror $MIRROR"         || MIRRORCMD=''
2066 [ -n "$PASSWORD" ] && PASSWORDCMD="--password $PASSWORD"   || PASSWORDCMD=''
2067 [ -n "$BOOT_APPEND" ] && BOOT_APPEND="--boot_append $BOOT_APPEND" || BOOT_APPEND=''
2068
2069 # and finally write script and execute it
2070 cat>|/usr/bin/grml-debootstrap_noninteractive<<EOF
2071 #!/bin/sh
2072 AUTOINSTALL='yes' grml-debootstrap $TARGETCMD $GRUBCMD $GROOTCMD $RELEASECMD $MIRRORCMD $PASSWORDCMD $BOOT_APPEND
2073 EOF
2074
2075 chmod 750  /usr/bin/grml-debootstrap_noninteractive
2076
2077 screen /usr/bin/grml-debootstrap_noninteractive
2078 einfo "Invoking a shell, just exit to continue booting..."
2079 /bin/zsh
2080
2081 fi # checkbootparam "BOOT_IMAGE=debian2hd
2082 }
2083 # }}}
2084
2085 config_virtualbox_shared_folders() {
2086 if [ -r /proc/acpi/battery/BAT0/info ] && grep -q 'OEM info:.*innotek' /proc/acpi/battery/BAT0/info ; then
2087   einfo "VirtualBox detected, trying to set up Shared Folders."
2088   if ! modprobe -l | grep -q vboxsf.ko ; then
2089     ewarn "vboxsf driver not present, not setting up VirtualBox Shared Folders."
2090     eend 0
2091   elif ! [ -x /usr/sbin/VBoxService ] ; then
2092     ewarn "virtualbox-guest-utils not installed, not setting up VirtualBox Shared Folders."
2093     eend 0
2094   else
2095     eindent
2096
2097       einfo "Loading vboxsf driver."
2098       lsmod | grep -q vboxsf || modprobe vboxsf
2099       eend $?
2100
2101       einfo "Adjusting /dev/vboxguest."
2102       chown root:vboxsf /dev/vboxguest
2103       chmod 660 /dev/vboxguest
2104       eend $?
2105
2106       if [ -n "$CONFIG_FSTAB_USER" ] ; then
2107         fstabuser="$CONFIG_FSTAB_USER"
2108       else
2109         fstabuser=$(getent passwd 1000 | cut -d: -f1)
2110       fi
2111       einfo "Adding $fstabuser to group vboxsf."
2112       adduser grml vboxsf &>/dev/null
2113       eend $?
2114
2115       einfo "Starting VBoxService."
2116       VBoxService >/dev/null &
2117       eend $?
2118
2119     eoutdent
2120   fi
2121 fi
2122 }
2123
2124 # {{{ Support customization
2125 config_distri(){
2126 if checkbootparam 'distri'; then
2127   DISTRI="$(getbootparam 'distri' 2>>$DEBUG)"
2128   if [ -r "${LIVECD_PATH}"/desktop/"$DISTRI".jpg ] ; then
2129      [ -n "$BOOTDEBUG" ] && einfo "Debug: bootoption distri found and file ${LIVECD_PATH}/desktop/${DISTRI} present" && eend 0
2130      # make sure the desktop.jpg file is not a symlink, so copying does not file then
2131      [ -L /usr/share/grml/desktop.jpg ] && rm /usr/share/grml/desktop.jpg
2132      cp "${LIVECD_PATH}"/desktop/"$DISTRI".jpg /usr/share/grml/desktop.jpg
2133   fi
2134 fi
2135 }
2136 # }}}
2137
2138 ## END OF FILE #################################################################
2139 # vim:foldmethod=marker expandtab ai ft=zsh shiftwidth=3