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