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