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