Consequently use eerror for displaying error messages.
[grml-debootstrap.git] / grml-debootstrap
1 #!/bin/bash
2 # Filename:      grml-debootstrap
3 # Purpose:       wrapper around debootstrap for installing plain Debian via Grml
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 # http://www.debian.org/releases/stable/i386/index.html.en
9
10 set -e # exit on any error
11
12 # variables {{{
13 PN="$(basename $0)"
14 VERSION="$(dpkg --list $PN 2>/dev/null| awk '/^i/ {print $3}')"
15 VERSION="${VERSION:-unknown}"
16 MNTPOINT="/mnt/debootstrap.$$"
17
18 # defaults
19 VMSIZE="2G"
20 FORCE=''
21
22 # inside the chroot system locales might not be available, so use minimum:
23 export LANG=C
24 export LC_ALL=C
25
26 # make sure interactive mode is only executed when
27 # using an empty configuration file or option --interactive
28 INTERACTIVE=''
29 # }}}
30
31 # source core functions {{{
32 . /etc/grml/lsb-functions
33 . /etc/grml/script-functions
34 # }}}
35
36 # help text {{{
37 usage() {
38   echo "$PN - wrapper around debootstrap for installing Debian
39
40 Usage: $PN [options]
41
42 Bootstrap options:
43
44   -m, --mirror <URL>     Mirror which should be used for apt-get/aptitude.
45   -i, --iso <mnt>        Mountpoint where a Debian ISO is mounted to, for use
46                          instead of fetching packages from a mirror.
47   -r, --release <name>   Release of new Debian system (default: squeeze).
48   -t, --target <target>  Target partition (/dev/...) or directory where the
49                          system should be installed to.
50   -p, --mntpoint <mnt>   Mountpoint used for mounting the target system,
51                          has no effect if -t is given and represents a directory.
52       --debopt <params>  Extra parameters passed to the debootstrap command.
53       --interactive      Use interactive mode (frontend).
54       --nodebootstrap    Skip debootstrap, only do configuration to the target.
55       --grub <device>    Target for grub installation. Usage example: /dev/sda
56       --arch <arch>      Architecture to use. Currently only i386 is supported.
57       --filesystem <fs>  Filesystem that should be used when target is a partition
58                          or Virtual Machine (see --vmfile).
59       --insecure         Do not download and check Release file signatures.
60       --force            Do not prompt for user acknowledgement.
61
62 Options for Virtual Machine deployment:
63
64       --vmfile           Set up a Virtual Machine instead of installing to
65                          a partition or directory, to be combined with --target,
66                          like: --vmfile --target /mnt/sda1/qemu.img
67       --vmsize <size>    Use specified size for size of VM file (default: 2G).
68                          Syntax as supported by qemu-img, like: --vmsize 3G
69
70 Configuration options:
71
72   -c, --config <file>      Use specified configuration file, defaults to
73                              /etc/debootstrap/config
74   -d, --confdir <path>     Place of config files for debootstrap, defaults
75                              to /etc/debootstrap
76       --packages <file>    Install packages defined in specified list file.
77       --nopackages         Skip installation of packages defined in
78                              /etc/debootstrap/packages
79       --debconf <file>     Pre-seed packages using specified pre-seed db file.
80       --keep_src_list      Do not overwrite user provided apt sources.list.
81       --hostname <name>    Hostname of Debian system.
82       --password <pwd>     Use specified password as password for user root.
83       --bootappend <line>  Add specified appendline to kernel whilst booting.
84       --chroot-scripts <d> Execute chroot scripts from specified directory.
85       --pre-scripts <dir>  Execute scripts from specified directory (before chroot-scripts).
86       --scripts <dir>      Execute scripts from specified directory (after chroot-scripts).
87
88 Other options:
89
90   -v, --verbose            Increase verbosity.
91   -h, --help               Print this usage information and exit.
92   -V, --version            Show summary of options and exit.
93
94 Usage examples can be found in the grml-debootstrap manpage.
95 Send bugreports to the grml-team: bugs (at) grml.org || http://grml.org/bugs/
96 "
97 }
98
99 if [ "$1" = '-h' ] || [ "$1" = '-help' ] || [ "$1" = "--help" ] ; then
100    usage
101    echo 'Please notice that this script requires root permissions!'
102    exit 0
103 fi
104 # }}}
105
106 # make sure we have what we need {{{
107 check4progs debootstrap dialog || exit 1
108 # }}}
109
110 # source main configuration file {{{
111 if [ -r /etc/debootstrap/config ] ; then
112   . /etc/debootstrap/config
113 fi
114 # }}}
115
116 # cmdline handling {{{
117 # source external command line parameter-processing script
118 if [ -r ./cmdlineopts.clp ] ; then
119    . ./cmdlineopts.clp
120 elif [ -r /usr/share/grml-debootstrap/functions/cmdlineopts.clp ] ; then
121    . /usr/share/grml-debootstrap/functions/cmdlineopts.clp
122 else
123    eerror "Error: cmdline function file not found, exiting."
124    eend 1
125    exit 1
126 fi
127
128 # == business-logic of command line parameter-processing
129
130 # source configuration file in <confdir> if supplied. {{{
131 [ "$_opt_confdir" ] && {
132   CONFFILES=$_opt_confdir
133   einfo "Using config files under $CONFFILES/."
134   if ! [ -r "$CONFFILES/config" ] ; then
135     eerror "Error: config file $CONFFILES/config not found."; eend 1; exit 1
136   fi
137   if ! . "$CONFFILES/config" ; then
138     eerror "Error reading config file $CONFFILES/config" ; eend 1 ; exit 1
139   fi
140   # restore the command line parameter value
141   CONFFILES=$_opt_confdir
142 }
143 # }}}
144
145 [ "$_opt_mirror" ]              && MIRROR=$_opt_mirror
146 [ "$_opt_iso" ]                 && ISO=$_opt_iso
147 [ "$_opt_release" ]             && RELEASE=$_opt_release
148 [ "$_opt_target" ]              && TARGET=$_opt_target
149 [ "$_opt_vmfile" ]              && VIRTUAL=1
150 [ "$_opt_vmsize" ]              && VMSIZE=$_opt_vmsize
151 [ "$_opt_mntpoint" ]            && MNTPOINT=$_opt_mntpoint
152 [ "$_opt_debopt" ]              && DEBOOTSTRAP_OPT=$_opt_debopt
153 [ "$_opt_interactive" ]         && INTERACTIVE=1
154 [ "$_opt_config" ]              && CONFIGFILE=$_opt_config
155 [ "$_opt_filesystem" ]          && MKFS="mkfs.$_opt_filesystem"
156 [ "$_opt_packages_set" ]        && PACKAGES='yes'
157 [ "$_opt_nopackages" ]          && PACKAGES=''
158 [ "$_opt_debconf_set" ]         && DEBCONF='yes'
159 [ "$_opt_scripts_set" ]         && SCRIPTS='yes'
160 [ "$_opt_pre_scripts_set" ]     && PRE_SCRIPTS='yes'
161 [ "$_opt_chroot_scripts_set" ]  && CHROOT_SCRIPTS='yes'
162 [ "$_opt_keep_src_list" ]       && KEEP_SRC_LIST='yes'
163 [ "$_opt_hostname" ]            && HOSTNAME=$_opt_hostname
164 [ "$_opt_password" ]            && ROOTPASSWORD=$_opt_password
165 [ "$_opt_bootappend" ]          && BOOT_APPEND=$_opt_bootappend
166 [ "$_opt_grub" ]                && GRUB=$_opt_grub
167 [ "$_opt_arch" ]                && ARCH=$_opt_arch
168 [ "$_opt_insecure" ]            && SECURE='false'
169 [ "$_opt_force" ]               && FORCE=$_opt_force
170 [ "$_opt_verbose" ]             && VERBOSE="-v"
171
172 [ "$_opt_help" ] && {
173   usage ; eend 0
174   eend 0
175   exit 0
176 }
177
178 [ "$_opt_version" ] && {
179   einfo "$PN - version $VERSION"
180   einfo "Send bug reports to bugs@grml.org or http://grml.org/bugs/"
181   eend 0
182   exit 0
183 }
184 # }}}
185
186 # check for root permissions {{{
187 if ! check4root ; then
188    echo "For usage instructions please execute '$PN --help'."
189    exit 1
190 fi
191 # }}}
192
193 # make sure we have what we need {{{
194 if [ -n "$VIRTUAL" ] ; then
195   check4progs kpartx mksh qemu-img || exit 1
196 fi
197 # }}}
198
199 # source specified configuration file {{{
200 if [ -n "$CONFIGFILE" ] ; then
201    einfo "Reading specified config file $CONFIGFILE."
202    if ! . "$CONFIGFILE" ; then
203       eerror "Error reading config file $CONFIGFILE" ; eend 1 ; exit 1
204    fi
205 fi
206 # }}}
207
208 # backwards compability checks {{{
209 if [ -n "$GROOT" ] ; then
210    eerror "Error: you seem to have \$GROOT configured."
211    eerror "This variable is no longer supported, please visit the"
212    eerror "grml-debootstrap documentation for details."
213    eend 1
214    exit 1
215 fi
216
217 if echo "$GRUB" | grep -q '^hd' ; then
218    eerror "Error: this syntax for the grub configuration variable is no longer supported."
219    eerror "Please do not use hd... any longer but /dev/sdX instead."
220    eend 1
221    exit 1
222 fi
223 # }}}
224
225 # welcome screen {{{
226 welcome_dialog()
227 {
228    dialog --title "$PN" --yesno "Welcome to the interactive configuration of ${PN}.
229 Do you want to continue installing Debian using this frontend?" 0 0
230 }
231 # }}}
232
233 # ask for target {{{
234 prompt_for_target()
235 {
236   AVAILABLE_PARTITIONS=$(LANG=C fdisk -l 2>/dev/null | \
237                sed 's/*//' | \
238                grep -v 'Extended$' | \
239                gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}'; ls /dev/md* 2>/dev/null || true);
240
241   if [ -z "$AVAILABLE_PARTITIONS" ] ; then
242      dialog --title "$PN" --trim \
243      --msgbox "Sorry, no partitions found. Please configure your
244      harddisks (see /proc/partitions) using a tool like fdisk,
245      cfdisk, gpart, gparted,..." 0 0
246      exit 0
247   fi
248
249   PARTITION_LIST=$(for i in $(echo $AVAILABLE_PARTITIONS) ; do
250                        echo "$i $(blkid -s TYPE -o value $i 2>/dev/null || echo [no_filesystem_yet])"
251                    done)
252
253   TARGET=$(dialog --title "$PN" --single-quoted --stdout \
254          --menu "Please select the target partition:" 0 0 0 \
255          $PARTITION_LIST)
256 }
257 # }}}
258
259 # ask for bootmanager {{{
260 prompt_for_bootmanager()
261 {
262   ADDITIONAL_PARAMS=""
263
264   if echo "$TARGET" | grep -q "/dev/md" ; then
265      MBRPART="all disks of Software RAID $TARGET"
266   else
267      # figure out whole disk device
268      found=
269      for device in /dev/disk/by-id/*
270      do
271         [ $(readlink -f $device) = ${TARGET} ] || continue
272         found=1
273         break
274      done
275      [ -n "$found" ] && MBRDISK=$(echo ${device}|sed -e 's/-part[0-9][0-9]*$//')
276      if [ -e "$MBRDISK" ]; then
277         MBRDISK=$(readlink -f $MBRDISK)
278      else
279         # fall back to old behaviour
280         MBRDISK=$(echo ${TARGET} | sed -e 's/[0-9][0-9]*$//')
281      fi
282
283      MBRPART="MBR of $MBRDISK"
284   fi
285
286   for device in cciss/c0d0 sda hda; do
287     if [ /dev/$device != ${MBRDISK} ]; then
288       grep -q $device /proc/partitions && \
289       ADDITIONAL_PARAMS="$ADDITIONAL_PARAMS:$device:install bootmanager grub into MBR of /dev/$device"
290     fi
291   done
292   ADDITIONAL_PARAMS=${ADDITIONAL_PARAMS#:}
293
294   OIFS="$IFS"; IFS=:
295
296   GETMBR=$(dialog --stdout --title "$PN" --default-item mbr \
297           --menu "Where do you want to install the bootmanager grub?" 0 0 0 \
298             mbr       "install bootmanager into $MBRPART" \
299             nowhere   "do not install bootmanager at all" \
300           ${ADDITIONAL_PARAMS})
301   [ $? -eq 0 ] || bailout 3
302   IFS="$OIFS"
303
304   case "$GETMBR" in
305     mbr)
306       # /dev/md0: has to be installed in MBR of /dev/md0 and not in /dev/md:
307       if echo "$TARGET" | grep -q "/dev/md" ; then
308          # using sw-raid:
309          if [ -n "$SELECTED_PARTITIONS" ] ; then
310             GRUB=$(echo ${SELECTED_PARTITIONS} | awk '{print $1}') # use first disk only
311          else
312             GRUB="$TARGET"
313          fi
314       else
315         GRUB="$MBRDISK"
316       fi
317       ;;
318     hda)
319       GRUB="/dev/hda"
320       ;;
321     sda)
322       GRUB="/dev/sda"
323       ;;
324     nowhere)
325       GRUB=''
326       ;;
327   esac
328 }
329 # }}}
330
331 # ask for Debian release {{{
332 prompt_for_release()
333 {
334   [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='squeeze'
335   RELEASE="$(dialog --stdout --title "${PN}" --default-item $DEFAULT_RELEASE --menu \
336             "Please enter the Debian release you would like to use for installation:" \
337             0 50 4 \
338             lenny    Debian/old-stable \
339             squeeze  Debian/stable \
340             wheezy   Debian/testing \
341             sid      Debian/unstable)"
342 }
343 # }}}
344
345 # ask for hostname {{{
346 prompt_for_hostname()
347 {
348   HOSTNAME="$(dialog --stdout --title "${PN}" --inputbox \
349             "Please enter the hostname you would like to use for installation:" \
350             0 0 $HOSTNAME)"
351 }
352 # }}}
353
354 # ask for password {{{
355 prompt_for_password()
356 {
357      ROOTPW1='PW1'
358      ROOTPW2='PW2'
359      while [ "$ROOTPW1" != "$ROOTPW2" ]; do
360        ROOTPW1=$(dialog --insecure --stdout --title "${PN}" --passwordbox \
361        "Please enter the password for the root account:" 10 60)
362        ROOTPW2=$(dialog --insecure --stdout --title "${PN}" --passwordbox \
363        "Please enter the password for the root account again for \
364        confirmation:" 10 60)
365
366        if [ "$ROOTPW1" != "$ROOTPW2" ]; then
367          $(dialog --stdout --title "${PN}" --ok-label \
368          "Retry" --msgbox "Passwords do not match!" 10 60)
369        fi
370      done
371      ROOTPASSWORD="$ROOTPW1"
372 }
373 # }}}
374
375 # ask for Debian mirror {{{
376 prompt_for_mirror()
377 {
378   [ -n "$ISO" ] && DEFAULT_MIRROR='local' || DEFAULT_MIRROR='net'
379
380   CHOOSE_MIRROR=$(dialog --stdout --title "$PN" --default-item $DEFAULT_MIRROR \
381           --menu "Where do you want to install from?" 0 0 0 \
382             net   "install via network (downloading from mirror)" \
383             local "install from local directory/mirror"
384           )
385
386   if [ "$CHOOSE_MIRROR" = 'net' ] ; then
387      [ -n "$MIRROR" ] || MIRROR='http://cdn.debian.net/debian'
388      MIRROR="$(dialog --stdout --title "${PN}" --inputbox \
389                "Please enter Debian mirror you would like to use for installing packages." \
390                0 0 $MIRROR)"
391   else # CHOOSE_MIRROR == local
392      [ -n "$ISO" ] || ISO='/mnt/mirror'
393      ISO="$(dialog --stdout --title "${PN}" --inputbox \
394                "Please enter directory name you would like to use for installing packages." \
395                0 0 $ISO)"
396   fi
397 }
398 # }}}
399
400 # software raid setup {{{
401 config_swraid_setup()
402 {
403 TMPFILE=$(mktemp)
404
405 # Currently we support only raid1:
406 RAIDLEVEL='raid1'
407
408 #RAIDLEVEL=$(dialog --stdout --title "$PN" --default-item raid1 \
409 #                   --menu "Which RAID level do you want to use?" 0 0 0 \
410 #                     raid1 "Software RAID level 1" \
411 #                     raid5 "Software RAID level 5")
412 #[ $? -eq 0 ] || bailout 20
413
414 MD_LIST=$(for i in $(seq 0 9) ; do
415             awk '{print $4}' /proc/partitions | grep -q md$i || \
416             echo "/dev/md$i /dev/md$i"
417           done)
418
419 TARGET=$(dialog --stdout --title "$PN" --default-item /dev/md0 \
420 --menu "Which device do you want to use for ${RAIDLEVEL}?
421
422 Notice: activated devices will not be listed for security reasons. Anyway, please make sure the selected device is not in use already!" 0 0 0 \
423 $MD_LIST)
424 [ $? -eq 0 ] || bailout 20
425
426 AVAILABLE_PARTITIONS=$(LANG=C fdisk -l 2>/dev/null | \
427              sed 's/*//' | \
428              grep -v 'Extended$' | \
429              gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}')
430 [ -n "$AVAILABLE_PARTITIONS" ] || echo "FIXME: no partitions available?"
431 PARTITION_LIST=$(for i in $(echo $AVAILABLE_PARTITIONS) ; do
432                      echo "$i $(blkid -s TYPE -o value $i 2>/dev/null || echo [no_filesystem_yet]) off"
433                  done)
434
435 dialog --title "$PN" --separate-output \
436        --checklist "Please select the partitions you would like to use for your $RAIDLEVEL on ${TARGET}:" 0 0 0 \
437        $PARTITION_LIST 2>$TMPFILE
438 RETVAL=$?
439 SELECTED_PARTITIONS="$(cat $TMPFILE)"
440
441 NUM_PARTITIONS=0
442 for i in $(cat $TMPFILE) ; do
443    NUM_PARTITIONS=$((${NUM_PARTITIONS}+1))
444 done
445
446 # force metadata version 0.90 for lenny so old grub can boot from this array.
447 METADATA_VERSION=""
448 if [ $RELEASE = "lenny" ]; then
449    METADATA_VERSION="-e0"
450 fi
451
452 ERRORFILE=$(mktemp)
453 set +e
454 # TODO: better error handling?
455 yes | mdadm --create "${TARGET}" --level="${RAIDLEVEL}" \
456       --raid-devices="${NUM_PARTITIONS}" ${METADATA_VERSION} ${SELECTED_PARTITIONS} >/dev/null 2>$ERRORFILE
457 RC=$?
458 set -e
459
460 if [ "$RC" = 0 ] ; then
461    dialog --title "$PN" --msgbox \
462    "Creating $TARGET was successful." 0 0
463    rm -f "$TMPFILE" "$ERRORFILE"
464 else
465    dialog --title "$PN" --msgbox \
466    "There was an error setting up $TARGET:
467
468 $(cat $ERRORFILE)
469
470 Exiting." 0 0
471    rm -f "$TMPFILE" "$ERRORFILE"
472    exit 1
473 fi
474
475 }
476
477 prompt_for_swraid()
478 {
479 if dialog --stdout --title "$PN" \
480           --defaultno --yesno "Do you want to configure Software RAID?
481
482 Please notice that only RAID level 1 is supported by ${PN} currently. Configuration will take place using mdadm." 0 0 ; then
483   config_swraid_setup
484 fi
485 }
486 # }}}
487
488 # user should recheck his configuration {{{
489 # support full automatic installation:
490 checkforrun() {
491    dialog --timeout 10 --title "$PN" \
492           --yesno "Do you want to stop at this stage?
493
494 Notice: you are running ${PN} in non-interactive mode.
495 ${PN} will install Debian ${RELEASE} on ${TARGET}.
496 Last chance to quit. Timeout of 10 seconds running....
497
498 Do you want to stop now?" 0 0 2>/dev/null
499 }
500
501 # make sure the user is aware of the used configuration {{{
502 checkconfiguration()
503 {
504 if [ -n "$AUTOINSTALL" ] ; then
505    if checkforrun ; then
506       eerror "Exiting as requested" ; eend 0
507       exit 1
508    fi
509 elif [ -n "$INTERACTIVE" ] ; then
510
511    INFOTEXT="Please recheck configuration before execution:
512    "
513    [ -n "$TARGET" ]  && INFOTEXT="$INFOTEXT
514    Target:          $TARGET"
515    [ -n "$GRUB" ]    && INFOTEXT="$INFOTEXT
516    Install grub:    $GRUB"
517    [ -n "$RELEASE" ] && INFOTEXT="$INFOTEXT
518    Using release:   $RELEASE"
519    [ -n "$HOSTNAME" ] && INFOTEXT="$INFOTEXT
520    Using hostname   $HOSTNAME"
521    [ -n "$MIRROR" ]  && INFOTEXT="$INFOTEXT
522    Using mirror:    $MIRROR"
523    [ -n "$ISO" ]  && INFOTEXT="$INFOTEXT
524    Using ISO:       $ISO"
525
526    INFOTEXT="$INFOTEXT
527
528 Is this ok for you? Notice: selecting 'No' will exit ${PN}."
529
530    dialog --title "$PN" --no-collapse \
531           --yesno "$INFOTEXT" 0 0
532
533 else # if not running automatic installation display configuration and prompt for execution:
534    einfo "$PN - Please recheck configuration before execution:"
535    echo
536    echo "   Target:          $TARGET"
537
538    # do not display if MNTPOINT is the default one
539    case "$MNTPOINT" in /mnt/debootstrap*) ;; *) echo "   Mount point:     $MNTPOINT" ;; esac
540
541    if [ -n "$VIRTUAL" ] ; then
542       echo "   Install grub:    yes"
543    else
544      [ -n "$GRUB" ]     && echo "   Install grub:    $GRUB" || echo "   Install grub:    no"
545    fi
546
547    [ -n "$RELEASE" ]  && echo "   Using release:   $RELEASE"
548    [ -n "$MIRROR" ]   && echo "   Using mirror:    $MIRROR"
549    [ -n "$HOSTNAME" ] && echo "   Using hostname:  $HOSTNAME"
550    [ -n "$ISO" ]      && echo "   Using ISO:       $ISO"
551    if [ -n "$VIRTUAL" ] ; then
552       echo "   Deploying as Virtual Machine."
553       [ -n "$VMSIZE" ] && echo "   Using Virtual Disk file with size of ${VMSIZE}."
554    fi
555
556    echo
557    echo "   Important! Continuing will delete all data from ${TARGET}!"
558
559    if [ -n "$FORCE" ] ; then
560      einfo "Skip user acknowledgement as requested via --force option."
561    else
562      echo
563      einfon "Is this ok for you? [y/N] "
564      read a
565      if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
566         eerror "Exiting as requested." ; eend 1
567         exit 1
568      fi
569    fi
570 fi
571 }
572 # }}}
573
574 # interactive mode {{{
575 interactive_mode()
576 {
577   welcome_dialog
578
579   prompt_for_release
580
581   prompt_for_swraid
582
583   prompt_for_target
584
585   prompt_for_bootmanager
586
587   prompt_for_hostname
588
589   prompt_for_password
590
591   prompt_for_mirror
592 }
593
594 # run interactive mode if we didn't get the according configuration yet
595 if [ -z "$TARGET" -o -n "$INTERACTIVE" ] ; then
596    # only target might be unset, so make sure the INTERACTIVE flag is set as well
597    INTERACTIVE=1
598    interactive_mode
599 fi
600 # }}}
601
602 checkconfiguration
603
604 # finally make sure at least $TARGET is set [the partition for the new system] {{{
605 if [ -n "$TARGET" ] ; then
606    SHORT_TARGET="${TARGET##*/}"
607 else
608    eerror "Please adjust $CONFFILES/config or..."
609    eerror "... use the interactive version for configuration before running ${0}" ; eend 1
610    exit 1
611 fi
612 # }}}
613
614 # stages setup {{{
615 if [ -z "$STAGES" ] ; then
616    STAGES="/var/cache/grml-debootstrap/stages_${SHORT_TARGET}"
617    [ -d "$STAGES" ] || mkdir -p "$STAGES"
618 fi
619
620 if [ -r "$STAGES"/grml-debootstrap ] ; then
621    if grep -q done $STAGES/grml-debootstrap ; then
622       eerror "Error: grml-debootstrap has been executed already, won't continue therefore."
623       eerror "If you want to re-execute grml-debootstrap just manually remove ${STAGES}" ; eend 1
624    fi
625 fi
626 # }}}
627
628 # partition handling {{{
629 PARTITION=''
630 DIRECTORY=''
631
632 set_target_directory(){
633     # assume we are installing into a directory, don't run mkfs and grub related stuff therefore
634     DIRECTORY=1
635     MNTPOINT="$TARGET"
636     MKFS=''
637     TUNE2FS=''
638     FSCK=''
639     GRUB=''
640     # make sure we normalise the path to an absolute directory name so something like:
641     #  mkdir -p foo/a bar/a; (cd foo; grml-debootstrap -t a)&; (cd bar; grml-debootstrap -t a)&; wait
642     # works
643     TARGET="$(readlink -f $TARGET)"
644 }
645
646 if [ -b "$TARGET" ] || [ -n "$VIRTUAL" ] ; then
647     PARTITION=1
648 else
649     set_target_directory
650 fi
651 # }}}
652
653 # architecture setup {{{
654 if [ -n "$ARCH" ] ; then
655    ARCHCMD="--arch $ARCH"
656    ARCHINFO=" (${ARCH})"
657 else
658    ARCH="$(dpkg --print-architecture)"
659    ARCHCMD="--arch $ARCH"
660    ARCHINFO=" (${ARCH})"
661 fi
662 # }}}
663
664 # keyring setupt {{{
665 KEYRING=""
666 if [ "$SECURE" = 'yes' ] ; then
667    if [ -e '/etc/apt/trusted.gpg' ] ; then
668       KEYRING="--keyring /etc/apt/trusted.gpg"
669    else
670       eerror "Could not find /etc/apt/trusted.gpg."
671    fi
672 else
673    ewarn "Not checking Release signatures!"
674 fi
675 # }}}
676
677 # make sure we have the right syntax when using an iso image {{{
678 if [ -n "$ISO" ] ; then
679    case $ISO in
680       file*) # do nothing
681       ;;
682       *)
683       ISO=file:$1
684       ;;
685    esac
686 fi
687 ISODIR=${ISO##file:}
688 ISODIR=${ISODIR%%/}
689 # }}}
690
691 # helper functions {{{
692 # we want to exit smoothly and clean:
693 bailout(){
694   # make sure $TARGET is not mounted when exiting grml-debootstrap
695   if [ -n "$MNTPOINT" ] ; then
696      if grep -q $MNTPOINT /proc/mounts ; then
697         # make sure nothing is left inside chroot so we can unmount it
698         [ -x "$MNTPOINT"/etc/init.d/ssh   ] && "$MNTPOINT"/etc/init.d/ssh stop
699         [ -x "$MNTPOINT"/etc/init.d/mdadm ] && "$MNTPOINT"/etc/init.d/mdadm stop
700         # ugly, but make sure we really don't leave anything (/proc /proc is intended)
701         for ARG in /sys /proc /proc ; do
702           [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount $ARG >/dev/null 2>&1 || true
703         done
704         umount "$MNTPOINT"/dev >/dev/null 2>&1 || true
705
706         [ -d "$MNTPOINT/$ISODIR" ] && umount "$MNTPOINT/$ISODIR" >/dev/null 2>&1 || true
707
708         if [ -n "$DIRECTORY" ] ; then
709           einfo "Not unmounting $MNTPOINT as you requested me to install into a directory of your own choice." ; eend 0
710         else
711           einfo "Unmounting $MNTPOINT" ; umount "$MNTPOINT" ; eend $?
712         fi
713
714         if [ -n "$STAGES" ] ; then
715            echo -n "Removing stages directory ${STAGES}: "
716            rm -rf "$STAGES" && echo done
717         fi
718
719         # remove directory only if we used the default with process id inside the name
720         if echo "$MNTPOINT" | grep -q '/mnt/debootstrap\.' ; then
721            einfo "Removing directory ${MNTPOINT}" ; rmdir $MNTPOINT ; eend $?
722         fi
723      fi
724   fi
725
726   if [ -n "${ORIG_TARGET}" ] ; then
727     einfo "Removing loopback mount of file ${ORIG_TARGET}."
728     kpartx -d "${ORIG_TARGET}" ; eend $?
729   fi
730
731   [ -n "$1" ] && EXIT="$1" || EXIT="1"
732   [ -n "$3" ] && einfo "Notice: just remove $STAGES/$3 to reexecute the stage"
733
734   exit "$EXIT"
735 }
736 trap bailout HUP INT QUIT TERM
737
738 # we want to execute all the functions only once, simple check for it:
739 stage() {
740   if [ -n "$2" ] ; then
741      echo "$2" > "${STAGES}/${1}"
742      return 0
743   elif grep -q done "${STAGES}/${1}" 2>/dev/null ; then
744      ewarn "Notice: stage $1 has been executed already, skipping execution therefore." ; eend 0
745      eindent
746        ewarn "To reexecute it clean up the according directory inside $STAGES" ; eend 0
747      eoutdent
748      return 1
749   fi
750 }
751 # }}}
752
753 # create filesystem {{{
754 mkfs() {
755   if [ -n "$DIRECTORY" ] ; then
756      einfo "Running grml-debootstrap on a directory, skipping mkfs stage."
757   else
758     if grep -q "$TARGET" /proc/mounts ; then
759       eerror "$TARGET already mounted, exiting to avoid possible damage. (Manually unmount $TARGET)" ; eend 1
760       exit 1
761     fi
762
763     if [ -n "$MKFS" ] ; then
764        einfo "Running $MKFS on $TARGET"
765        $MKFS $TARGET ; RC=$?
766
767        # make sure /dev/disk/by-uuid/... is up2date, otherwise grub
768        # will fail to detect the uuid in the chroot
769        if echo "$TARGET" | grep -q "/dev/md" ; then
770          blockdev --rereadpt "${TARGET}"
771        elif ! [ -n "$VIRTUAL" ] ; then
772          blockdev --rereadpt "${TARGET%%[0-9]*}"
773        fi
774        # give the system 2 seconds, otherwise we might run into
775        # race conditions :-/
776        sleep 2
777
778        eval $(blkid -o udev $TARGET 2>/dev/null)
779        [ -n "$ID_FS_UUID" ] && TARGET_UUID="$ID_FS_UUID" || TARGET_UUID=""
780
781        eend $RC
782     fi
783
784   fi
785 }
786 # }}}
787
788 # modify filesystem settings {{{
789 tunefs() {
790   if [ -n "$TUNE2FS" ] && echo "$MKFS" | grep -q "mkfs.ext" ; then
791      einfo "Disabling automatic filesystem check on $TARGET via tune2fs"
792      $TUNE2FS $TARGET
793      eend $?
794   fi
795 }
796 # }}}
797
798 # mount the new partition or if it's a directory do nothing at all {{{
799 mount_target() {
800   if [ -n "$DIRECTORY" ] ; then
801      einfo "Running grml-debootstrap on a directory, nothing to mount."
802   else
803      if grep -q $TARGET /proc/mounts ; then
804         ewarn "$TARGET already mounted, continuing anyway." ; eend 0
805      else
806        if ! [ -d "${MNTPOINT}" ] ; then
807           [ -n "$VIRTUAL" ] || mkdir -p "${MNTPOINT}"
808        fi
809        einfo "Mounting $TARGET to $MNTPOINT"
810        mkdir -p "$MNTPOINT"
811        mount -o rw,suid,dev $TARGET $MNTPOINT
812        eend $?
813      fi
814   fi
815   if [ -n "$ISODIR" ] ; then
816      einfo "Mounting Debian image loopback to $MNTPOINT/$ISODIR."
817      mkdir -p "$MNTPOINT/$ISODIR"
818      mount --bind "$ISODIR" "$MNTPOINT/$ISODIR"
819      eend $?
820   fi
821 }
822 # }}}
823
824 # prepare VM image for usage with debootstrap {{{
825 prepare_vm() {
826   if [ -z "$VIRTUAL" ] ; then
827      return 0 # be quite by intention
828   fi
829
830   if [ -b "$TARGET" ] ; then
831      eerror "Error: specified virtual disk target ($TARGET) is an existing block device."
832      eend 1
833      exit 1
834   fi
835
836   ORIG_TARGET="$TARGET" # store for later reuse
837
838   qemu-img create -f raw "${TARGET}" "${VMSIZE}"
839   echo 4 66 | mksh /usr/share/grml-debootstrap/bootgrub.mksh -A | dd of="$TARGET" conv=notrunc
840   dd if=/dev/zero bs=1 conv=notrunc count=64 seek=446 of="$TARGET"
841   parted -s "${TARGET}" 'mkpart primary ext3 2M -1'
842
843   DEVINFO=$(kpartx -av $TARGET) # 'add map loop1p1 (253:0): 0 6289408 linear /dev/loop1 2048'
844   if [ -z "${DEVINFO}" ] ; then
845     eerror "Error setting up loopback device." ; eend 1
846     exit 1
847   fi
848
849   # hopefully this always works as expected
850   LOOP=$(echo ${DEVINFO} | sed 's/.* linear //; s/ [[:digit:]]*//') # '/dev/loop1'
851   BLOCKDEV=$(echo "${DEVINFO}" | sed -e 's/.* (\(.*:.*\)).*/\1/')   # '253:0'
852   LOOP_PART="$(echo ${DEVINFO##add map } | sed 's/ .*//')" # '/dev/loop1p1'
853   export TARGET="/dev/mapper/$LOOP_PART" # '/dev/mapper/loop1p1'
854
855   blockdev --rereadpt "${LOOP}"
856
857   if [ -z "$TARGET" ] ; then
858      eerror "Error: target could not be set to according /dev/mapper/* device." ; eend 1
859      exit 1
860   fi
861 }
862 # }}}
863
864 # make VM image bootable and unmount it {{{
865 finalize_vm() {
866   if [ -z "${VIRTUAL}" ] ; then
867      return 0
868   fi
869
870   if ! mount "${TARGET}" "${MNTPOINT}" ; then
871     eerror "Error: Mounting ${TARGET} failed, can not continue." ; eend 1
872     exit 1
873   fi
874
875   einfo "Installing Grub as bootloader."
876   mount -t proc none "${MNTPOINT}"/proc
877   mount -t sysfs none "${MNTPOINT}"/sys
878   mount --bind /dev "${MNTPOINT}"/dev
879
880   mkdir -p "${MNTPOINT}/boot/grub"
881   if ! [ -d "${MNTPOINT}"/usr/lib/grub/i386-pc/ ] ; then
882      eerror "Error: grub not installed inside Virtual Machine. Can not install bootloader." ; eend 1
883      exit 1
884   fi
885
886   cp "${MNTPOINT}"/usr/lib/grub/i386-pc/* "${MNTPOINT}/boot/grub/"
887   chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos ext2
888   dd if="${MNTPOINT}/tmp/core.img" of="${ORIG_TARGET}" conv=notrunc seek=4
889   rm -f "${MNTPOINT}/tmp/core.img"
890
891   einfo "Updating grub configuration file."
892   chroot "${MNTPOINT}" update-grub
893
894   umount "${MNTPOINT}"/proc
895   umount "${MNTPOINT}"/sys
896   umount "${MNTPOINT}"/dev
897
898   einfo "Adjusting grub.cfg for successful boot sequence."
899   # ugly but needed to boot grub acordingly
900   sed -i "s;set root=.*;set root='(hd0,msdos1)';" "${MNTPOINT}"/boot/grub/grub.cfg
901   sed -i "s; root=/dev/.*; root=/dev/sda1;" "${MNTPOINT}"/boot/grub/grub.cfg
902
903   umount "${MNTPOINT}"
904   kpartx -d "${ORIG_TARGET}" >/dev/null
905 }
906 # }}}
907
908 # install main chroot {{{
909 debootstrap_system() {
910   if [ "$_opt_nodebootstrap" ]; then
911      einfo "Skipping debootstrap as requested."
912      return
913   fi
914
915   if grep -q "$MNTPOINT" /proc/mounts || [ -n "$DIRECTORY" ] ; then
916      einfo "Running $DEBOOTSTRAP $DEBOOTSTRAP_OPT for release ${RELEASE}${ARCHINFO} using ${MIRROR}${ISO}"
917      if [ -n "$MIRROR" ] ; then
918         einfo "Executing: $DEBOOTSTRAP $ARCHCMD $KEYRING $DEBOOTSTRAP_OPT $RELEASE $MNTPOINT $MIRROR"
919         $DEBOOTSTRAP $ARCHCMD $KEYRING $DEBOOTSTRAP_OPT $RELEASE $MNTPOINT $MIRROR
920      else
921         einfo "Executing: $DEBOOTSTRAP $ARCHCMD $KEYRING $DEBOOTSTRAP_OPT $RELEASE $MNTPOINT $ISO"
922         $DEBOOTSTRAP $ARCHCMD $KEYRING $DEBOOTSTRAP_OPT $RELEASE $MNTPOINT $ISO
923      fi
924      eend $?
925   else
926      eerror "Error: $MNTPOINT not mounted, can not continue."
927      eend 1
928   fi
929 }
930 # }}}
931
932 # prepare chroot via chroot-script {{{
933 preparechroot() {
934   einfo "Preparing chroot system"
935
936   # provide variables to chroot system
937   CHROOT_VARIABLES="/var/cache/grml-debootstrap/variables_${SHORT_TARGET}"
938   touch $CHROOT_VARIABLES
939   chmod 600 $CHROOT_VARIABLES # make sure nobody except root can read it
940   echo "# Configuration of ${PN}"                              > $CHROOT_VARIABLES
941   [ -n "$ARCH" ]          && echo "ARCH=$ARCH"                 >> $CHROOT_VARIABLES
942   [ -n "$GRUB" ]          && echo "GRUB=$GRUB"                 >> $CHROOT_VARIABLES
943   [ -n "$HOSTNAME" ]      && echo "HOSTNAME=$HOSTNAME"         >> $CHROOT_VARIABLES
944   [ -n "$INSTALL_NOTES" ] && echo "INSTALL_NOTES=$INSTALL_NOTES" >> $CHROOT_VARIABLES
945   [ -n "$ISODIR" ]        && echo "ISODIR=$ISO"                >> $CHROOT_VARIABLES
946   [ -n "$ISO" ]           && echo "ISO=$ISO"                   >> $CHROOT_VARIABLES
947   [ -n "$KEEP_SRC_LIST" ] && echo "KEEP_SRC_LIST=$KEEP_SRC_LIST" >> $CHROOT_VARIABLES
948   [ -n "$MIRROR" ]        && echo "MIRROR=$MIRROR"             >> $CHROOT_VARIABLES
949   [ -n "$PACKAGES" ]      && echo "PACKAGES=$PACKAGES"         >> $CHROOT_VARIABLES
950   [ -n "$RM_APTCACHE" ]   && echo "RM_APTCACHE=$RM_APTCACHE"   >> $CHROOT_VARIABLES
951   [ -n "$ROOTPASSWORD" ]  && echo "ROOTPASSWORD=$ROOTPASSWORD" >> $CHROOT_VARIABLES
952   [ -n "$SELECTED_PARTITIONS" ] && echo "SELECTED_PARTITIONS=$SELECTED_PARTITIONS" >> $CHROOT_VARIABLES
953   [ -n "$TARGET" ]        && echo "TARGET=$TARGET"             >> $CHROOT_VARIABLES
954   [ -n "$TARGET_UUID" ]   && echo "TARGET_UUID=$TARGET_UUID"   >> $CHROOT_VARIABLES
955
956   cp $VERBOSE $CONFFILES/chroot-script $MNTPOINT/bin/chroot-script
957   chmod 755 $MNTPOINT/bin/chroot-script
958   [ -d "$MNTPOINT"/etc/debootstrap/ ] || mkdir "$MNTPOINT"/etc/debootstrap/
959
960   # make sure we have our files for later use via chroot-script
961   cp $VERBOSE $CONFFILES/config    $MNTPOINT/etc/debootstrap/
962   # make sure we adjust the configuration variables accordingly:
963   sed -i "s#RELEASE=.*#RELEASE=\"$RELEASE\"#" $MNTPOINT/etc/debootstrap/config
964   sed -i "s#TARGET=.*#TARGET=\"$TARGET\"#"    $MNTPOINT/etc/debootstrap/config
965   sed -i "s#GRUB=.*#GRUB=\"$GRUB\"#"          $MNTPOINT/etc/debootstrap/config
966
967   # install notes:
968   if [ -n "$INSTALL_NOTES" ] ; then
969      [ -r "$INSTALL_NOTES" ] && cp "$INSTALL_NOTES" $MNTPOINT/etc/debootstrap/
970   fi
971
972   # package selection:
973   cp $VERBOSE ${_opt_packages:-$CONFFILES/packages} \
974     $MNTPOINT/etc/debootstrap/packages
975
976   # debconf preseeding:
977   _opt_debconf=${_opt_debconf:-$CONFFILES/debconf-selections}
978   [ -f $_opt_debconf -a "$DEBCONF" = 'yes' ] && \
979     cp $VERBOSE $_opt_debconf $MNTPOINT/etc/debootstrap/debconf-selections
980
981   # copy scripts that should be executed inside the chroot:
982   _opt_chroot_scripts=${_opt_chroot_scripts:-$CONFFILES/chroot-scripts/}
983   [ -d $_opt_chroot_scripts -a "$CHROOT_SCRIPTS" = 'yes' ] && {
984     mkdir -p $MNTPOINT/etc/debootstrap/chroot-scripts
985     cp -a $VERBOSE $_opt_chroot_scripts/* $MNTPOINT/etc/debootstrap/chroot-scripts/
986   }
987
988   # notice: do NOT use $CHROOT_VARIABLES inside chroot but statically file instead!
989   cp $VERBOSE $CHROOT_VARIABLES  $MNTPOINT/etc/debootstrap/variables
990
991   cp $VERBOSE -a -L $CONFFILES/extrapackages/ $MNTPOINT/etc/debootstrap/
992
993   # make sure we can access network [relevant for cdebootstrap]
994   [ -f "$MNTPOINT/etc/resolv.conf" ] || cp $VERBOSE /etc/resolv.conf $MNTPOINT/etc/resolv.conf
995
996   # provide system's /etc/hosts to the target:
997   if ! [ -f "$MNTPOINT/etc/hosts" ] ; then
998      cp $VERBOSE /etc/hosts $MNTPOINT/etc/hosts
999   fi
1000
1001   # setup default locales
1002   [ -n "$LOCALES" ] && cp $VERBOSE $CONFFILES/locale.gen  $MNTPOINT/etc/locale.gen
1003
1004   # MAKEDEV is just a forking bomb crap, let's do it on our own instead :)
1005   ( cd $MNTPOINT/dev && tar zxf /etc/debootstrap/devices.tar.gz )
1006
1007   # copy any existing files to chroot
1008   [ -d $CONFFILES/bin   ] && cp $VERBOSE -a -L $CONFFILES/bin/*   $MNTPOINT/bin/
1009   [ -d $CONFFILES/boot  ] && cp $VERBOSE -a -L $CONFFILES/boot/*  $MNTPOINT/boot/
1010   [ -d $CONFFILES/etc   ] && cp $VERBOSE -a -L $CONFFILES/etc/*   $MNTPOINT/etc/
1011   [ -d $CONFFILES/sbin  ] && cp $VERBOSE -a -L $CONFFILES/sbin/*  $MNTPOINT/sbin/
1012   [ -d $CONFFILES/share ] && cp $VERBOSE -a -L $CONFFILES/share/* $MNTPOINT/share/
1013   [ -d $CONFFILES/usr   ] && cp $VERBOSE -a -L $CONFFILES/usr/*   $MNTPOINT/usr/
1014   [ -d $CONFFILES/var   ] && cp $VERBOSE -a -L $CONFFILES/var/*   $MNTPOINT/var/
1015
1016   # copy local network setup to chroot
1017   if [ -r /etc/network/interfaces -a ! -r "${MNTPOINT}"/etc/network/interfaces ] ; then
1018      [ -d $MNTPOINT/etc/network ] || mkdir $MNTPOINT/etc/network
1019      cp $VERBOSE /etc/network/interfaces $MNTPOINT/etc/network/interfaces
1020   fi
1021
1022   # install config file providing some example entries
1023   if [ -r /etc/network/interfaces.examples -a ! -r "$MNTPOINT/etc/network/interfaces.examples" ] ; then
1024      cp /etc/network/interfaces.examples "$MNTPOINT/etc/network/interfaces.examples"
1025   fi
1026
1027   eend 0
1028 }
1029 # }}}
1030
1031 # execute all scripts in /etc/debootstrap/pre-scripts/ {{{
1032 execute_pre_scripts() {
1033    # make sure we have $MNTPOINT available for our scripts
1034    export MNTPOINT
1035    if [ -d "$_opt_pre_scripts" ] || [ "$PRE_SCRIPTS" = 'yes' ] ; then
1036       [ -d "$_opt_pre_scripts" ] && pre_scripts="$_opt_pre_scripts" || pre_scripts="$CONFFILES/pre-scripts/"
1037       for script in ${pre_scripts}/* ; do
1038          if [ -x "$script" ] ; then
1039             einfo "Executing pre-script $script"
1040             $script ; eend $?
1041          fi
1042       done
1043    fi
1044 }
1045 # }}}
1046
1047 # execute all scripts in /etc/debootstrap/scripts/ {{{
1048 execute_scripts() {
1049    # make sure we have $MNTPOINT available for our scripts
1050    export MNTPOINT
1051    if [ -d "$_opt_scripts" ] || [ "$SCRIPTS" = 'yes' ] ; then
1052       [ -d "$_opt_scripts" ] && scripts="$_opt_scripts" || scripts="$CONFFILES/scripts/"
1053       for script in ${scripts}/* ; do
1054          if [ -x "$script" ] ; then
1055             einfo "Executing script $script"
1056             $script ; eend $?
1057          fi
1058       done
1059    fi
1060 }
1061 # }}}
1062
1063 # execute chroot-script {{{
1064 chrootscript() {
1065   if ! [ -r "$MNTPOINT/bin/chroot-script" ] ; then
1066      mount_target
1067   fi
1068
1069   if [ -x "$MNTPOINT/bin/chroot-script" ] ; then
1070      einfo "Executing chroot-script now"
1071      mount --bind /dev "$MNTPOINT"/dev
1072      chroot "$MNTPOINT" /bin/chroot-script ; RC=$?
1073      umount "$MNTPOINT"/dev
1074      eend $RC
1075   else
1076      eerror "Fatal: $MNTPOINT/bin/chroot-script could not be found."
1077      eend 1
1078   fi
1079 }
1080 # }}}
1081
1082 # unmount $MNTPOINT {{{
1083 umount_chroot() {
1084
1085   # display installation notes:
1086   if [ -n "$INSTALL_NOTES" ] ; then
1087      [ -r "${MNTPOINT}/${INSTALL_NOTES}" ] && cat "${MNTPOINT}/${INSTALL_NOTES}"
1088   fi
1089
1090   if [ -n "$ISODIR" ] ; then
1091      if grep -q "$ISODIR" /proc/mounts ; then
1092         einfo "Unmount $MNTPOINT/$ISODIR"
1093         umount "$MNTPOINT/$ISODIR"
1094         eend $?
1095      fi
1096   fi
1097
1098   if grep -q "$MNTPOINT" /proc/mounts ; then
1099      if [ -n "$PARTITION" ] ; then
1100         einfo "Unmount $MNTPOINT"
1101         umount $MNTPOINT
1102         eend $?
1103      fi
1104   fi
1105 }
1106 # }}}
1107
1108 # execute filesystem check {{{
1109 fscktool() {
1110   if [ "$FSCK" = 'yes' ] ; then
1111      [ -n "$FSCKTOOL" ] || FSCKTOOL="fsck.${MKFS#mkfs.}"
1112      einfo "Checking filesystem on $TARGET using $FSCKTOOL"
1113      $FSCKTOOL $TARGET
1114      eend $?
1115   fi
1116 }
1117 # }}}
1118
1119 # now execute all the functions {{{
1120 for i in prepare_vm mkfs tunefs mount_target debootstrap_system \
1121          preparechroot execute_pre_scripts chrootscript execute_scripts \
1122          umount_chroot finalize_vm fscktool ; do
1123     if stage "${i}" ; then
1124        $i && ( stage "${i}" done && rm -f "${STAGES}/${i}" ) || bailout 2 "i"
1125     fi
1126 done
1127 # }}}
1128
1129 # finalize {{{
1130 einfo "Removing ${CHROOT_VARIABLES}" ; rm "$CHROOT_VARIABLES" ; eend $?
1131 einfo "Removing ${STAGES}" ; rmdir "$STAGES" ; eend $?
1132
1133 # Remove temporary mountpoint again
1134 if echo "$MNTPOINT" | grep -q '/mnt/debootstrap\.' ; then
1135    einfo "Removing directory ${MNTPOINT}" ; rmdir "$MNTPOINT" ; eend $?
1136 fi
1137 # }}}
1138
1139 # end dialog of autoinstallation {{{
1140 if [ -n "$AUTOINSTALL" ] ; then
1141    if dialog --title "${PN}" --pause "Finished execution of ${PN}.
1142 Automatically rebooting in 10 seconds.
1143
1144 Choose Cancel to skip rebooting." 10 60 10 ; then
1145      noeject noprompt reboot
1146   fi
1147 else
1148    einfo "Finished execution of ${PN}. Enjoy your Debian system." ; eend 0
1149 fi
1150 # }}}
1151
1152 ## END OF FILE #################################################################
1153 # vim: ai tw=100 expandtab foldmethod=marker shiftwidth=3