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