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