f2e48ac8f205391fa094445ccd17c568611f9de5
[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 # {{{ Collect partitions from /proc/partitions first for enabling DMA
825 check_partitions(){
826 partitions=""
827 IDEDISKS=""
828 while read major minor blocks partition relax; do
829   partition="${partition##*/}"
830   [ -z "$partition" -o ! -e "/dev/$partition" ] && continue
831   case "$partition" in
832     hd?) IDEDISKS="$IDEDISKS $partition";;                # IDE  Harddisk, entire disk
833     sd?) ;;                                               # SCSI Harddisk, entire disk
834 #    [hs]d*) partitions="$partitions /dev/$partition";;    # IDE or SCSI disk partition
835     [hs]d*|ub*) partitions="$partitions /dev/$partition";;    # IDE, USB or SCSI disk partition
836   esac
837 done <<EOT
838 $(awk 'BEGIN{old="__start"}{if($0==old){exit}else{old=$0;if($4&&$4!="name"){print $0}}}' /proc/partitions)
839 EOT
840 }
841 check_partitions >/dev/null 2>&1 # avoid output "check_partitions:3: read-only file system"
842 # }}}
843
844 # {{{ Start brltty
845 config_brltty() {
846   if checkbootparam 'brltty' ; then
847     [ -x /lib/brltty/brltty.sh ] && /lib/brltty/brltty.sh
848   fi
849 }
850 # }}}
851
852 # {{{ Enable DMA for all IDE drives now if not disabled
853 # Notice: Already done by linuxrc, but make sure it's done also on harddisk-installed systems
854 config_dma(){
855 if checkbootparam 'nodma'; then
856   ewarn "Skipping DMA accelleration as requested on boot commandline." ; eend 0
857 else
858   for d in $(cd /proc/ide 2>>$DEBUG && echo hd[a-z]); do
859     if test -d /proc/ide/$d; then
860       if egrep -q 'using_dma[ \t]+0' /proc/ide/$d/settings 2>>$DEBUG; then
861         MODEL="$(cat /proc/ide/$d/model 2>>$DEBUG)"
862         test -z "$MODEL" && MODEL="[GENERIC IDE DEVICE]"
863         einfo "Enabling DMA acceleration for: ${WHITE}$d        ${YELLOW}[${MODEL}]${NORMAL}"
864         echo "using_dma:1" >/proc/ide/$d/settings
865         eend 0
866       fi
867     fi
868   done
869 fi
870 }
871 # }}}
872
873 # {{{ Start creating /etc/fstab with HD partitions and USB SCSI devices now
874 config_fstab(){
875
876 NOSWAP="yes" # we do not use swap by default!
877 if checkbootparam 'swap' || checkbootparam 'anyswap' ; then
878    NOSWAP=''
879    checkbootparam 'anyswap' && export ANYSWAP='yes' || export ANYSWAP=""
880 fi
881
882 # Scan for swap, config, homedir - but only in live-mode
883 if [ -z "$INSTALLED" ] ; then
884    [ -z "$NOSWAP" ] && einfo "Searching for swap partition(s) as requested."
885    GRML_IMG=""
886    GRML_SWP=""
887    HOMEDIR="$(getbootparam 'home')"
888    if [ -n "$partitions" ]; then
889       while read p m f relax; do
890         case "$p" in *fd0*|*proc*|*sys*|*\#*) continue;; esac
891         partoptions="users,exec"
892         fnew=""
893         # it's a swap partition?
894         case "$f" in swap)
895           eindent
896           if [ -n "$NOSWAP" ]; then
897              ewarn "Ignoring swap partition ${WHITE}$p${NORMAL}. (Force usage via boot option 'swap', or execute grml-swapon)"
898              eend 0
899           else
900              case "$(dd if=$p bs=1 count=6 skip=4086 2>/dev/null)" in
901                    S1SUSP|S2SUSP|pmdisk|[zZ]*)
902                      if [ -n "$ANYSWAP" ] ; then
903                         einfo "Using swap partition ${WHITE}${p}${NORMAL} [bootoption anyswap found]."
904                         swapon $p 2>>$DEBUG ; eend $?
905                      else
906                         ewarn "Suspend signature on ${WHITE}${p}${NORMAL} found, not using as swap. (Force usage via boot option: anyswap)"
907                      fi
908                      ;;
909                    *)
910                      if [[ "$p" == LABEL* ]] ; then
911                         p=$(blkid -t $p | awk -F: '{print $1}')
912                      fi
913                      if grep -q $p /proc/swaps ; then
914                         ewarn "Not using swap partition ${WHITE}${p}${NORMAL} as it is already in use." ; eend 0
915                      else
916                         if [ -b "$p" ] ; then
917                         einfo "Using swap partition ${WHITE}${p}${NORMAL}."
918                         swapon $p 2>>$DEBUG ; eend $?
919                         else
920                         ewarn "$p is not a valid block device - not using it therefore." ; eend 0
921                         fi
922                      fi
923                      ;;
924              esac # dd-check
925           fi # -n "$NOSWAP
926           eoutdent
927           continue
928           ;;
929         esac # it's a swap partition?
930
931         # mount read-only
932         MOUNTOPTS="ro"
933         case "$f" in
934           vfat|msdos|ntfs) MOUNTOPTS="$MOUNTOPTS,uid=${fstabuser},gid=${fstabuser}" ;;
935           ext2|ext3|reiserfs|jfs|reiser4|xfs) MOUNTOPTS="$MOUNTOPTS,noatime" ;;
936           *) continue ;;
937           # *) NONEFOUND='1'; continue ;;
938         esac
939
940         # use a swapfile
941         if [ -z "$NOSWAP" ] ; then
942            mount -o "$MOUNTOPTS" -t $f $p $m 2>>$DEBUG && MOUNTED=1 || continue
943            # Activate swapfile, if exists
944            SWAPFILE="$(/bin/ls -1d $m/[Gg][Rr][Mm][Ll].[Ss][Ww][Pp] 2>/dev/null)"
945         fi
946         if [ -z "$NOSWAP" -a -n "$SWAPFILE" -a -f "$SWAPFILE" ]; then
947            mount -o remount,rw $m && MOUNTED=1
948            if swapon "$SWAPFILE" 2>>$DEBUG ; then
949               eindent
950                 einfo "Using GRML swapfile ${WHITE}${SWAPFILE}${NORMAL}."
951               eoutdent
952               fnew="$SWAPFILE swap swap defaults 0 0"
953               grep -q "$fnew" "/etc/fstab" || echo "$fnew" >> /etc/fstab
954               GRML_SWP="$GRML_SWP $SWAPFILE"
955               eend 0
956            fi
957            mount -o remount,ro $m 2>>$DEBUG && MOUNTED=1
958         fi
959
960         # use a image as home
961         IMAGE="$(/bin/ls -1d $m/[Gg][Rr][Mm][Ll].[Ii][Mm][Gg] 2>/dev/null)"
962         if [ -z "$GRML_IMG" -a -n "$IMAGE" -a -f "$IMAGE" ]; then
963            if [ -n "$HOMEDIR" ]; then
964               if [ "$HOMEDIR" != "scan" -a "$HOMEDIR" != "$IMAGE" -a "$HOMEDIR" != "${IMAGE%/*.*}" ]; then
965                  continue
966               fi
967            fi
968            if type -a grml-image >/dev/null 2>&1 && grml-image "$IMAGE" </dev/console >/dev/console 2>&1; then
969               GRML_IMG="$IMAGE"
970               mount -o remount,ro $m 2>>$DEBUG && MOUNTED=1
971            fi
972         fi
973         eend 0
974
975         # Umount, if not in use
976         [ -n "$MOUNTED" ] && umount -r $m 2>/dev/null
977
978       done <<EOT
979       $(cat /etc/fstab)
980 EOT
981    fi # -n $partitions
982 fi # -z $INSTALLED
983 }
984 # }}}
985
986 # {{{ Mouse
987 config_mouse(){
988 if [ -n "$MOUSE_DEVICE" ] ; then
989   einfo "Detecting mouse: ${MOUSE_FULLNAME} at ${MOUSE_DEVICE}" ; eend $?
990 fi
991 }
992 # }}}
993
994 # {{{ IPv6 configuration
995 # Load IPv6 kernel module and print IP adresses
996 config_ipv6(){
997 if checkbootparam 'ipv6'; then
998   einfo "Enabling IPv6 as requested on boot commandline (sleeping for 2 seconds)"
999   modprobe ipv6
1000   # we probably need some time until stateless autoconfiguration has happened
1001   sleep 2
1002   NETDEVICES="$(awk -F: '/eth.:|tr.:|wlan.:/{print $1}' /proc/net/dev 2>>$DEBUG)"
1003   for DEVICE in `echo "$NETDEVICES"`; do
1004     eindent
1005       einfo "$DEVICE:"
1006       ADDRESSES="$(ifconfig $DEVICE | awk '/.*inet6 addr:.*/{print $3}')"
1007       COUNT="$(ifconfig $DEVICE | awk '/.*inet6 addr:.*/{ sum += 1};END {print sum }')"
1008       eindent
1009         for ADDR in `echo "$ADDRESSES"` ; do
1010             einfo "$ADDR"
1011         done
1012         if [ "$COUNT" -eq "0" ] ; then
1013            einfo "(none)" ; eend 1
1014         fi
1015       eoutdent
1016     eoutdent
1017   done
1018   eend 0
1019 fi
1020 }
1021 # }}}
1022
1023 # {{{ CPU-detection
1024 config_cpu(){
1025 if checkbootparam 'nocpu'; then
1026   ewarn "Skipping CPU detection as requested on boot commandline." ; eend 0
1027   return 0
1028 fi
1029
1030 if [[ $(grep -c processor /proc/cpuinfo) -gt 1 ]] ; then
1031    einfo "Found CPU:"
1032    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)
1033    echo $CPU | sed 's/ \{1,\}/ /g'
1034    eend 0
1035 else
1036    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
1037 fi
1038
1039 # no cpufreq setup inside VirtualBox
1040 if $VIRTUALBOX ; then
1041    einfo 'Virtual Box detected, skipping cpufreq setup.' ; eend 0
1042    return 0
1043 fi
1044
1045 if [ -x /etc/init.d/loadcpufreq ] ; then
1046    einfo "Trying to set up cpu frequency scaling:"
1047    eindent
1048    SKIP_CPU_GOVERNOR=''
1049    LOADCPUFREQ=$(mktemp)
1050    /etc/init.d/loadcpufreq start >"$LOADCPUFREQ" 2>&1 ; RC=$?
1051    if grep -q FATAL "$LOADCPUFREQ" ; then
1052       eindent
1053         SKIP_CPU_GOVERNOR=1
1054         oldIFS="$IFS"
1055         IFS="
1056 "
1057          for line in $(grep FATAL "$LOADCPUFREQ" | sed 's/.*FATAL: //; s/ (.*)//') ; do
1058              eerror "$line" ; eend $RC
1059          done
1060          IFS="$oldIFS"
1061       eoutdent
1062    elif grep -q done "$LOADCPUFREQ" ; then
1063       MODULE=$(grep done "$LOADCPUFREQ" | sed 's/.*done (\(.*\))./\1/')
1064       if [ -n "$MODULE" -a "$MODULE" != none ]; then
1065          einfo "Loading cpufreq kernel module $MODULE" ; eend 0
1066       else
1067          SKIP_CPU_GOVERNOR=1
1068          ewarn "Could not find an appropriate kernel module for cpu frequency scaling." ; eend 1
1069       fi
1070    fi
1071
1072    rm -f $LOADCPUFREQ
1073
1074    if [ -z "$SKIP_CPU_GOVERNOR" ] ; then
1075      if grep -vq ondemand /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors; then
1076        einfo "Loading cpufreq_ondemand"
1077        modprobe cpufreq_ondemand
1078        eend $?
1079      fi
1080
1081      einfo "Setting ondemand governor"
1082      RC=0
1083      for file in $(find /sys/devices/system/cpu/ -name scaling_governor 2>/dev/null) ; do
1084        echo ondemand > $file || RC=1
1085      done
1086      eend $RC
1087    fi # cpu-governor
1088
1089    eoutdent
1090 fi
1091 }
1092 # }}}
1093
1094 # {{{ autostart of ssh
1095 config_ssh(){
1096 if checkbootparam 'ssh' ; then
1097    local PASSWD
1098    PASSWD="$(getbootparam 'ssh' 2>>$DEBUG)"
1099
1100    config_userlocal
1101    einfo "Bootoption ssh found, trying to set password for root and user $localuser"
1102    [ -z "$localuser" ] && eend 1
1103
1104    eindent
1105    if [ -z "$PASSWD" ] ; then
1106      set_passwd && ewarn "No given password for found. Using random password: $PASSWD" && eend 0
1107    fi
1108    eoutdent
1109
1110    if [ -n "$PASSWD" ] ; then
1111       chpass_options=""
1112       if chpasswd --help 2>&1 | grep -q -- '-m,' ; then
1113         chpass_options="-m"
1114       fi
1115
1116       echo "$localuser:$PASSWD" | chpasswd $chpass_options
1117       echo "root:$PASSWD" | chpasswd $chpass_options
1118
1119       eindent
1120       ewarn "Warning: please change the password for root and user $localuser as soon as possible!"
1121       eoutdent
1122    fi
1123
1124    einfo "Starting secure shell server in background for root and user $localuser"
1125    /etc/init.d/rmnologin start >>$DEBUG 2>>$DEBUG
1126    /etc/init.d/ssh start >>$DEBUG 2>>$DEBUG &
1127    eend $?
1128
1129 fi
1130 }
1131
1132 # }}}
1133
1134 # {{{ display hostkeys of SSH server
1135 config_display_ssh_fingerprints() {
1136   if ! ls /etc/ssh/ssh_host_\*_key >/dev/null 2>&1 ; then
1137     return 0 # no SSH host keys present
1138   fi
1139
1140   einfo "SSH key fingerprints:"
1141   for file in /etc/ssh/ssh_host_*_key ; do
1142     einfon
1143     ssh-keygen -l -f $file
1144   done | column -t
1145   eend $?
1146 }
1147 # }}}
1148
1149 # {{{ autostart of x11vnc
1150 config_vnc(){
1151 if checkbootparam 'vnc' ; then
1152    config_userlocal
1153    VNC_PASSWD=''
1154    VNC_PASSWD="$(getbootparam 'vnc' 2>>$DEBUG)"
1155    einfo "Bootoption vnc found, trying to set password for user $localuser."
1156    eindent
1157    if [ -z "$VNC_PASSWD" ] ; then
1158       if [ -x /usr/bin/apg ] ; then
1159          VNC_PASSWD="$(apg -M NL -a 0 -m 8 -x 12 -n 1)"
1160       elif [ -x /usr/bin/gpw ] ; then
1161          VNC_PASSWD="$(gpw 1)"
1162       elif [ -x /usr/bin/pwgen ] ; then
1163          VNC_PASSWD="$(pwgen -1 8)"
1164       elif [ -x /usr/bin/hexdump ] ; then
1165          VNC_PASSWD="$(dd if=/dev/urandom bs=14 count=1 2>/dev/null | hexdump | awk '{print $3 $4}')"
1166       elif [ -n "$RANDOM" ] ; then
1167          VNC_PASSWD="${localuser}${RANDOM}"
1168       else
1169          VNC_PASSWD=''
1170          eerror "Empty passphrase and neither pwgen nor hexdump nor \$RANDOM found. Skipping."
1171          eend 1
1172       fi
1173
1174       if [ -n "$VNC_PASSWD" ] ; then
1175          ewarn "No given password for vnc found. Using random password: $VNC_PASSWD" ; eend 0
1176       fi
1177    fi
1178    eoutdent
1179
1180    # finally check if we have a password we can use:
1181    if [ -n "$VNC_PASSWD" ] ; then
1182
1183       VNCDIR="/home/${localuser}/.vnc"
1184       [ -d "$VNCDIR" ] || mkdir "$VNCDIR"
1185
1186       if [ ! -x /usr/bin/x11vnc ] ; then
1187          eerror "Error: x11vnc not found - can not set up vnc. Please make sure to install the x11vnc package."
1188          eend 1
1189       else
1190          /usr/bin/x11vnc -storepasswd "$VNC_PASSWD" "$VNCDIR"/passwd ; eend $?
1191          /bin/chown -R "$localuser": "$VNCDIR"
1192       fi
1193    fi
1194    if checkbootparam 'vnc_connect' ; then
1195       VNC_CONNECT=''
1196       VNC_CONNECT="$(getbootparam 'vnc_connect' 2>>$DEBUG)"
1197       einfo "Bootoption vnc_connect found, will start vnc with connect to $VNC_CONNECT."
1198       #store the options in a file
1199       VNCDIR="/home/${localuser}/.vnc"
1200       [ -d "$VNCDIR" ] || mkdir "$VNCDIR"
1201       echo " --connect $VNC_CONNECT " >> $VNCDIR/options
1202    fi
1203 fi
1204 }
1205 # }}}
1206
1207 # {{{ set password for root and default user
1208 config_passwd(){
1209 if checkbootparam 'passwd' >>$DEBUG 2>&1; then
1210   local PASSWD
1211   PASSWD="$(getbootparam 'passwd' 2>>$DEBUG)"
1212
1213   config_userlocal
1214   einfo "Bootoption passwd found, trying to set password for root and user $localuser"
1215   [ -z "$localuser" ] && eend 1
1216
1217   eindent
1218   if [ -z "$PASSWD" ] ; then
1219     set_passwd && ewarn "No given password for found. Using random password: $PASSWD" && eend 0
1220   fi
1221   eoutdent
1222
1223   if [ -n "$PASSWD" ] ; then
1224     chpass_options=""
1225     if chpasswd --help 2>&1 | grep -q -- '-m,' ; then
1226       chpass_options="-m"
1227     fi
1228
1229     echo "$localuser:$PASSWD" | chpasswd $chpass_options
1230     echo "root:$PASSWD" | chpasswd $chpass_options
1231
1232     eindent
1233     ewarn "Warning: please change the password for root and user $localuser as soon as possible!"
1234     eoutdent
1235   fi
1236
1237 fi
1238
1239 if checkbootparam 'encpasswd' >>$DEBUG 2>&1; then
1240   local PASSWD
1241   PASSWD="$(getbootparam 'encpasswd' 2>>$DEBUG)"
1242
1243   if [ -z "$PASSWD" ] ; then
1244     eerror "No hashed password found, can not set password."
1245     eend 1
1246     return
1247   fi
1248
1249   config_userlocal
1250   einfo "Bootoption encpasswd found, trying to set hashed password for root and user $localuser"
1251   [ -z "$localuser" ] && eend 1
1252
1253   if [ -n "$PASSWD" ] ; then
1254     chpass_options="-e"
1255
1256     echo "$localuser:$PASSWD" | chpasswd $chpass_options
1257     echo "root:$PASSWD" | chpasswd $chpass_options
1258
1259     eindent
1260     ewarn "Warning: please change the password for root and user $localuser as soon as possible!"
1261     eoutdent
1262   fi
1263
1264 fi
1265 }
1266 # }}}
1267
1268 # {{{ Sound
1269 config_mixer () {
1270    if ! [ -x /usr/bin/amixer ] ; then
1271       eerror "amixer binary not available. Can not set sound volumes therefore."
1272       eend 1
1273    else
1274       if ! [ -r /proc/asound/cards ] ; then
1275          ewarn "No soundcard present, skipping mixer settings therefore."
1276          eend 0
1277          return
1278       fi
1279
1280       for card in $(cat /proc/asound/cards| grep -e '^\s*[0-9]' | awk '{print $1}') ; do
1281          einfo "Configuring soundcard \"$(awk -F\[ '/^ *'$card' \[/{ FS=" "; $0=$2; print $1}' < /proc/asound/cards)\""
1282          eindent
1283
1284          if checkbootparam 'vol' ; then
1285             VOL="$(getbootparam 'vol' 2>>$DEBUG)"
1286             if [ -z "$VOL" ] ; then
1287                eerror "Bootoption vol found but no volume level/parameter given. Using defaults (75%)."
1288                VOL='75'
1289                eend 1
1290             fi
1291          else
1292             VOL='75'
1293          fi
1294
1295          if checkbootparam 'nosound' ; then
1296             einfo "Muting sound devices on request."
1297             ERROR=$(amixer -q set Master mute)
1298             RC=$?
1299             if [ -n "$ERROR" ] ; then
1300                eindent
1301                eerror "Problem muting sound devices: $ERROR"
1302                eoutdent
1303             fi
1304             eend $RC
1305          elif [ -z "$INSTALLED" ] ; then
1306             einfo "Setting mixer volumes to level ${WHITE}${VOL}${NORMAL}."
1307
1308             if checkbootparam 'micvol' ; then
1309                MICVOL="$(getbootparam 'micvol' 2>>$DEBUG)"
1310                einfo "Setting microphone to ${WHITE}${MICVOL}${NORMAL}."
1311             else
1312                MICVOL=0
1313             fi
1314
1315             CONTROLS=$(amixer -c $card scontrols | awk -F"Simple mixer control " '{print $2}')
1316             IFSOLD=${IFS:-}
1317             IFS='
1318 '
1319             for CONTROL in ${=CONTROLS} ; do
1320                # such devices can not be controlled with amixer ... unmute
1321                [[ "$CONTROL" == *Console* ]] && continue
1322
1323                if ! echo "${CONTROL}" | grep -q -i "mic" ; then
1324                    if amixer -c $card sget "${CONTROL}" | grep -q 'Capabilities:.*pswitch' ; then
1325                       amixer -c $card -q set "${CONTROL}" unmute
1326                    fi
1327                    if amixer -c $card sget "${CONTROL}" | grep -q -P 'Capabilities:.*(pvolume| volume)' ; then
1328                       amixer -c $card -q set "${CONTROL}" "${VOL}"%
1329                    fi
1330                fi
1331
1332                if [ ${MICVOL} -ne 0 ] ; then
1333                   if amixer -c $card sget "${CONTROL}" | grep -q 'Capabilities:.*cswitch' ; then
1334                      amixer -c $card -q set "${CONTROL}" unmute
1335                   fi
1336                   if amixer -c $card sget "${CONTROL}" | grep -q 'Capabilities:.*cvolume' ; then
1337                      amixer -c $card -q set "${CONTROL}" $MICVOL%
1338                   fi
1339                   eend $?
1340                fi
1341             done
1342             IFS=$IFSOLD
1343          fi # checkbootparam 'nosound'
1344          eoutdent
1345       done
1346    fi
1347 }
1348 # }}}
1349
1350 # {{{ modem detection
1351 config_modem(){
1352 if checkbootparam 'nomodem'; then
1353   ewarn "Skipping check for AC97 modem controller as requested on boot commandline." ; eend 0
1354 else
1355   if [ -x /etc/init.d/sl-modem-daemon ] ; then
1356      if lspci | grep Intel | grep -q "AC'97 Modem Controller" ; then
1357         einfo "AC97 modem controller detected. Start it running 'Start sl-modem-daemon'."
1358         eend 0
1359      fi
1360   fi
1361 fi
1362 }
1363 # }}}
1364
1365 # {{{ wondershaper
1366 config_wondershaper(){
1367  if checkbootparam 'wondershaper' ; then
1368     WONDER="$(getbootparam 'wondershaper' 2>>$DEBUG)"
1369     CMD=wondershaper
1370     DEVICE=""
1371     DOWNSTREAM=""
1372     UPSTREAM=""
1373     if [ -n "$WONDER" ]; then
1374       # Extra options
1375       DEVICE="${WONDER%%,*}"
1376       R="${WONDER#*,}"
1377       if [ -n "$R" -a "$R" != "$WONDER" ]; then
1378         WONDER="$R"
1379         DOWNSTREAM="${WONDER%%,*}"
1380         R="${WONDER#*,}"
1381         if [ -n "$R" -a "$R" != "$WONDER" ]; then
1382           WONDER="$R"
1383           UPSTREAM="${WONDER%%,*}"
1384           R="${WONDER#*,}"
1385         fi
1386       fi
1387     fi
1388     [ -n "$DEVICE" ]     && CMD="$CMD $DEVICE"
1389     [ -n "$DOWNSTREAM" ] && CMD="$CMD $DOWNSTREAM"
1390     [ -n "$UPSTREAM" ]   && CMD="$CMD $UPSTREAM"
1391     einfo "Starting wondershaper (${CMD}) in background."
1392     ( sh -c $CMD & ) && eend 0
1393  fi
1394 }
1395 # }}}
1396
1397 # {{{ syslog-ng
1398 config_syslog(){
1399  if checkbootparam 'nosyslog'; then
1400     ewarn "Not starting syslog daemon as requested on boot commandline." ; eend 0
1401  else
1402     SYSLOGD=''
1403     [ -x /etc/init.d/syslog-ng ] && SYSLOGD='syslog-ng'
1404     [ -x /etc/init.d/rsyslog   ] && SYSLOGD='rsyslog'
1405     [ -x /etc/init.d/dsyslog   ] && SYSLOGD='dsyslog'
1406     [ -x /etc/init.d/sysklogd  ] && SYSLOGD='sysklogd'
1407     [ -x /etc/init.d/inetutils-syslogd ] && SYSLOGD='inetutils-syslogd'
1408
1409     if [ -z "$SYSLOGD" ] ; then
1410        eerror "No syslog daemon found." ; eend 1
1411     else
1412        einfo "Starting $SYSLOGD in background."
1413        /etc/init.d/$SYSLOGD start >>$DEBUG &
1414        eend 0
1415     fi
1416  fi
1417 }
1418 # }}}
1419
1420 # {{{ gpm
1421 config_gpm(){
1422  if checkbootparam 'nogpm'; then
1423   ewarn "Not starting GPM as requested on boot commandline." ; eend 0
1424  else
1425    if ! [ -r /dev/input/mice ] ; then
1426       eerror "No mouse found - not starting GPM." ; eend 1
1427    else
1428       einfo "Starting gpm in background."
1429       /etc/init.d/gpm start >>$DEBUG &
1430       # ( while [ ! -e /dev/psaux ]; do sleep 5; done; /etc/init.d/gpm start >>$DEBUG ) &
1431       eend 0
1432    fi
1433  fi
1434 }
1435 # }}}
1436
1437 # {{{ services
1438 config_services(){
1439  if checkbootparam 'services' ; then
1440     SERVICE="$(getbootparam 'services' 2>>$DEBUG)"
1441     SERVICELIST=$(echo "$SERVICE" | sed 's/,/\\n/g')
1442     SERVICENL=$(echo "$SERVICE" | sed 's/,/ /g')
1443     for service in $(echo -e $SERVICELIST) ; do
1444       # support running (custom) init scripts in non-blocking mode
1445       # if they contain the keyword "DO_NO_RUN_IN_BACKGROUND".
1446       if grep -q 'DO_NO_RUN_IN_BACKGROUND' "/etc/init.d/${service}" 2>>$DEBUG ; then
1447         einfo "Starting service ${service}."
1448         /etc/init.d/${service} start >>$DEBUG
1449       else
1450         einfo "Starting service ${service} in background."
1451         /etc/init.d/${service} start >>$DEBUG &
1452       fi
1453     done
1454     eend $?
1455  fi
1456 }
1457 # }}}
1458
1459 # {{{ remote files
1460 get_remote_file() {
1461   [ "$#" -eq 2 ] || ( echo "Error: wrong parameter for get_remote_file()" ; return 1 )
1462   SOURCE=$(eval echo "$1")
1463   TARGET="$2"
1464   getconfig() {
1465   wget --timeout=10 --dns-timeout=10  --connect-timeout=10 --tries=1 \
1466        --read-timeout=10 ${SOURCE} -O ${TARGET} && return 0 || return 1
1467   }
1468   einfo "Trying to get ${WHITE}${TARGET}${NORMAL}"
1469   counter=10
1470   while ! getconfig && [[ "$counter" != 0 ]] ; do
1471     echo -n "Sleeping for 1 second and trying to get config again... "
1472     counter=$(( counter-1 ))
1473     echo "$counter tries left" ; sleep 1
1474   done
1475   if [ -s "$TARGET" ] ; then
1476     einfo "Downloading was successfull." ; eend 0
1477     einfo "md5sum of ${WHITE}${TARGET}${NORMAL}: "
1478     md5sum ${TARGET} ; eend 0
1479     return 0;
1480   else
1481     einfo "Sorry, could not fetch ${SOURCE}" ; eend 1
1482     return 1;
1483  fi
1484 }
1485 # }}}
1486
1487 # {{{ config files
1488 config_netconfig(){
1489  if checkbootparam 'netconfig' ; then
1490   CONFIG="$(getbootparam 'netconfig' 2>>$DEBUG)"
1491   CONFIGFILE='/tmp/netconfig.grml'
1492
1493   if get_remote_file ${CONFIG} ${CONFIGFILE} ; then
1494     cd / && einfo "Unpacking ${WHITE}${CONFIGFILE}${NORMAL}:" && /usr/bin/unp $CONFIGFILE $EXTRACTOPTIONS ; eend $?
1495   fi
1496
1497  fi
1498 }
1499 # }}}
1500
1501 # {{{ remote scripts
1502 config_netscript() {
1503  if checkbootparam 'netscript' ; then
1504   CONFIG="$(getbootparam 'netscript' 2>>$DEBUG)"
1505   SCRIPTFILE='/tmp/netscript.grml'
1506
1507   if get_remote_file ${CONFIG} ${SCRIPTFILE} ; then
1508     chmod +x ${SCRIPTFILE}
1509     einfo "Running ${WHITE}${SCRIPTFILE}${NORMAL}:" && NETSCRIPT=${CONFIG} ${SCRIPTFILE} ; eend $?
1510   fi
1511
1512  fi
1513 }
1514 # }}}
1515
1516 # {{{ stats
1517 config_stats() {
1518  if ! checkbootparam 'nostats' ; then
1519    BASE_URL="http://stats.grml.org/report/"
1520    ACTION_NAME=Boot
1521
1522    HOST_ID=$(cat /proc/sys/kernel/random/boot_id)
1523
1524    grep -q " lm " /proc/cpuinfo && HAS_64BIT="1" || HAS_64BIT="0"
1525    DATE_STRING=$(date +'h=%H&m=%M&s=%S')
1526    [ -e /etc/grml_version ] && VERSION=$(cat /etc/grml_version) || \
1527      VERSION=$(lsb_release -d | awk -F: '{gsub(/^[ \t]+/, "", $2); print $2}')
1528
1529    PARAMS="$( echo "$CMDLINE" | sed -e 's/=[^ ]*/=x/g' | tr " " "\n"|sort|tr "\n" " " )"
1530
1531    echo "$CMDLINE" | grep -q -e "fetch" -e "nfsroot" && BOOT="remote"
1532    [ -z "$BOOT" ] && BOOT="local"
1533
1534    ADDITIONAL_PARAMS=""
1535    ( [ -n "$COLUMNS" ] && [ -n "$LINES" ] ) && \
1536      ADDITIONAL_PARAMS="$ADDITIONAL_PARAMS&res=$((COLUMNS * 8))x$((LINES * 16))"
1537
1538    URI='$BASE_URL?action=${ACTION_NAME}\&$DATE_STRING\&unique_id=${HOST_ID}\&support_64bit=$HAS_64BIT\&version=$VERSION\&bootup=$BOOT\&params=$PARAMS$ADDITIONAL_PARAMS'
1539
1540    get_remote_file "$URI" "/dev/null"  >/dev/null 2>&1 &!
1541  fi
1542 }
1543 # }}}
1544
1545 # {{{ fix/workaround for unionfs
1546 fix_unionfs(){
1547   if [ -z "$INSTALLED" ]; then
1548    touch /var/cache/apt/*cache.bin
1549   fi
1550 }
1551 # }}}
1552
1553 # {{{ start X window system via grml-x
1554 config_x_startup(){
1555 # make sure we start X only if startx is used *before* a nostartx option
1556 # so it's possible to disable automatic X startup using nostart
1557 if checkbootparam 'startx' && ! echo "$CMDLINE" | grep -q 'startx.*nostartx' ; then
1558  if [ -x "$(which X)" ] ; then
1559   if [ -z "$INSTALLED" ] ; then
1560    WINDOWMANAGER="$(getbootparam 'startx' 2>>$DEBUG)"
1561    if [ -z "$WINDOWMANAGER" ] ; then
1562      einfo "No window manager specified. Using default one." && eend 0
1563    else
1564      einfo "Window manager ${WHITE}${WINDOWMANAGER}${NORMAL} found as bootoption." && eend 0
1565    fi
1566    einfo "Setting up and invoking grml-x ${WINDOWMANAGER}. Just exit X windows system to get full featured consoles."
1567    config_userlocal
1568  cat>|/etc/init.d/xstartup<<EOF
1569 #!/bin/sh
1570 su $localuser -c "/usr/bin/grml-x ${WINDOWMANAGER}"
1571 EOF
1572    chmod 755 /etc/init.d/xstartup
1573
1574    # adjust inittab for xstartup
1575    if grep -q '^6:' /etc/inittab ; then
1576       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
1577    else # just append tty6 to inittab if no definition is present:
1578       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
1579    fi
1580
1581    /sbin/telinit q ; eend $?
1582
1583    if grep -q '^allowed_users=' /etc/X11/Xwrapper.config ; then
1584       sed -i 's/^allowed_users=.*/allowed_users=anybody/' /etc/X11/Xwrapper.config
1585    else
1586       echo 'allowed_users=anybody' >> /etc/X11/Xwrapper.config
1587    fi
1588
1589   else
1590     eerror "We are not running in live mode - startx will not work, skipping it."
1591     eerror " -> Please use something like xdm, gdm or kdm for starting X on a harddisk system!" ; eend 1
1592   fi
1593  else
1594    eerror "/usr/bin/X is not present on this grml flavour."
1595    eerror "  -> Boot parameter startx does not work therefore." ; eend 1
1596  fi
1597 fi
1598 }
1599 # }}}
1600
1601 # {{{ configuration framework
1602 config_extract(){
1603 if checkbootparam 'extract' ; then
1604  EXTRACT="$(getbootparam 'extract' 2>>$DEBUG)"
1605  EXTRACTOPTIONS="-- -x $EXTRACT"
1606 fi
1607 }
1608
1609 config_finddcsdir() {
1610 #  - If no GRMLCFG partition is found and noautoconfig is _not_ given
1611 #    on the command line, nothing is changed and the dcs files are
1612 #    searched within the .iso, $dcs-dir is set to the root directory
1613 #    within the .iso
1614 #  - If a GRMLCFG partition is found, $dcs-dir is set to the root of
1615 #    the GRMLCFG partition unless noautoconfig is set. If noautoconfig is
1616 #    set, $dcs-dir is set to the root directory within the .iso.
1617 #  - If myconfig=foo is set on the command line, $dcs-dir is set to
1618 #    foo, even if a GRMLCFG partition is present.
1619 DCSDIR=""
1620 DCSMP="/mnt/grml"
1621 # autoconfig, see issue673
1622 GRMLCFG="$(getbootparam 'autoconfig' 2>>$DEBUG)"
1623 [ -n "$GRMLCFG" ] || GRMLCFG="GRMLCFG"
1624 if checkbootparam 'noautoconfig' || checkbootparam 'forensic' ; then
1625   DCSDIR="${LIVECD_PATH}" # set default so it works for "scripts" boot option as expected
1626   ewarn "Skipping running automount of device(s) labeled $GRMLCFG as requested." ; eend 0
1627 else
1628   if [ -z "$INSTALLED" ] ; then
1629     if checkbootparam 'myconfig' ; then
1630       DCSDEVICE="$(getbootparam 'myconfig' 2>>$DEBUG)"
1631       if [ -z "$DCSDEVICE" ]; then
1632         eerror "Error: No device for bootoption myconfig provided." ; eend 1
1633       fi # [ -z "$DCSDEVICE" ]
1634     elif checkvalue $CONFIG_MYCONFIG; then # checkbootparam myconfig
1635       einfo "Searching for device(s) labeled with $GRMLCFG. (Disable this via boot option: noautoconfig)" ; eend 0
1636       eindent
1637       DCSDEVICE=$(blkid -t LABEL=$GRMLCFG | head -1 | awk -F: '{print $1}')
1638
1639       modprobe 9p 2>/dev/null || true
1640       if [ -z "$DCSDEVICE" ] && grep -q 9p /proc/filesystems ; then
1641           if grep -q "$GRMLCFG" /sys/bus/virtio/devices/*/mount_tag 2>/dev/null ; then
1642             einfo "Found 9p-virtio fs with mount_tag $GRMLCFG"
1643             DCSDEVICE="$GRMLCFG"
1644             MOUNTOPTIONS="ro,trans=virtio"
1645             DCSFS="9p"
1646           fi
1647       fi
1648
1649       if [ -n "$DCSDEVICE" ]; then
1650         DCSMP="/mnt/grmlcfg"
1651       fi
1652       eoutdent
1653     fi
1654
1655     # if not specified/present then assume default:
1656     if [ -z "$DCSDEVICE" ]; then
1657       DCSDIR="${LIVECD_PATH}"
1658     else
1659       eindent
1660       einfo "debs, config, scripts are read from $DCSDEVICE." ; eend 0
1661       DCSDIR="$(< /proc/mounts awk -v DCSDEV=$DCSDEVICE '{if ($1 == DCSDEV) { print $2 }}')"
1662       if [ -n "$DCSDIR" ]; then
1663         ewarn "$DCSDEVICE already mounted on $DCSDIR"; eend 0
1664       else
1665         [ -d $DCSMP ] || mkdir $DCSMP
1666         umount $DCSMP >>$DEBUG 2>&1 # make sure it is not mounted
1667         mount -o ${MOUNTOPTIONS:-ro} -t ${DCSFS:-auto} $DCSDEVICE  $DCSMP ; RC="$?"
1668         if [[ $RC == 0 ]]; then
1669           einfo "Successfully mounted $DCSDEVICE to $DCSMP (readonly)." ; eend 0
1670         else
1671           eerror "Error: mounting $DCSDEVICE to $DCSMP (readonly) failed." ; eend 1
1672         fi
1673         DCSDIR="$DCSMP"
1674       fi
1675       eoutdent
1676     fi
1677   fi
1678 fi
1679
1680 if [ -n "$DCSDIR" -a "$DCSDIR" != "${LIVECD_PATH}" ] ; then
1681   einfo "Debs, config, scripts (if present) will be read from $DCSDIR." ; eend 0
1682 elif checkbootparam 'debs' || checkbootparam 'config' || checkbootparam 'scripts'; then
1683   einfo "Debs, config, scripts will be read from the live image directly." ; eend 0
1684 fi
1685 }
1686
1687
1688 config_partconf() {
1689 if checkbootparam 'partconf' ; then
1690  MOUNTDEVICE="$(getbootparam 'partconf' 2>>$DEBUG)"
1691  if [ -n "$MOUNTDEVICE" ]; then
1692    [ -d /mnt/grml ] || mkdir /mnt/grml
1693    mount -o ro -t auto $MOUNTDEVICE /mnt/grml ; RC="$?"
1694     if [[ $RC == 0 ]]; then
1695       einfo "Successfully mounted $MOUNTDEVICE to /mnt/grml (readonly)." ; eend 0
1696       einfo "Copying files from $MOUNTDEVICE over grml system."
1697       for file in `cat /etc/grml/partconf` ; do
1698         [ -d /mnt/grml/$file ] && cp -a /mnt/grml/${file}* ${file} && echo "copied: $file"
1699         [ -f /mnt/grml/$file ] && cp -a /mnt/grml/${file}  ${file} && echo "copied: $file"
1700       done && eend 0
1701     else
1702       einfo "Could not mount $MOUNTDEVICE to /mnt/grml - sorry." ; eend 1
1703     fi # mount $MOUNTDEVICE
1704    grep -q '/mnt/grml' /proc/mounts && umount /mnt/grml
1705  else
1706    einfo "Sorry, no device for bootoption partconf provided. Skipping." ; eend 1
1707  fi # [ -n "$MOUNTDEVICE" ]
1708 fi
1709 }
1710 # }}}
1711
1712 # {{{ /cdrom/.*-options
1713 config_debs(){
1714 if checkbootparam 'debs' ; then
1715    iszsh && setopt localoptions shwordsplit
1716    DEBS="$(getbootparam 'debs' 2>>$DEBUG)"
1717    if [ -z "$DEBS" ] ; then
1718       DEBS="*.deb"
1719    fi
1720    if ! echo $DEBS | grep -q '/'; then
1721      # backwards compatibility: if no path is given get debs from debs/
1722      DEBS="debs/$DEBS"
1723    fi
1724    einfo "Trying to install Debian package(s) ${DEBS}"
1725    DEBS="$(eval echo ${DCSDIR}/$DEBS)"
1726    dpkg -i $DEBS ; eend $?
1727 fi
1728 }
1729
1730 config_scripts(){
1731 if checkbootparam 'scripts' || [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1732    SCRIPTS="$(getbootparam 'scripts' 2>>$DEBUG)"
1733    if [ -d ${DCSDIR}/scripts ] && [ -z "$SCRIPTS" ]; then
1734      SCRIPTS="$(cd ${DCSDIR}/scripts; /bin/ls -1d [Gg][Rr][Mm][Ll].[Ss][Hh] 2>>$DEBUG)"
1735    fi
1736    if ! echo $SCRIPTS | grep -q '/'; then
1737      # backwards compatibility: if no path is given get scripts from scripts/
1738      SCRIPTS="scripts/$SCRIPTS"
1739    fi
1740    if [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1741      # we are executing from a GRMLCFG labeled fs
1742      # kick everything we have done before and start over
1743      SCRIPTS="$(cd ${DCSDIR}; /bin/ls -1d [Gg][Rr][Mm][Ll].[Ss][Hh] 2>>$DEBUG)"
1744    fi
1745    if [ -n "$SCRIPTS" ]; then
1746      SCRIPTS="${DCSDIR}/$SCRIPTS"
1747      if [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1748        einfo "Trying to execute ${SCRIPTS}"
1749        sh -c $SCRIPTS
1750        eend $?
1751      elif [ -d "$SCRIPTS" ]; then
1752        einfo "Bootparameter scripts found. Trying to execute from directory ${SCRIPTS}:"
1753        run-parts --regex '.*' $SCRIPTS
1754        eend $?
1755      else
1756        einfo "Bootparameter scripts found. Trying to execute ${SCRIPTS}:"
1757        sh -c $SCRIPTS
1758        eend $?
1759      fi
1760    fi
1761 fi
1762 }
1763
1764 config_config(){
1765 if checkbootparam 'config' || [ "$DCSMP" = "/mnt/grmlcfg" ]; then
1766   CONFIG="$(getbootparam 'config' 2>>$DEBUG)"
1767   if [ -z "$CONFIG" ]; then
1768     CONFIG="$(cd ${DCSDIR}; ls -1d [Cc][Oo][Nn][Ff][Ii][Gg].[Tt][Bb][Zz] 2>>$DEBUG)"
1769   fi
1770   if [ -n "$CONFIG" ]; then
1771     if [ -d "${DCSDIR}/${CONFIG}" ] ; then
1772       einfo "Taking configuration from directory ${DCSDIR}/${CONFIG}"
1773
1774       cp -a ${DCSDIR}/${CONFIG}/* /
1775     elif [ -f "${DCSDIR}/${CONFIG}" ]; then
1776       einfo "Extracting configuration from file ${DCSDIR}/${CONFIG}"
1777
1778       cd /
1779       unp ${DCSDIR}/${CONFIG} $EXTRACTOPTIONS ; eend $?
1780     else
1781       ewarn "Sorry, could not find configuration file or directory ${DCSDIR}/${FILENAME}." ; eend 1
1782     fi
1783   fi
1784 fi
1785 }
1786 # }}}
1787
1788 # {{{ confing_umount_dcsdir
1789 config_umount_dcsdir(){
1790    # umount $DCSMP if it was mounted by finddcsdir
1791    grep -q "$DCSMP" /proc/mounts && umount "$DCSMP"
1792 }
1793 # }}}
1794
1795 # {{{ mypath
1796 config_mypath(){
1797 if checkbootparam 'mypath' ; then
1798    MY_PATH="$(getbootparam 'mypath' 2>>$DEBUG)"
1799    einfo "Bootparameter mypath found, adding ${MY_PATH} to /etc/grml/my_path"
1800    touch /etc/grml/my_path
1801    chmod 644 /etc/grml/my_path
1802    # make sure the directories exist:
1803    eindent
1804    for i in $(echo $MY_PATH | sed 's/:/\n/g') ; do
1805        if ! [ -d "$i" ] ; then
1806           einfo "Creating directory $i"
1807           mkdir -p "$i" ; eend $?
1808        fi
1809    done
1810    grep -q "${MY_PATH}" /etc/grml/my_path || echo "${MY_PATH}" >> /etc/grml/my_path ; eend $?
1811    eoutdent
1812 fi
1813 }
1814 # }}}
1815
1816 # {{{ distcc
1817 config_distcc(){
1818 if checkbootparam 'distcc' ; then
1819  OPTIONS="$(getbootparam 'distcc' 2>>$DEBUG)"
1820  if [ -n "$OPTIONS" ]; then
1821     NET=""
1822     INTERFACE=""
1823     if [ -n "$OPTIONS" ]; then
1824       NET="${OPTIONS%%,*}"
1825       R="${OPTIONS#*,}"
1826       if [ -n "$R" -a "$R" != "$OPTIONS" ]; then
1827         OPTIONS="$R"
1828         INTERFACE="${OPTIONS%%,*}"
1829         R="${OPTIONS#*,}"
1830       fi
1831     fi
1832  fi
1833  CONFIG=/etc/default/distcc
1834  sed -i "s#^STARTDISTCC=.*#STARTDISTCC=YES#"  $CONFIG
1835  sed -i "s#^ALLOWEDNETS=.*#ALLOWEDNETS=$NET#" $CONFIG
1836
1837  if [ -n "$INTERFACE" ] ; then
1838    IP=$(LANG=C ifconfig $INTERFACE | gawk -F: /"inet addr"/'{print $2}' | gawk '{print $1}')
1839
1840    counter=10
1841    while [ -z "$IP" ] && [[ "$counter" != 0 ]] ; do
1842      counter=$(( counter-1 ))
1843      ewarn "No ip address for $INTERFACE found. Sleeping for 3 seconds. $counter tries left."
1844      sleep 3
1845      IP=$(LANG=C ifconfig $INTERFACE | gawk -F: /"inet addr"/'{print $2}' | gawk '{print $1}')
1846    done
1847  fi
1848
1849  if [ -n "$IP" ] ; then
1850    sed -i "s#^LISTENER=.*#LISTENER=$IP#"      $CONFIG
1851
1852    einfo "Bootoption distcc found. Preparing setup for distcc daemon."
1853    eindent
1854     id distccd >/dev/null 2>&1 || \
1855     (
1856       einfo "Creating distcc user" ; \
1857       adduser --quiet --system --ingroup nogroup --home / --no-create-home distccd ; eend $?
1858     )
1859
1860     einfo "Starting distcc for network ${NET}, listening on ${IP}."
1861    /etc/init.d/distcc start >/dev/null ; eend $?
1862    eoutdent
1863  else
1864    eerror "No ip address for $INTERFACE found. distcc can not be used without it." ; eend 1
1865  fi
1866 fi
1867
1868 if checkbootparam 'gcc'; then
1869  GCC="$(getbootparam 'gcc' 2>>$DEBUG)"
1870  eindent
1871  einfo "Pointing /usr/bin/gcc to /usr/bin/gcc-${GCC}."
1872  eoutdent
1873  rm -f /usr/bin/gcc
1874  ln -s /usr/bin/gcc-${GCC} /usr/bin/gcc ; eend $?
1875 fi
1876
1877 if checkbootparam 'gpp'; then
1878  GPP="$(getbootparam 'gpp' 2>>$DEBUG)"
1879  eindent
1880   einfo "Pointing /usr/bin/g++ to /usr/bin/g++-${GPP}."
1881   if [ -x /usr/bin/g++-${GPP} ] ; then
1882      rm -f /usr/bin/g++
1883      ln -s /usr/bin/g++-${GPP} /usr/bin/g++ ; eend $?
1884   fi
1885   einfo "Pointing /usr/bin/cpp to /usr/bin/cpp-${GPP}."
1886   if [ -x /usr/bin/cpp-${GPP} ] ; then
1887      rm -f /usr/bin/cpp
1888      ln -s /usr/bin/cpp-${GPP} /usr/bin/cpp ; eend $?
1889   fi
1890  eoutdent
1891 fi
1892
1893 }
1894 # }}}
1895
1896 # {{{ load modules
1897 # Notice: use it only on live-cd system, if running from harddisk please
1898 # add modules to /etc/modules and activate /etc/init.d/module-init-tools
1899 # in /etc/runlevel.conf
1900 config_modules(){
1901 MODULES_FILE=/etc/grml/modules
1902 if checkbootparam 'nomodules' ; then
1903   ewarn "Skipping loading of modules defined in ${MODULES_FILE} as requested." ; eend 0
1904 elif [ -z "$INSTALLED" ]; then
1905  if [ -r $MODULES_FILE ] ; then
1906   einfo "Loading modules specified in ${MODULES_FILE}:"
1907   eindent
1908   grep '^[^#]' $MODULES_FILE | \
1909   while read module args; do
1910     [ "$module" ] || continue
1911       einfo "${module}"
1912       modprobe $module $args ; eend $?
1913   done
1914   eoutdent
1915  else
1916   ewarn "File $MODULES_FILE does not exist. Skipping loading of specific modules." ; eend 1
1917  fi
1918 fi
1919 }
1920 # }}}
1921
1922 # {{{ SW-RAID
1923 config_swraid(){
1924   [ -n "$INSTALLED" ] && return 0
1925
1926   # notice: checkbootparam "forensic" is just for users who don't know how to really use the bootoption
1927   if checkbootparam 'noraid'   || checkbootparam 'noswraid' || \
1928      checkbootparam 'forensic' || checkbootparam 'raid=noautodetect' ; then
1929      ewarn "Skipping SW-RAID code as requested on boot commandline." ; eend 0
1930   else
1931     [ -e /proc/mdstat ] || modprobe md_mod
1932     if ! [ -x /sbin/mdadm ] ; then
1933        eerror "mdadm not available, can not execute it." ; eend 1
1934     else
1935
1936        # if ! egrep -qv '^(MAILADDR.*|#.*|)$' /etc/mdadm/mdadm.conf 2>>$DEBUG ; then
1937        # find out whether we have a valid configuration file already
1938        if ! grep -q ARRAY /etc/mdadm/mdadm.conf 2>>$DEBUG ; then
1939           einfo "Creating /etc/mdadm/mdadm.conf for use with mdadm."
1940           [ -r /etc/mdadm/mdadm.conf ] && mv /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.old
1941           MDADM_MAILADDR__='root' /usr/share/mdadm/mkconf > /etc/mdadm/mdadm.conf ; eend $?
1942         else
1943           ewarn "/etc/mdadm/mdadm.conf looks like a configured mdadm setup, will not touch it." ; eend 0
1944        fi
1945
1946        if ! checkbootparam 'swraid' ; then
1947           eindent
1948           einfo "Just run 'Start mdadm-raid' to assemble md arrays or boot using 'swraid' as bootoption for autostart."
1949           eoutdent
1950        else
1951           einfo "Bootoption swraid found. Searching for software RAID arrays:"
1952           eindent
1953            IFSOLD=${IFS:-}
1954            IFS='
1955 '
1956            for line in $(mdadm --assemble --scan --auto=yes --symlink=no 2>&1) ; do
1957                case $line in
1958                  *'No arrays found'*)
1959                    ewarn "$line" ; eend 0
1960                    ;;
1961                  *)
1962                    einfo "$line" ; eend 0
1963                    ;;
1964                esac
1965            done
1966            IFS=$IFSOLD
1967          eoutdent
1968
1969          if [ -r /proc/mdstat ] ; then
1970             eindent
1971             MDSTAT=$(grep '^md[0-9]' /proc/mdstat)
1972             if [ -z "$MDSTAT" ] ; then
1973                ewarn "No active arrays found" ; eend 0
1974             else
1975                IFSOLD=${IFS:-}
1976                IFS='
1977 '
1978                for line in $(grep '^md[0-9]' /proc/mdstat) ; do
1979                    einfo "active arrays: $line" ; eend 0
1980                done
1981                IFS=$IFSOLD
1982             fi
1983             eoutdent
1984          fi # /proc/mdstat
1985        fi # bootoption swraid
1986
1987      fi # is /sbin/mdadm executable?
1988   fi # check for bootoptions
1989 }
1990 # }}}
1991
1992 # {{{ dmraid
1993 config_dmraid(){
1994   [ -n "$INSTALLED" ] && return 0
1995
1996   if checkbootparam 'nodmraid' ; then
1997     ewarn "Skipping dmraid code as requested on boot commandline." ; eend 0
1998     return 0
1999   fi
2000
2001   if ! [ -x /sbin/dmraid ] ; then
2002     eerror "dmraid not available, can not execute it." ; eend 1
2003     return
2004   fi
2005
2006   dmraid_wrapper() {
2007     # usage: dmraid_wrapper <dmraid_option>
2008     [ -n "$1" ] || return 1
2009
2010     IFSOLD=${IFS:-}
2011     IFS='
2012 '
2013     eindent
2014
2015     for line in $(dmraid $1 ; echo errcode:$?); do
2016       case $line in
2017         *'no block devices found'*)
2018           einfo "No block devices found" ; eend 0
2019           break
2020           ;;
2021         *'no raid disks'*)
2022           einfo "No active dmraid devices found" ; eend 0
2023           break
2024           ;;
2025         errcode:0)
2026           eend 0;
2027           ;;
2028         errcode:1)
2029           eend 1
2030           ;;
2031         *)
2032           einfo "$line"
2033           ;;
2034       esac
2035     done
2036
2037     eoutdent
2038     IFS=$IFSOLD
2039   }
2040
2041   if checkbootparam 'dmraid' ; then
2042     local ACTION="$(getbootparam 'dmraid' 2>>$DEBUG)"
2043     if [ "$ACTION" = "off" ] ; then
2044       # Deactivates all active software RAID sets:
2045       einfo "Deactivating present dmraid sets (as requested via dmraid=off):"
2046       dmraid_wrapper -an
2047     else
2048       # Activate all software RAID sets discovered:
2049       einfo "Activating present dmraid sets (as requested via dmraid):"
2050       dmraid_wrapper -ay
2051     fi
2052
2053     return
2054   fi
2055
2056   # by default (no special bootoptions) discover all software RAID devices:
2057   einfo "Searching for any present dmraid sets:"
2058   dmraid_wrapper -r
2059 }
2060 # }}}
2061
2062 # {{{ LVM (Logical Volumes)
2063 config_lvm(){
2064   [ -n "$INSTALLED" ] && return 0
2065
2066   if checkbootparam 'nolvm' ; then
2067      ewarn "Skipping LVM code as requested on boot commandline." ; eend 0
2068   else
2069     # Debian etch provides /etc/init.d/lvm only, newer suites provide /etc/init.d/lvm2
2070     if ! [ -x /sbin/lvm -a -x /sbin/lvdisplay ] || ! [ -x /etc/init.d/lvm2 -o -x /etc/init.d/lvm ] ; then
2071        eerror "LVM not available, can not execute it." ; eend 1
2072     else
2073        if lvdisplay 2>&1 | grep -v 'No volume groups found' >/dev/null 2>&1 ; then
2074           einfo "You seem to have logical volumes (LVM) on your system."
2075           eindent
2076           einfo "Just run 'Start lvm2' to activate them or boot using 'lvm' as bootoption for autostart."
2077           eend 0
2078           if checkbootparam 'lvm' ; then
2079              einfo "Bootoption LVM found. Searching for logical volumes:"
2080              /etc/init.d/lvm2 start ; eend $?
2081           fi
2082           eoutdent
2083        fi
2084     fi # check for lvm binary
2085   fi # check for bootoption nolvm
2086 }
2087 # }}}
2088
2089 # {{{ debnet: setup network based on an existing one found on a partition
2090 config_debnet(){
2091 if checkbootparam 'debnet' ; then
2092  einfo "Bootoption 'debnet' found. Searching for Debian network configuration: "
2093  /usr/sbin/debnet
2094 fi
2095 }
2096 # }}}
2097
2098 # {{{ disable console blanking
2099 config_blanking(){
2100 if checkbootparam 'noblank' ; then
2101   einfo "Bootoption noblank found. Disabling monitor blanking."
2102   setterm -blank 0 ; eend $?
2103 fi
2104 }
2105 # }}}
2106
2107 # {{{ tohd= bootoption
2108 config_tohd()
2109 {
2110   if checkbootparam 'tohd' ; then
2111      local TARGET="$(getbootparam 'tohd' 2>>$DEBUG)"
2112      if [ -z "$TARGET" ] ; then
2113         eerror "Error: tohd specified without any partition, can not continue." ; eend 1
2114         eerror "Please use something like tohd=/dev/sda9." ; eend 1
2115         return 1
2116      fi
2117
2118      if ! [ -b "$TARGET" ] ; then
2119         eerror "Error: $TARGET is not a valid block device, sorry." ; eend 1
2120         return 1
2121      fi
2122
2123      if grep -q $TARGET /proc/mounts ; then
2124         eerror "$TARGET already mounted, skipping execution of tohd therefore."
2125         eend 1
2126         return 1
2127      fi
2128
2129      local MOUNTDIR=$(mktemp -d)
2130
2131      if mount -o rw "$TARGET" "$MOUNTDIR" ; then
2132         einfo "Copyring live system to $TARGET - this might take a while"
2133         rsync -a --progress ${LIVECD_PATH}/live $MOUNTDIR
2134         sync
2135         umount "$MOUNTDIR"
2136         eend $?
2137         einfo "Booting with \"grml bootfrom=$TARGET\" should work now." ; eend 0
2138      else
2139         eerror "Error when trying to mount $TARGET, sorry."; eend 1
2140         return 1
2141      fi
2142
2143      rmdir "$MOUNTDIR"
2144   fi
2145 }
2146 # }}}
2147
2148 # {{{ debootstrap: automatic installation
2149 config_debootstrap(){
2150
2151 if checkbootparam "BOOT_IMAGE=debian2hd" || checkbootparam "debian2hd" ; then
2152
2153 einfo "Bootoption debian2hd found. Setting up environment for automatic installation via grml-debootstrap." ; eend 0
2154
2155 if ! [ -x /usr/sbin/grml-debootstrap ] ; then
2156    eindent
2157    eerror "Bootoption debian2hd found, but grml-debootstrap is not available." ; eend 1
2158    eoutdent
2159    exit 1
2160 fi
2161
2162 if checkbootparam 'target' ; then
2163   TARGET=''
2164   TARGET="$(getbootparam 'target' 2>>$DEBUG)"
2165   # notice: the following checks whether the given partition is available, if not the skip
2166   # execution of grml-debootstrap as it might result in data loss...
2167   if ! [ -r "$TARGET" ] ; then
2168      eerror "Target $TARGET does not exist. Skipping execution of grml-debootstrap therefore." ; eend 1
2169   fi
2170 else
2171   eindent
2172   eerror "No bootoption named target found, can not continue execution of grml-debootstrap." ; eend 1
2173   eoutdent
2174   exit 1
2175 fi
2176
2177 if checkbootparam 'grub' ; then
2178   GRUB=''
2179   GRUB="$(getbootparam 'grub' 2>>$DEBUG)"
2180 fi
2181
2182 if checkbootparam 'groot' ; then
2183   GROOT=''
2184   GROOT="$(getbootparam 'groot' 2>>$DEBUG)"
2185 fi
2186
2187 if checkbootparam 'release' ; then
2188   RELEASE=''
2189   RELEASE="$(getbootparam 'release' 2>>$DEBUG)"
2190 fi
2191
2192 if checkbootparam 'mirror' ; then
2193   MIRROR=''
2194   MIRROR="$(getbootparam 'mirror' 2>>$DEBUG)"
2195 fi
2196
2197 if checkbootparam 'boot_append' ; then
2198   BOOT_APPEND=''
2199   BOOT_APPEND="$(getbootparam 'boot_append' 2>>$DEBUG)"
2200 fi
2201
2202 if checkbootparam 'password' ; then
2203   PASSWORD=''
2204   PASSWORD="$(getbootparam 'password' 2>>$DEBUG)"
2205 fi
2206
2207 # now check which options are available
2208 if [ -n "TARGET" ] ; then
2209    TARGETCMD="--target $TARGET"
2210 else
2211    TARGETCMD=''
2212    eindent
2213    eerror "Target not set via bootoption. Skipping execution of grml-debootstrap therefore."; eend 1
2214    eoutdent
2215    exit 1
2216 fi
2217 [ -n "$GRUB" ]     && GRUBCMD="--grub $GRUB"               || GRUBCMD=''
2218 [ -n "$GROOT" ]    && GROOTCMD="--groot $GROOT"            || GROOTCMD=''
2219 [ -n "$RELEASE" ]  && RELEASECMD="--release $RELEASE"      || RELEASECMD=''
2220 [ -n "$MIRROR" ]   && MIRRORCMD="--mirror $MIRROR"         || MIRRORCMD=''
2221 [ -n "$PASSWORD" ] && PASSWORDCMD="--password $PASSWORD"   || PASSWORDCMD=''
2222 [ -n "$BOOT_APPEND" ] && BOOT_APPEND="--boot_append $BOOT_APPEND" || BOOT_APPEND=''
2223
2224 # and finally write script and execute it
2225 cat>|/usr/bin/grml-debootstrap_noninteractive<<EOF
2226 #!/bin/sh
2227 AUTOINSTALL='yes' grml-debootstrap $TARGETCMD $GRUBCMD $GROOTCMD $RELEASECMD $MIRRORCMD $PASSWORDCMD $BOOT_APPEND
2228 EOF
2229
2230 chmod 750  /usr/bin/grml-debootstrap_noninteractive
2231
2232 screen /usr/bin/grml-debootstrap_noninteractive
2233 einfo "Invoking a shell, just exit to continue booting..."
2234 /bin/zsh
2235
2236 fi # checkbootparam "BOOT_IMAGE=debian2hd
2237 }
2238 # }}}
2239
2240 config_virtualbox_shared_folders() {
2241 if $VIRTUALBOX ; then
2242   einfo "VirtualBox detected, trying to set up Shared Folders."
2243   if ! modinfo vboxsf &>/dev/null ; then
2244     ewarn "vboxsf driver not present, not setting up VirtualBox Shared Folders."
2245     eend 0
2246   elif ! [ -x /usr/sbin/VBoxService ] ; then
2247     ewarn "virtualbox-guest-utils not installed, not setting up VirtualBox Shared Folders."
2248     eend 0
2249   else
2250     eindent
2251
2252       einfo "Loading vboxsf driver."
2253       lsmod | grep -q vboxsf || modprobe vboxsf
2254       eend $?
2255
2256       einfo "Adjusting /dev/vboxguest."
2257       chown root:vboxsf /dev/vboxguest
2258       chmod 660 /dev/vboxguest
2259       eend $?
2260
2261       config_userfstab
2262
2263       einfo "Adding $fstabuser to group vboxsf."
2264       adduser grml vboxsf &>/dev/null
2265       eend $?
2266
2267       einfo "Starting VBoxService."
2268       VBoxService >/dev/null &
2269       eend $?
2270
2271     eoutdent
2272   fi
2273 fi
2274 }
2275
2276 # {{{ Support customization
2277 config_distri(){
2278 if checkbootparam 'distri'; then
2279   DISTRI="$(getbootparam 'distri' 2>>$DEBUG)"
2280   if [ -r "${LIVECD_PATH}"/desktop/"$DISTRI".jpg ] ; then
2281      [ -n "$BOOTDEBUG" ] && einfo "Debug: bootoption distri found and file ${LIVECD_PATH}/desktop/${DISTRI} present" && eend 0
2282      # make sure the desktop.jpg file is not a symlink, so copying does not file then
2283      [ -L /usr/share/grml/desktop.jpg ] && rm /usr/share/grml/desktop.jpg
2284      cp "${LIVECD_PATH}"/desktop/"$DISTRI".jpg /usr/share/grml/desktop.jpg
2285   fi
2286 fi
2287 }
2288 # }}}
2289
2290 ## END OF FILE #################################################################
2291 # vim:foldmethod=marker expandtab ai ft=zsh shiftwidth=2