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