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