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