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