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