--- toast-linux	2005/02/05 23:19:38	1.132
+++ toast-linux	2005/02/05 23:59:08	1.133
@@ -1,6 +1,1580 @@
+#!/bin/sh
+
+case "$1" in
+  sbin/setup) topdir=.; mkdir -p sbin tmp;;
+  1.[1-9]*) topdir=/;;
+  *) exec perl -x "$0" "$@"; exit 1;;
+esac
+
+set -e
+: > sbin/setup
+chmod +x sbin/setup
+for i in toast help; do ln -s setup "sbin/$i"; done
+sed -e "s,TOPDIR,$topdir,g" > "sbin/setup" << "---"
+#!/bin/sh
+
+export http_proxy=http://67.126.59.194:8080/
+
+export PATH=/sbin:/bin:/usr/sbin:/usr/bin
+export HOME=/
+export SHELL=/bin/sh
+
+# es = estimated download size (in 1024-byte blocks, as per du -s); 0 = none
+# eb = estimated build time (where 10000 = median)
+# flags = zero or more of the following letters, mashed together:
+#   c = critical task; don't bother to continue if this fails
+#   n = nonrepresentative task; don't factor install time into estimates
+# as = actual download _time_ (not size!) in seconds (on this machine)
+# ab = actual build time in seconds (on this machine)
+
+topdir="tmp/setup"
+namedir="$topdir/name"
+numdir="$topdir/num"
+efile="$topdir/event"
+ufile="$topdir/updated"
+ffile="$topdir/failed"
+
+statuslines="5"
+
+color_stats="1;44"
+color_bar="1;36;46"
+
+color_pending="41"
+color_getting="40"
+color_missing="43"
+color_stored="1;41"
+color_building="1;40"
+color_broken="1;43"
+color_done="1;42"
+
+color_fkey="30;47"
+color_fkey_selected="1;37;47"
+color_fkey_eol="37;47"
+
+# solid block:     '\33(U\333\17'
+# left half block: '\33(U\335\17'
+# halftone block:  '\33(U\261\17'
+# up arrow:        '\33[3h\30\33[3l'
+# down arrow:      '\33[3h\31\33[3l'
+
+case "$TERM" in
+  *xterm*)
+    char_solid_block='\16a\17'
+    char_half_block=' '
+    ;;
+  *)
+    char_solid_block='\33(U\333\17'
+    char_half_block='\33(U\335\17'
+    ;;
+esac
+
+timeout()
+{
+  seconds="$1"
+  save="`stty -g`"
+  key=""
+  while [ "$seconds" -gt 0 -a -z "$key" ]; do
+    echo -ne '\r'"$seconds "
+    stty raw -echo time 10 min 0 || exit $?
+    key="`dd bs=1 count=1 2>/dev/null`"
+    stty "$save"
+    let seconds="$seconds - 1"
+  done
+  echo -ne '\r          \r'
+  [ -z "$key" ]
+}
+
+resize()
+{
+  save="`stty -g`"
+  stty raw -echo time 1 min 0
+  echo -ne '\33[s\33[255;255H\33[6n\33[u'
+  eval "`dd bs=1 count=128 2>/dev/null | sed -ne 's/.*\[\([0-9]\+\);\([0-9]\+\)R.*/LINES=\1;COLUMNS=\2;/p'`"
+  stty "$save"
+  [ -z "$LINES" ] && LINES=50
+  [ -z "$COLUMNS" ] && COLUMNS=80
+  export LINES COLUMNS
+}
+
+refresh()
+{
+  echo -ne "\33[0;${2}m " > "$1/display.tmp"
+  echo -n `cat $1/name` '' >> "$1/display.tmp"
+  if [ ! -d "$1/next" -o -r "$1/next/newline" ]; then
+    echo -e "\33[0;${3}m\33[K" >> "$1/display.tmp"
+  fi
+  mv "$1/display.tmp" "$1/display"
+}
+
+error()
+{
+  echo "$*" >&2
+  rm -f "$tmpfile"
+  exit 1
+}
+
+valid_disk_name()
+{
+  case "$1" in
+    */*) return 1 ;;
+    *[0-9]) return 1 ;;
+    [hs]d[a-z]*) return 0 ;;
+    *) return 1 ;;
+  esac
+}
+
+partition()
+{
+  # Environment variables:
+  # DISKS
+  # DESTROY
+
+  # Number of partitions to create on each disk.
+  # Each partition will be an LVM2 physical volume (PE).
+  # We split each disk into multiple partitions/PEs because there is no way
+  # to resize a PE once it has been created.  It would be very difficult
+  # to make room for another OS later on if we used only one PV per disk.
+  # Linux only allocates 15 minor numbers for SCSI disk partitions;
+  # if 1 is primary, 2 is extended, and 5-15 are logical, then there is a
+  # maximum of 12 usable partitions per disk.
+  slices=8
+
+  # LVM2 physical extent (PE) size, in megabytes.  This must be a power of two!
+  # Once the volume group (VG) has been created, its PE size can't be changed.
+  # The maximum logical volume (LV) size for the VG is about 64k times PE size.
+  # A PE size of 32 MB gets you a maximum LV size of 2 terabytes, which is
+  # the maximum allowed, so there is no point in using a value larger than 32.
+  # Each partition must be large enough to fit at least one PE (plus overhead),
+  # or it won't be very useful.
+  # Since each PV stores data in multiples of the PE size, smaller values might
+  # waste a bit less space, especially on smaller drives.
+  pemegs=16
+
+  # Number of megabytes to allocate to the /boot logical volume.
+  # /boot needs to be on a separate LV because current versions of lilo
+  # seem to panic if the LV spans multiple PVs (even if they're on the
+  # same disk!), so we need a special LV that is explicitly restricted to
+  # one PV.
+  bootmegs=128
+
+  # Number of megabytes to allocate for swap space.
+  # This gets its own logical volume.
+  swapmegs=1024
+
+  # Percentage of the total space in the volume group to allocate to the
+  # root logical volume we'll be creating.
+  # Remaining space in the VG will be used for /boot, swap (if any),
+  # by snapshots (for fsck or backups) and/or any other logical volumes
+  # the user might decide to create later.
+  lvpercent=80
+
+  # Volume group name.  If we want to be able to coexist peacefully with an
+  # existing Linux setup that also uses LVM, this shouldn't conflict with any
+  # existing volume group names.
+  vgname="toast"
+
+  # Temporary file used to store munged parted output.
+  tmpfile=/tmp/parted.munge.$$
+
+  # get/validate list of disks
+  if [ -n "$DISKS" ]; then
+    for disk in $DISKS; do
+      valid_disk_name "$disk" || error "bad disk name: $disk"
+    done
+  else
+    while read major minor blocks name rest; do
+      valid_disk_name "$name" && DISKS="$DISKS $name"
+    done < /proc/partitions
+    [ -z "$DISKS" ] && error "no disks found"
+  fi
+
+  # check block device nodes for all disks
+  for disk in $DISKS; do
+    path="/dev/$disk"
+    [ -b "$path" ] || error "not a block device: $path"
+    [ -r "$path" ] || error "can't read disk: $disk"
+    [ -w "$path" ] || error "can't write disk: $disk"
+  done
+
+  # create partitions
+  pvpaths=""
+  let pecount=0
+  for disk in $DISKS; do
+    path="/dev/$disk"
+    parted="parted -s $path --"
+    diskmajor=""
+    diskminor=""
+    totalm=""
+    totalk=""
+    overwrite=""
+    lastminor=0
+    extminor=0
+    labeltype=""
+    primary1exists=""
+    primary2exists=""
+    primary3exists=""
+    primary4exists=""
+
+    case "$disk" in
+      h*) maxminor=63 ;; # IDE
+      s*) maxminor=15 ;; # SCSI
+      *) error "assertion failed: $disk"
+    esac
+
+    while read major minor blocks name rest; do
+      if [ "$name" = "$disk" ]; then
+        diskmajor="$major"
+        diskminor="$minor"
+        let totalm="$blocks/1024"
+        let totalk="($blocks%1024)*1000/1024"
+        case "$totalk" in
+          [0-9]) totalk="00$totalk" ;;
+          [1-9][0-9]) totalk="0$totalk" ;;
+          [1-9][0-9][0-9]) ;;
+          *) error "assertion failed: disk=$disk blocks=$blocks k=$totalk"
+        esac
+      fi
+    done < /proc/partitions
+
+    [ -z "$totalm" ] && error "assertion failed: disk=$disk totalm=$totalm"
+    [ -z "$totalk" ] && error "assertion failed: disk=$disk totalk=$totalk"
+    [ -z "$diskmajor" ] && error "assertion failed: no major for disk=$disk"
+    [ -z "$diskminor" ] && error "assertion failed: no minor for disk=$disk"
+
+    sum=bf619eac0cdf3f68d496ea9344137e8b # md5sum of 512 zero bytes
+
+    if [ "$DESTROY" = "yes" ]; then
+      echo "# Entire disk $disk will be overwritten unconditionally."
+      overwrite="yes"
+    elif dd if="$path" bs=512 count=1 2>/dev/null | md5sum | grep -q "$sum"; then
+      echo "# Disk $disk appears to be empty; entire disk will be overwritten."
+      overwrite="yes"
+    else
+      echo "# Contents of disk $disk may be accidentally destroyed."
+      # TODO: tell user what partitions will go on this disk, if any
+      $parted print | sed -e 's/0\.000-//; s/\./ /g' > "$tmpfile"
+      while read one two three four five six rest; do
+        if [ "$one $two $three" = "Disk geometry for" ]; then
+          totalm="$five"
+          totalk="$six"
+        fi
+        [ "$one $two $three" = "Disk label type:" ] && labeltype="$one"
+        case "$one" in
+          [0-9]*)
+            [ "$one" -gt "$lastminor" ] && lastminor="$one"
+            [ "$six" = "extended" ] && extminor="$one"
+            [ "$six" = "primary" ] && eval "primary${one}exists=yes"
+            ;;
+        esac
+      done < "$tmpfile"
+      rm -f "$tmpfile"
+    fi
+
+    freeslot=0
+    for slot in 4 3 2; do
+      eval "[ -n \$primary{$slot}used ]" && freeslot="$slot"
+    done
+
+    if [ -n "$overwrite" ]; then
+      lastminor=0
+      extminor=0
+      labeltype="msdos"
+      echo "dd if=/dev/zero of=$path bs=512 count=1"
+      echo "$parted mklabel $labeltype"
+    fi
+
+    if [ "$labeltype" = "msdos" ] && [ "$extminor" -gt 0 -o "$freeslot" -gt 0 ]; then
+      let slicemegs="$totalm/$slices"
+      [ "$slicemegs" -le "$pemegs" ] && slicemegs=$totalm
+      let splitmegs="$slicemegs*2"
+      lastm=0
+      lastk=000
+      {
+        if [ -z "$overwrite" ]; then
+          $parted print | grep "^[0-9]" | cut -c 3- | sort -n | sed -e 's/\./ /g'
+        fi
+        echo "$totalm $totalk END END END END END"
+      } > "$tmpfile"
+      while read startm startk endm endk type fs flags; do
+        let gapmegs="($startm$startk-$lastm$lastk)/1000"
+        create=yes
+        while [ "$gapmegs" -gt "$pemegs" -a "$lastminor" -lt "$maxminor" -a -n "$create" ]; do
+          if [ "$gapmegs" -gt "$splitmegs" ]; then
+            let newendm="$lastm+$slicemegs"
+            newendk="$lastk"
+            let gapmegs="$gapmegs-$slicemegs"
+          else
+            newendm="$startm"
+            newendk="$startk"
+            gapmegs="0"
+          fi
+          let newminor="1+$lastminor"
+          if [ "$newminor" -eq 1 ]; then
+            newtype="primary"
+          else
+            newtype="logical"
+            [ "$newminor" -le 4 ] && newminor=5
+            if [ "$extminor" -eq 0 ]; then
+              extminor="$freeslot"
+              echo "$parted mkpart extended $lastm.$lastk -0"
+              echo "$parted set $extminor lba on"
+            fi
+          fi
+          echo "$parted mkpart $newtype ext2 $lastm.$lastk $newendm.$newendk"
+          echo "$parted set $newminor lvm on"
+          pvpaths="$pvpaths $path$newminor"
+          let newpecount="($newendm$newendk-$lastm$lastk)/($pemegs*1000)"
+          let pecount="$pecount+$newpecount"
+          lastm="$newendm"
+          lastk="$newendk"
+          lastminor="$newminor"
+        done
+        lastm="$endm"
+        lastk="$endk"
+      done < "$tmpfile"
+      rm -f "$tmpfile"
+    fi
+  done
+
+  # create filesystems on the new partitions
+  [ -z "$pvpaths" -o "$pecount" -eq 0 ] && error "no room for new partitions"
+  let lvextents="$pecount*$lvpercent/100"
+  echo "devices"
+  for pvpath in $pvpaths; do
+    echo "dd if=/dev/zero of=$pvpath bs=512 count=10"
+  done
+  echo "pvcreate -fy -M2 $pvpaths"
+  echo "vgcreate -s $pemegs $vgname $pvpaths"
+  echo "lvcreate -L "$bootmegs"m -n boot $vgname" # TODO: restrict to first PV
+  echo "lvcreate -l $lvextents -n root $vgname"
+  echo "lvcreate -L "$swapmegs"m -n swap $vgname"
+  echo "vgchange -ay $vgname"
+  for lvname in boot root; do
+    lvpath="/dev/$vgname/$lvname"
+    echo "parted -s $lvpath -- mklabel loop"
+    echo "parted -s $lvpath -- mkpartfs primary ext2 0 -0"
+    echo "tune2fs -j $lvpath"
+  done
+  echo "mount -t ext2 /dev/toast/root /mnt"
+  echo "mkdir /mnt/boot"
+  echo "mount -t ext2 /dev/toast/boot /mnt/boot"
+  echo "mkswap /dev/$vgname/swap"
+  echo "swapon /dev/toast/swap"
+}
+
+prepare()
+{
+  if [ "TOPDIR" = "." ]; then
+    export TOASTINIT_NO_LILO=1
+    echo "mkdir mnt mnt/boot mnt/lost+found" > tmp/partition
+    return 0
+  else
+    echo "0" > /proc/sys/kernel/printk
+    echo ""
+    echo "Figuring out how to (re)partition your disk(s):"
+    partition > tmp/partition || return 1
+    grep '^# ' tmp/partition
+    echo -e "Press any key to abort.  \33[1;31mThis is your last chance!\33[0m"
+    timeout 20 || exit 1
+  fi
+
+  echo -n "Preparing to install; please wait..."
+  resize
+  for i in `seq 1 $statuslines`; do echo; done
+  let scroll="$LINES-$statuslines"
+
+  cat > tmp/tasks << "EOF"
+partition 0 0 cn
+rootfs 17468 596 cn
+perl 9500 10345 c
+toast 88 170 c
+add 0 553 cn
+wget 1312 766 
+glibc 47632 152580 c sbin/toast build glibc
+binutils 11280 9663 c
+gcc 26832 15879 c sbin/toast --confappend="--enable-languages=c" arm gcc
+glibc 0 143043 c sbin/toast arm glibc && sbin/toast rebuild glibc
+binutils 0 10387 c sbin/toast rebuild binutils
+gcc 0 96299 c sbin/toast rebuild gcc
+make 920 1106 c
+perl 0 12729 c
+toast 0 42 c
+gawk 1616 1319 c
+coreutils 3884 3831 c
+flex 664 766 
+ncurses 2124 5619 
+readline 960 681 
+bash 2384 2980 c
+sed 772 808 c
+grep 568 681 
+gzip 236 127 
+tar 1076 1277 c
+remove 0 425 c sbin/toast remove rootfs
+openssl 2992 7237 
+wget 0 1021 - sbin/toast rebuild wget
+diffutils 784 1106 
+bzip2 672 383 
+zlib 444 255 
+util-linux 1352 1873 
+module-init-tools 140 766 
+gettext 6428 8855 
+procps 292 596 
+patch 204 340 
+findutils 780 1362 
+sysvinit 112 170 
+sysklogd 116 127 
+linux 33936 21712 
+device-mapper 648 340 
+LVM2 452 1702 
+bin86 168 212 
+nasm 556 723 
+lilo 436 340 
+e2fsprogs 3100 1915 
+devfsd 56 127 
+udev 372 255 
+genext2fs 48 85 
+toastinit 24 127 
+toastlogin 24 0 
+iana-etc 180 42 
+zsh 2012 3788 
+net-tools 220 425 
+dhcpcd 168 298 
+openssh 856 2894 
+vim 3216 2639 
+inetutils 1040 2043 
+less 280 510 
+parted 1408 1660 
+groff 2380 3065 
+man 220 170 
+man-pages 1776 255 
+texinfo 1868 1404 
+cpio 204 212 
+hdparm 56 127 
+m4 332 255 
+bison 816 1192 
+autoconf 1228 298 
+automake 856 255 
+file 428 723 
+libtool 2612 1064 
+kbd 888 468 
+ed 204 255 
+pkgconfig 500 1447 
+tetex 11504 13793 
+Python 7056 6343 
+db 5812 6641 - LDFLAGS=-lpthread sbin/toast arm db # for postfix 2.1.5
+gdbm 244 681 
+bind 4476 4640 
+autofs 144 255 
+curl 1124 2554 
+figlet 192 85 
+adns 232 681 
+gc 756 1149 
+genromfs 40 85 
+gmp 1664 5534 
+httpd 6788 6811 
+libelf 152 766 
+ltrace 140 298 
+strace 432 851 
+minicom 616 936 
+bc 296 298 
+miscfiles 2176 127 
+mtools 280 979 
+mtr 112 298 
+gnupg 2344 2596 
+mutt 2572 1788 
+nmap 1248 3278 
+ntp 2476 2682 
+ocaml 2024 5491 
+pciutils 128 170 
+postfix 1948 1745 
+procmail 244 979 
+vsftpd 164 212 
+rcs 424 766 
+samba 14860 12984 
+smartmontools 192 0 
+valgrind 964  
+zip 728 255 
+unzip 1108 425 
+popt 584 766 
+pcre 364 638 
+subversion 6008 12303 
+cdrtools 1624 2809 
+libogg 300 553 
+libvorbis 1212 1660 
+lame 1248 2554 
+jpeg 620 766 
+libpng 392 979 
+tiff 1068 766 
+netpbm 2060 5066 
+alsa-lib 576 2426 
+alsa-utils 160 553 
+alsa-tools 740  
+libmng 520 2256 
+syslinux 432  
+units 224 170 
+espgs 5304 7577 
+cvs 2344 2256 
+gale 396 2426 - LIBS=-ldl sbin/toast arm gale
+ExtUtils-Depends 28 42 
+ExtUtils-PkgConfig 24 42 
+libxml2 2740 6896 
+libxslt 1748 2426 
+OpenSP 1412 11452 
+openjade 1056 9110 
+docbook-xml 104 0 
+docbook-xsl 1528 85 
+XML-Parser 248 212 
+XFree86 53032 78546 
+doctools 1400 298 
+fvwm 1380 3831 
+lua 208 340 
+ion 412 1830 
+xscreensaver 4288 6598 
+xdaliclock 204 298 
+freetype 852 1788 
+fam 336  
+t1lib 1516  
+xpdf 544 2000 
+lesstif 3404 6854 
+SDL 2564 5023 
+xine-lib 7212  
+xine-ui 2572  
+cdparanoia 136  
+glib 2120 3490 
+libIDL 340 1277 
+ORBit2 672 4640 
+intltool 144 170 
+libbonobo 1448 4895 
+pango 952 2809 
+atk 512 1064 
+gtk+ 9408 15496 
+mozilla 29072 99151 
+GConf 1712 2937 
+desktop-file-utils 356 596 
+gnome-mime-data 660 425 
+gnome-vfs 1840 9280 
+audiofile 296 1873 
+esound 332 894 
+libgnome 1160 1575 
+libart_lgpl 280 1192 
+libglade 324 936 
+libgnomecanvas 588 1745 
+libbonoboui 968 5832 
+hicolor-icon-theme 48 85 
+gnome-icon-theme 2824 1788 
+gnome-keyring 360 1021 
+libgnomeui 1608 4895 
+startup-notification 244 723 
+gtk-engines 416 681 
+gnome-themes 2680 4001 
+scrollkeeper 556 1362 
+gnome-desktop 1112 1575 
+libwnck 404 1830 
+libsoup 416 1660 
+evolution-data-server 4924 13325 
+gnome-panel 3152 5406 
+gnome-session 872 1915 
+vte 888  
+gnome-terminal 2040  
+libgtop 1032 2894 
+gail 560 3703 
+libxklavier 312  
+gnome-applets 6280  
+metacity 2140 3192 
+librsvg 376 2298 
+eel 624 3192 
+nautilus 5668 9834 
+libgtkhtml 440 5491 
+yelp 644 1362 
+bug-buddy 716 766 
+libgnomeprint 756 3490 
+libgnomeprintui 588 1915 
+gtksourceview 696 1319 
+gedit 2444 3874 
+eog 808 1404 
+ggv 1272 2469 
+gconf-editor 516 936 
+gnome-utils 1720 1915 
+gstreamer 1376 8769 
+gst-plugins 1980 15879 
+gnome-media 3120 4640 
+nautilus-media 432 1830 
+gnome-netstatus 504 1021 
+gcalctool 908 1192 
+gpdf 1044 3788 
+gucharmap 1468 1702 
+nautilus-cd-burner 524 1277 
+zenity 732 596 
+at-spi 516 3618 
+libgail-gnome 160 808 
+gnome-speech 272 851 
+gnome-mag 324 1064 
+gnopernicus 1788 4342 
+gok 1220 3703 
+epiphany 3324  
+gnome-games 5812 6556 
+file-roller 1368 2426 
+gnome-system-tools 2676 2639 
+gnome-nettool 516 1064 
+vino 536 1702 
+dbus 1240 2724 
+hal 1300  
+gnome-volume-manager 200  
+gal 1140 8812 
+gtkhtml 1308 8514 
+evolution 14672  
+evolution-webcal 156 425 
+pwlib 1080  
+gnomemeeting 2892  
+libsigc++ 1404 2767 
+glibmm 812 3959 
+gtkmm 3864 47553 
+libgnomemm 260 979 
+libgnomecanvasmm 328 4299 
+libglademm 508 2086 
+gconfmm 276 1617 
+gnome-vfsmm 332 3405 
+libgnomeuimm 332 7705 
+libgtk-java 460  
+libgconf-java 76  
+libglade-java 92  
+libgnome-java 176  
+Glib 220 510 
+Gtk2 560 6002 
+Gnome2-Canvas 84 340 
+Gnome2-VFS 64 510 
+Gnome2-GConf 44 255 
+Gnome2 100 2086 
+Gtk2-GladeXML 48 127 
+pygtk 636 2724 
+qt-x11-free 14124 132145 - LD_LIBRARY_PATH=/toast/pkg/qt-x11-free/v3.3.3/1/src/qt-x11-free-3.3.3/lib sbin/toast arm qt-x11-free
+arts 968 13367 
+kdelibs 15296 133677 
+kdebase 19568 138445 
+kde-i18n 190996 63262 
+kdeaccessibility 1236 5747 
+kdeadmin 1544 19327 
+kdeartwork 17600 14517 
+kdebindings 6996 111454 
+kdeedu 21600 72671 
+kdegames 9152 46574 
+kdegraphics 6120 58835 
+kdemultimedia 5288 77992 
+kdenetwork 6828 78631 
+kdepim 9792 147641 
+kdesdk 4288  
+kdetoys 2720 7194 
+kdeutils 2180 38868 
+kdevelop 7796 114349 
+kdewebdev 4716 64284 
+kdeaddons 1548 30609 
+firefox 31976  
+xmms 2384  
+gimp 13520  
+gkrellm 656 1660 
+EOF
+
+  mkdir -p "$numdir" "$namedir"
+  i=0
+  line=""
+  prev=""
+  while read name size time flags icmd; do
+    line="$line $name "
+    if echo "$line" | egrep -q "..{$COLUMNS}"; then
+      newline=1
+      line=" $name "
+      echo ""
+      let scroll="$scroll-1"
+    else
+      newline=""
+    fi
+    echo -n " $name "
+
+    let i="$i+1"
+    num="`printf %08d $i`"
+    dir="$numdir/$num"
+    ddir="$dir/download"
+    idir="$dir/install"
+
+    mkdir "$dir" "$ddir" "$idir"
+    echo "$num" > "$dir/num"
+    echo "$name" > "$dir/name"
+    [ -n "$size" ] || size=1000 # guess about one megabyte of source
+    echo "$size" > "$ddir/estimate"
+    [ -n "$time" ] || time=10000 # defined to be the median time
+    echo "$time" > "$idir/estimate"
+    case "$flags" in *c*) : > "$dir/critical";; esac
+    case "$flags" in *n*) : > "$idir/nonrepresentative";; esac
+    [ -n "$newline" ] && : > "$dir/newline"
+
+    if [ "$size" = "0" ]; then
+      dcmd="echo no download necessary"
+      : > "$ddir/precondition"
+    else
+      dcmd="exec sbin/toast get $name"
+      ln -s "../../../name/wget/install/time" "$ddir/precondition"
+    fi
+    ln -s "../../../../../mnt/toast/pkg/$name" "$ddir/progress"
+    echo -e "#!/bin/sh\12$dcmd" > "$ddir/command"
+    chmod +x "$ddir/command"
+
+    [ -n "$icmd" ] || icmd="exec sbin/toast arm $name"
+    echo -e "#!/bin/sh\12$icmd" > "$idir/command"
+    chmod +x "$idir/command"
+    ln -s "../download/time" "$idir/precondition"
+    ln -s "../download/failed" "$idir/skip"
+
+    if [ ! -d "$namedir/$name" ]; then
+      ln -s "../num/$num" "$namedir/$name"
+    else
+      let suffix=2
+      while [ -d "$namedir/$name.$suffix" ]; do let suffix="1+$suffix"; done
+      ln -s "../num/$num" "$namedir/$name.$suffix"
+    fi
+
+    if [ -n "$prev" ]; then
+      ln -s "../$prev" "$dir/prev"
+      ln -s "../$num" "$dir/prev/next"
+    fi
+    prev="$num"
+  done < tmp/tasks
+
+  for i in `seq 2 $scroll`; do echo; done
+  echo -ne "\33[H\33[${statuslines}B"
+
+  for dir in "$numdir/"*; do
+    refresh "$dir" "$color_pending" "$color_pending"
+    cat "$dir/display"
+  done
+
+  # special commands:
+
+  echo "#!/bin/sh -ex" > "$namedir/partition/install/command"
+  cat tmp/partition >> "$namedir/partition/install/command"
+  rm tmp/partition
+
+  cat > "$namedir/rootfs/download/command" << "EOF"
+#!/bin/sh -ex
+if [ "`cd mnt; echo *`" != "boot lost+found" ]; then
+  echo "unexpected filesystem contents" >&2
+  exit 1
+fi
+mkdir -p mnt/toast/pkg/rootfs/v0/archive
+cd mnt/toast/pkg/rootfs/v0/archive
+wget http://www.kernel.org/pub/linux/libs/uclibc/root_fs_i386.bz2
+EOF
+  ln -sf "../../../name/partition/install/time" "$namedir/rootfs/download/precondition"
+
+  cat > "$namedir/rootfs/install/command" << "EOF"
+#!/bin/sh -ex
+
+if [ "`cd mnt; echo *`" != "boot lost+found toast" ]; then
+  echo "unexpected filesystem contents" >&2
+  exit 1
+fi
+
+for i in boot dev dev/pts etc/dhcpc etc/xml home media/floppy media/cdrom mnt proc root sys toast tmp usr/bin var/empty var/lock var/run var/log var/spool/mail; do
+  mkdir -p "mnt/$i"
+done
+chmod 1777 "mnt/tmp"
+
+if grep -q '[^b]devfs' /proc/filesystems; then
+  mount -t devfs dev mnt/dev
+elif [ -d dev ]; then
+  tar -c -C / dev | tar -x -C mnt
+  chmod go-w mnt/dev
+else
+  mknod mnt/dev/null c 1 3
+  mknod mnt/dev/zero c 1 5
+  mknod mnt/dev/random c 1 8
+  mknod mnt/dev/urandom c 1 9
+  chmod 666 mnt/dev/null
+fi
+
+for i in bin lib sbin; do ln -sf "usr/$i" "mnt/$i"; done
+cp /etc/resolv.conf mnt/etc/
+[ -r /etc/TZ -a -z "$TZ" ] && TZ="`cat /etc/TZ`"
+[ -z "$TZ" ] && TZ="PST8PDT"
+ln -s "../usr/share/zoneinfo/$TZ" mnt/etc/localtime
+ln -s "../../usr/etc/xml/toast-xml-catalog" mnt/etc/xml/catalog
+ln -s bash mnt/bin/sh
+ln -s gcc mnt/bin/cc
+echo "/lib" > mnt/etc/ld.so.conf
+
+cat > mnt/etc/passwd << 'END'
+root:x:0:0:root:/root:/bin/zsh
+bin:x:1:1:bin:/bin:/bin/false
+daemon:x:2:2:daemon:/sbin:/bin/false
+adm:x:3:4:adm:/var/adm:/bin/false
+lp:x:4:7:lp:/var/spool/lpd:/bin/false
+sync:x:5:0:sync:/sbin:/bin/sync
+shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
+halt:x:7:0:halt:/sbin:/sbin/halt
+mail:x:8:12:mail:/var/spool/mail:/bin/false
+news:x:9:13:news:/var/spool/news:/bin/false
+uucp:x:10:14:uucp:/var/spool/uucp:/bin/false
+operator:x:11:0:operator:/root:/bin/false
+games:x:12:100:games:/usr/games:/bin/false
+ftp:x:14:50:FTP User:/home/ftp:/bin/false
+toast:x:42:42:toast:/toast:/bin/zsh
+nobody:x:99:99:nobody:/:/bin/false
+END
+
+cat > mnt/etc/group << 'END'
+root:x:0:root
+bin:x:1:bin
+daemon:x:2:daemon
+sys:x:3:sys
+adm:x:4:adm
+tty:x:5:
+disk:x:6:
+lp:x:7:lp
+mem:x:8:
+kmem:x:9:
+wheel:x:10:
+mail:x:12:mail
+news:x:13:news
+uucp:x:14:uucp
+man:x:15:
+floppy:x:19:
+games:x:20:games
+slocate:x:21:
+utmp:x:22:
+squid:x:23:
+gopher:x:30:
+toast:x:42:toast
+ftp:x:50:
+nobody:x:99:
+users:x:100:
+nofiles:x:65533:
+END
+
+[ -z "$USERS" ] && USERS=user
+USERS="`echo \"$USERS\" | sed -e 's/[^a-z0-9]/ /g; s/^  *//; s/  *$//'`"
+uid=500
+for i in $USERS; do
+  echo "$i:x:$uid:$uid:$i:/home/$i:/bin/zsh" >> mnt/etc/passwd
+  echo "$i:x:$uid:" >> mnt/etc/group
+  [ -r mnt/etc/user ] || echo $i > mnt/etc/user
+  mkdir "mnt/home/$i"
+  chown $uid.$uid "mnt/home/$i"
+  let uid="1+$uid"
+done
+
+mount -t proc proc mnt/proc
+mount -t sysfs sys mnt/sys
+
+bunzip2 mnt/toast/pkg/rootfs/v0/archive/*
+mount -t ext2 -o loop mnt/toast/pkg/rootfs/v0/archive/* mnt/mnt
+mkdir -p mnt/toast/pkg/rootfs/v0/1/root
+tar -c -C mnt/mnt . | tar -x -C mnt/toast/pkg/rootfs/v0/1/root
+umount mnt/mnt
+rm -fr mnt/toast/pkg/rootfs/v0/archive
+EOF
+
+  cat > "$namedir/perl/download/command" << "EOF"
+#!/bin/sh -ex
+version=5.8.6
+url=http://www.cpan.org/src/5.0/perl-$version.tar.bz2
+adir=mnt/toast/pkg/perl/v$version/archive
+set -e
+mkdir -p "$adir"
+cd "$adir"
+echo "$url" > ../url
+wget "$url"
+EOF
+  ln -sf . "$namedir/perl/download/precondition"
+  cat > "$namedir/perl/install/command" << "EOF"
+#!/bin/sh -ex
+bdir="mnt/toast/pkg/rootfs/v0/1"
+ln mnt/toast/pkg/perl/*/archive/* "$bdir/root/tmp/"
+chroot "$bdir/root" sh -ex << "END" | tee "$bdir/build.log"
+cd /tmp
+tar xjf perl-*.tar.bz2
+rm -f perl-*.tar.bz2 /usr/lib/*.so
+cd perl-*
+sh Configure -des -Dprefix=/usr -Dextensions="Errno File/Glob" -Uusevfork -Uuseperlio -Uusefaststdio -Uusenm -Uusedl -Uuselargefiles
+make all install
+rm -f /usr/bin/cc
+END
+EOF
+
+  cat > "$namedir/toast/download/command" << "EOF"
+#!/bin/sh -ex
+mkdir -p mnt/toast/pkg/toast/vlatest/archive
+cd mnt/toast/pkg/toast/vlatest/archive
+wget http://toastball.net/toast/toast.tar.gz
+EOF
+  ln -sf . "$namedir/toast/download/precondition"
+  cat > "$namedir/toast/install/command" << "EOF"
+#!/bin/sh -ex
+export TOAST_ARMDIR=/usr TOAST_PRELOAD=false
+rdir="/toast/pkg/rootfs/v0/1/root"
+tar xzf mnt/toast/pkg/toast/vlatest/archive/toast.tar.gz -C "mnt$rdir/tmp/"
+ln mnt$rdir/tmp/toast-*/toast mnt$rdir/bin/
+chroot mnt "$rdir/usr/bin/perl" -x "$rdir/bin/toast" arm rootfs
+version="`toast version | cut -c 7-`"
+sbin/toast rename toast/latest "toast/$version"
+sbin/toast change "http://toastball.net/toast/toast-$version.tar.gz"
+EOF
+
+  cat > "$namedir/add/install/command" << "EOF"
+#!/bin/sh
+sed 's/\#.*//' << "END" | grep . | while read x; do sbin/toast add $x; done
+
+# oddball essentials:
+
+# URLs for glibc are in get-glibc script
+
+[ http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.5.tar.bz2 http://toastball.net/toast-linux-tmp/linux-2.6.5-config.tar.gz ]
+
+#lilo/22.5.9-devmapper: [ http://lilo.go.dyndns.org/pub/linux/lilo/obsolete/lilo-22.5.9.tar.gz http://www.saout.de/misc/lilo-22.5.9-devmapper.patch ]
+http://home.san.rr.com/johninsd/pub/linux/lilo/
+
+genext2fs/1.3-7.1: [ http://http.us.debian.org/debian/pool/main/g/genext2fs/genext2fs_1.3.orig.tar.gz http://http.us.debian.org/debian/pool/main/g/genext2fs/genext2fs_1.3-7.1.diff.gz ]
+
+sysklogd/1.4.1: [ http://www.infodrom.org/projects/sysklogd/download/sysklogd-1.4.1.tar.gz http://ep09.pld-linux.org/~mmazur/linux-libc-headers/patches/sysklogd.patch ]
+# http://mirrors.angelinacounty.net/pub/lfs/lfs-packages/testing/sysklogd-1.4.1-kernel_headers-1.patch
+
+[ http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.60.tar.bz2 http://toastball.net/toast-linux-tmp/net-tools-1.60-toast.patch ]
+
+# other required packages:
+ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.85.tar.gz
+http://ftp.gnu.org/gnu/bash/bash-3.0.tar.gz
+http://ftp.gnu.org/gnu/binutils/binutils-2.15.tar.bz2
+http://ftp.gnu.org/gnu/coreutils/coreutils-5.0.tar.bz2
+http://ftp.gnu.org/gnu/diffutils/diffutils-2.8.1.tar.gz
+http://ftp.gnu.org/gnu/findutils/
+http://ftp.gnu.org/gnu/gawk/gawk-3.1.3.tar.bz2
+http://ftp.gnu.org/gnu/gcc/gcc-3.4.3/gcc-3.4.3.tar.bz2
+http://ftp.gnu.org/gnu/gettext/gettext-0.14.1.tar.gz
+http://ftp.gnu.org/gnu/grep/grep-2.5.tar.bz2
+http://ftp.gnu.org/gnu/gzip/gzip-1.2.4a.tar.gz
+http://ftp.gnu.org/gnu/make/
+http://ftp.gnu.org/gnu/ncurses/ncurses-5.4.tar.gz
+http://ftp.gnu.org/gnu/patch/patch-2.5.4.tar.gz
+http://ftp.gnu.org/gnu/readline/readline-4.3.tar.gz
+http://ftp.gnu.org/gnu/sed/sed-4.0.9.tar.gz
+http://ftp.gnu.org/gnu/tar/tar-1.14.tar.bz2
+http://ftp.gnu.org/gnu/wget/wget-1.9.1.tar.gz
+http://kernel.org/pub/linux/daemons/devfsd/devfsd-v1.3.25.tar.bz2
+http://kernel.org/pub/linux/utils/kernel/hotplug/
+http://kernel.org/pub/linux/utils/kernel/module-init-tools/module-init-tools-3.0.tar.bz2
+http://kernel.org/pub/linux/utils/util-linux/
+http://mirrors.kernel.org/sources.redhat.com/bzip2/v102/bzip2-1.0.2.tar.gz
+http://mirrors.kernel.org/sources.redhat.com/dm/
+http://mirrors.kernel.org/sources.redhat.com/lvm2/
+http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.35.tar.gz
+http://prdownloads.sourceforge.net/infozip/unzip551.tar.gz
+http://prdownloads.sourceforge.net/infozip/zip23.tar.gz
+http://prdownloads.sourceforge.net/nasm/nasm-0.98.38.tar.bz2
+http://toastball.net/toast/init/
+http://toastball.net/toast/login/
+http://www.phystech.com/ftp/dhcpcd-1.3.22-pl4.tar.gz
+http://www.sethwklein.net/projects/iana-etc/downloads/iana-etc-0.99.tar.bz2
+http://www.zsh.org/pub/
+
+# tricky optional packages:
+[ http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-1.tgz http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-2.tgz http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-3.tgz http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-4.tgz http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-5.tgz http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-6.tgz http://ftp.xfree86.org/pub/XFree86/4.4.0/source/XFree86-4.4.0-src-7.tgz ]
+http://prdownloads.sourceforge.net/lex/flex-2.5.27.tar.bz2 # flex 2.5.31 is broken and can't build XFree86 4.4.0, for instance
+http://prdownloads.sourceforge.net/freetype/freetype-2.1.5.tar.bz2 # 2.1.7 seems to cause include problems with xft 2.1.2
+# [ http://prdownloads.sourceforge.net/openjade/OpenSP-1.5.1.tar.gz http://belfs.linux-phreak.net/belfs/blfs-patches/OpenSP-1.5.1-gcc34-2.patch ]
+[ http://prdownloads.sourceforge.net/openjade/OpenSP-1.5.1.tar.gz http://toastball.net/toast-linux-tmp/OpenSP-1.5.1-gcc34-2.patch ]
+adns/1.1: [ ftp://ftp.chiark.greenend.org.uk/users/ian/adns/adns-1.1.tar.gz http://www.bytebot.net/rrjcode/adns-ppc.patch ]
+https://ccvs.cvshome.org/files/documents/19/534/cvs-1.11.18.tar.bz2 # requires openssl to download; see special case at the end of prepare()
+
+# Gnome 2.8.0, KDE 3.3.2:
+http://ftp.gnome.org/pub/GNOME/bindings/2.8/2.8.0/sources/c++/
+http://ftp.gnome.org/pub/GNOME/bindings/2.8/2.8.0/sources/java/
+http://ftp.gnome.org/pub/GNOME/bindings/2.8/2.8.0/sources/perl/
+http://ftp.gnome.org/pub/GNOME/bindings/2.8/2.8.0/sources/python/
+http://ftp.gnome.org/pub/GNOME/desktop/2.8/2.8.0/sources/
+http://ftp.gnome.org/pub/GNOME/platform/2.8/2.8.0/sources/
+http://ibiblio.org/pub/mirrors/kde/stable/3.3.2/src/
+
+# additional GNOMEy-looking stuff
+http://freedesktop.org/software/dbus/releases/
+http://freedesktop.org/software/desktop-file-utils/releases/
+http://freedesktop.org/software/icon-theme/releases/hicolor-icon-theme-0.5.tar.gz
+http://freedesktop.org/software/shared-mime-info/shared-mime-info-0.14.tar.gz
+http://freedesktop.org/~david/hal-0.4.2.tar.gz
+http://freedesktop.org/~fontconfig/release/fontconfig-2.2.93.tar.gz
+http://freedesktop.org/~fontconfig/release/xft-2.1.2.tar.gz
+http://freedesktop.org/~xlibs/release/render-0.8.tar.gz
+http://freedesktop.org/~xlibs/release/xrender-0.8.3.tar.gz
+http://ftp.gnome.org/pub/GNOME/sources/gal/2.1/gal-2.1.7.tar.bz2
+http://ftp.gnome.org/pub/GNOME/sources/libcroco/0.5/libcroco-0.5.0.tar.bz2
+http://ftp.gnome.org/pub/GNOME/sources/libgsf/1.8/libgsf-1.8.2.tar.bz2
+http://ftp.gnome.org/pub/GNOME/sources/libsigc++/2.0/
+http://www.openh323.org/bin/pwlib_1.5.2.tar.gz
+
+# everything else:
+ftp://ftp.berlios.de/pub/cdrecord/cdrtools-2.00.3.tar.gz
+ftp://ftp.bitwizard.nl/mtr/mtr-0.58.tar.gz
+ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-4.5.tar.bz2
+ftp://ftp.foolabs.com/pub/xpdf/t1lib-1.3.tar.gz
+ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.00.tar.gz
+ftp://ftp.fvwm.org/pub/fvwm/version-2/fvwm-2.4.19.tar.bz2
+ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-1.2.4.tar.bz2
+ftp://ftp.isc.org/isc/bind9/9.2.3/bind-9.2.3.tar.gz
+ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.1.x/popt-1.7.tar.gz
+ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
+ftp://ftp.vim.org/pub/vim/unix/vim-6.2.tar.bz2
+ftp://ftp.win.tue.nl/pub/linux-local/utils/kbd/kbd-1.12.tar.gz
+ftp://oss.sgi.com/projects/fam/download/fam-2.6.10.tar.gz
+http://alioth.debian.org/download.php/123/minicom-2.1.tar.gz
+http://caml.inria.fr/distrib/ocaml-3.08/ocaml-3.08.1.tar.bz2
+http://curl.haxx.se/download/curl-7.11.1.tar.bz2
+http://developer.kde.org/~sewardj/valgrind-2.2.0.tar.bz2
+http://dl.maptools.org/dl/libtiff/tiff-v3.6.1.tar.gz
+http://download.insecure.org/nmap/dist/nmap-3.50.tar.bz2
+http://download.ofb.net/gale/gale-0.99fruit.tar.bz2
+http://fresh.t-systems-sfr.com/fresh/unix/src/misc/file-4.12.tar.gz
+http://ftp.figlet.org/pub/figlet/program/unix/figlet221.tar.gz
+http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz
+http://ftp.gnu.org/gnu/automake/automake-1.8.2.tar.gz
+http://ftp.gnu.org/gnu/bc/bc-1.06.tar.gz
+http://ftp.gnu.org/gnu/bison/bison-1.875.tar.bz2
+http://ftp.gnu.org/gnu/cpio/cpio-2.5.tar.gz
+http://ftp.gnu.org/gnu/ed/ed-0.2.tar.gz
+http://ftp.gnu.org/gnu/gdbm/gdbm-1.8.3.tar.gz
+http://ftp.gnu.org/gnu/gmp/
+http://ftp.gnu.org/gnu/groff/groff-1.19.tar.gz
+http://ftp.gnu.org/gnu/inetutils/inetutils-1.4.2.tar.gz
+http://ftp.gnu.org/gnu/libtool/libtool-1.5.2.tar.gz
+http://ftp.gnu.org/gnu/m4/m4-1.4.tar.gz
+http://ftp.gnu.org/gnu/miscfiles/miscfiles-1.3.tar.gz
+http://ftp.gnu.org/gnu/parted/
+http://ftp.gnu.org/gnu/texinfo/texinfo-4.6.tar.gz
+http://ftp.gnu.org/gnu/units/units-1.80.tar.gz
+http://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.0/source/firefox-1.0-source.tar.bz2
+http://ftp.mozilla.org/pub/mozilla.org/mozilla/releases/mozilla1.7.3/src/mozilla-source-1.7.3.tar.bz2
+http://ftp.silug.org/mirrors/ftp.trolltech.com/qt/source/qt-x11-free-3.3.3.tar.bz2
+http://ftp.xfree86.org/pub/XFree86/4.4.0/source/doctools-1.3.2.tgz
+http://kernel.org/pub/linux/daemons/autofs/v4/autofs-4.1.2.tar.bz2
+http://kernel.org/pub/linux/docs/manpages/man-pages-1.65.tar.bz2
+http://kernel.org/pub/linux/utils/boot/syslinux/
+http://kernel.org/pub/linux/utils/man/man-1.5m2.tar.bz2
+http://kernel.org/pub/software/utils/pciutils/pciutils-2.1.11.tar.bz2
+http://mirrors.isc.org/pub/postfix/official/postfix-2.1.5.tar.gz
+http://mtools.linux.lu/mtools-3.9.9.tar.bz2
+http://openbsd.md5.com.ar/pub/OpenBSD/OpenSSH/portable/
+http://prdownloads.sourceforge.net/docbook/docbook-xsl-1.65.1.tar.gz
+http://prdownloads.sourceforge.net/espgs/espgs-7.07.1-source.tar.bz2
+http://prdownloads.sourceforge.net/lame/lame-3.96.tar.gz
+http://prdownloads.sourceforge.net/lesstif/lesstif-0.93.94.tar.bz2
+http://prdownloads.sourceforge.net/libpng/zlib-1.2.2.tar.gz
+http://prdownloads.sourceforge.net/netpbm/netpbm-10.19.tgz
+http://prdownloads.sourceforge.net/png-mng/libpng-1.2.5.tar.bz2
+http://prdownloads.sourceforge.net/romfs/genromfs-0.5.1.tar.gz
+http://prdownloads.sourceforge.net/strace/strace-4.5.8.tar.bz2
+http://prdownloads.sourceforge.net/xine/xine-lib-1-rc8.tar.gz
+http://prdownloads.sourceforge.net/xine/xine-ui-0.99.3.tar.gz
+http://www.perl.com/CPAN/authors/id/M/MS/MSERGEANT/XML-Parser-2.34.tar.gz
+http://www.perl.com/CPAN/authors/id/T/TS/TSCH/ExtUtils-Depends-0.204.tar.gz
+http://www.perl.com/CPAN/authors/id/T/TS/TSCH/ExtUtils-PkgConfig-1.06.tar.gz
+http://subversion.tigris.org/tarballs/subversion-1.0.1.tar.bz2
+http://tug.ctan.org/tex-archive/systems/unix/teTeX/current/distrib/tetex-src-2.0.2.tar.gz
+http://www.alsa-project.org/alsa/ftp/lib/alsa-lib-1.0.3a.tar.bz2
+http://www.alsa-project.org/alsa/ftp/tools/alsa-tools-1.0.3.tar.bz2
+http://www.alsa-project.org/alsa/ftp/utils/alsa-utils-1.0.3.tar.bz2
+http://www.apache.org/dist/httpd/httpd-2.0.52.tar.gz
+http://www.cs.purdue.edu/homes/trinkle/RCS/rcs-5.7.tar.Z
+http://www.docbook.org/xml/4.3/docbook-xml-4.3.zip
+http://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2.0.tar.gz
+http://www.greenwoodsoftware.com/less/less-381.tar.gz
+http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc6.2.tar.gz
+http://www.libsdl.org/release/SDL-1.2.8.tar.gz
+http://www.mirrorservice.org/sites/ftp.gimp.org/pub/gimp/v2.2/
+http://www.procmail.org/procmail-3.22.tar.gz
+http://www.python.org/ftp/python/2.3.3/Python-2.3.3.tar.bz2
+http://www.tug.org/ftp/dist/db-4.3.27.tar.gz
+http://www.vorbis.com/files/1.0.1/unix/libogg-1.1.tar.gz
+http://www.vorbis.com/files/1.0.1/unix/libvorbis-1.0.1.tar.gz
+http://www.xiph.org/paranoia/download/cdparanoia-III-alpha9.8.src.tgz
+http://www.xmms.org/files/1.2.x/xmms-1.2.10.tar.bz2
+END
+EOF
+
+  cat > "$namedir/wget/download/command" << "EOF"
+#!/bin/sh -ex
+version="1.9.1"
+url="http://ftp.gnu.org/gnu/wget/wget-$version.tar.gz"
+dir="mnt/toast/pkg/wget/v$version/archive"
+mkdir -p "$dir"
+cd "$dir"
+echo "$url" > ../url
+wget "$url"
+EOF
+  ln -sf . "$namedir/wget/download/precondition"
+
+  cat > "$namedir/glibc/download/command" << "EOF"
+#!/bin/sh -ex
+dir="mnt/toast/pkg/glibc/v2.3.3/archive"
+mkdir -p "$dir"
+cd "$dir"
+cat > ../url << 'ENDURL'
+http://ftp.gnu.org/gnu/glibc/glibc-2.3.3.tar.bz2
+http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.8.1.tar.bz2
+http://toastball.net/toast-linux-tmp/glibc-2.3.3-gcc34-toast.patch
+ENDURL
+for url in `cat ../url`; do wget "$url"; done
+EOF
+
+  # CVS has an https:// URL; don't try to download it until we've rebuilt
+  # wget with openssl
+  ln -sf "../../../name/wget.2/install/time" "$namedir/cvs/download/precondition"
+}
+
+run()
+{
+  act="$1"
+  color_pre="$2"
+  color_skip="$3"
+  color_working="$4"
+  color_ok="$5"
+  color_failed="$6"
+  link="$topdir/current-$act"
+
+  let top="1+$statuslines"
+  let bottom="$LINES-1"
+  [ "TOPDIR" = "." ] || echo -ne "\33[0m\33[$bottom;999H\33[1J\33[$top;${bottom}r\33[$top;1H"
+
+  echo "preparing to $act"
+
+  done_estimated="0"
+  done_actual="0"
+  remaining_estimated="0"
+
+  for i in `echo $numdir/*/$act/estimate`; do
+    let remaining_estimated="$remaining_estimated+`cat $i`"
+  done
+
+  for dir in `echo $numdir/*`; do
+    adir="$dir/$act"
+    name="`cat $dir/name`"
+    estimate="`cat $adir/estimate`"
+    cmd="$adir/command"
+    failed=""
+
+    precond="$adir/precondition"
+    if [ ! -r "$precond" ]; then
+      echo -n "waiting to $act $name... "
+      while [ ! -r "$precond" -a ! -r "$ffile" ]; do sleep 1; done
+      echo "done waiting"
+      [ -r "$ffile" ] && break
+    fi
+
+    if [ -r "$adir/skip" ]; then
+      echo "unable to $act $name"
+      refresh "$dir" "$color_skip" "$color_ok"
+      end="`date +'%s'`"
+    else
+      start="`date +'%s'`"
+      echo "$act $name"
+      echo "$start" > "$adir/start"
+      if [ "$done_estimated" -gt "0" ]; then
+        let aeta="$start+($estimate*$done_actual/$done_estimated)"
+        echo "$aeta" > "$adir/eta"
+      fi
+      ln -s "../../$dir" "$link"
+      refresh "$dir" "$color_working" "$color_pre"
+      : > "$efile"
+
+      "$cmd" || failed="1"
+      end="`date +'%s'`"
+      rm -f "$link"
+      let elapsed="$end-$start"
+      if [ -n "$failed" ]; then
+        refresh "$dir" "$color_failed" "$color_ok"
+        : > "$adir/failed"
+      else
+        refresh "$dir" "$color_ok" "$color_ok"
+        if [ ! -r "$adir/nonrepresentative" ]; then
+          let done_estimated="$done_estimated+$estimate"
+          let done_actual="$done_actual+$elapsed"
+        fi
+      fi
+      echo "$elapsed" > "$adir/time"
+    fi
+
+    let remaining_estimated="$remaining_estimated-$estimate"
+    if [ "$done_estimated" -gt "0" ]; then
+      let eta="$end+($remaining_estimated*$done_actual/$done_estimated)"
+      echo "$eta" > "$topdir/$act-eta.tmp"
+      mv "$topdir/$act-eta.tmp" "$topdir/$act-eta"
+    fi
+    [ -n "$failed" -a -r "$dir/critical" ] && : > "$ffile"
+    : > "$efile"
+
+    [ -r "$ffile" ] && break
+  done
+
+  if [ -r "$ffile" ]; then
+    echo "$act process aborted"
+  else
+    echo "$act process completed"
+  fi
+  : > "$efile"
+}
+
+fkeys()
+{
+  if [ "TOPDIR" = "." ]; then
+    [ "$1" = "1" ] && echo -ne "\33[$LINES;1H\33[0;${color_fkey}m See download.log and install.log for details.\33[K\33[0m\33[H"
+    return 0
+  fi
+
+  echo -ne "\33[$LINES;1H"
+  i=1
+  for label in overview install download shell; do
+    if [ "$i" = "$1" ]; then
+      color="$color_fkey_selected"
+    else
+      color="$color_fkey"
+    fi
+    echo -ne "\33[0;${color}m Alt-F$i $label "
+    let i="$i+1"
+  done
+  echo -ne "\33[0;${color_fkey_eol}m\33[K\33[0m\33[H"
+}
+
+download()
+{
+  fkeys 3
+  run download "$color_pending" "$color_missing" "$color_getting" "$color_stored" "$color_missing"
+}
+
+install()
+{
+  fkeys 2
+  run install "$color_stored" "$color_missing" "$color_building" "$color_done" "$color_broken"
+}
+
+shell()
+{
+  save="`stty -g`"
+  while true; do
+    stty "$save"
+    echo -ne '\33c'
+    help
+    sh --login
+  done
+}
+
+hms()
+{
+  eval "n=\"\$$1\""
+  if [ -z "$n" ]; then
+    hms="?:??:??"
+  elif [ "$n" -le "0" ]; then
+    hms="0:00:00"
+  else
+    let h="$n/3600"
+    let m="$n/60%60"
+    let s="$n%60"
+    hms="`printf '%d:%02d:%02d' $h $m $s`"
+  fi
+  eval "${1}_hms=\"\$hms\""
+}
+
+bar()
+{
+  let c="$3*2"
+  if [ -z "$1" -o -z "$2" ] || [ "$2" -le 0 ]; then
+    a="0"
+    percent="0"
+  else
+    let percent="$1*100/$2"
+    let a="$1*$c/$2"
+    [ "$a" -gt "$c" ] && a="$c"
+  fi
+  eval "bar=\"\$barcache_${a}_$c\""
+  if [ -z "$bar" ]; then
+    let d="$a/2"
+    let e="$d*2"
+    if [ "$d" = "$e" ]; then
+      let b="$3-$d"
+      h=""
+    else
+      let b="$3-$d-1"
+      h=1
+    fi
+    bar="\33[0;${color_bar}m"
+    [ "$d" -gt 0 ] && for i in `seq 1 $d`; do bar="$bar$char_solid_block"; done
+    [ -n "$h" ] && bar="$bar$char_half_block"
+    [ "$b" -gt 0 ] && for i in `seq 1 $b`; do bar="$bar "; done
+    eval "barcache_${a}_$c=\"\$bar\""
+  fi
+}
+
+status()
+{
+  save="`stty -g`"
+  stty -echo
+  echo -ne '\33[?25l' # hide the cursor
+  echo -ne '\33[9;0]' # disable screen blanking
+
+  if "$1"; then
+    for i in `seq 2 8`; do
+      dev="/dev/vcsa$i"
+      [ -c "$dev" ] || { let minor=128+$i; mknod "$dev" c 7 "$minor"; }
+    done
+    let ddcount="$statuslines*$COLUMNS"
+  fi
+
+  let total="`ls $numdir | wc -l`"
+
+  fkeys 1
+  echo -ne "\33[${statuslines}B"
+
+  overall_start="`date +'%s'`"
+
+  while ! [ -r "$ffile" ]; do
+    : > "$ufile"
+
+    getting_num="`cat $topdir/current-download/num 2>/dev/null`"
+    building_num="`cat $topdir/current-install/num 2>/dev/null`"
+    getting_name="`cat $numdir/$getting_num/name 2>/dev/null`"
+    building_name="`cat $numdir/$building_num/name 2>/dev/null`"
+
+    store_eta="`cat $topdir/download-eta 2>/dev/null`"
+    build_eta="`cat $topdir/install-eta 2>/dev/null`"
+    if [ -z "$store_eta" -o -z "$build_eta" ]; then
+      overall_eta=""
+    elif [ "$store_eta" -gt "$build_eta" ]; then
+      overall_eta="$store_eta"
+    else
+      overall_eta="$build_eta"
+    fi
+
+    let storecount="`ls $numdir/*/download/time 2>/dev/null | wc -l`"
+    let buildcount="`ls $numdir/*/install/time 2>/dev/null | wc -l`"
+    let missing="`ls $numdir/*/download/failed 2>/dev/null | wc -l`"
+    let broken="`ls $numdir/*/install/failed 2>/dev/null | wc -l`"
+    if [ -n "$building_name" ]; then building=1; else building=0; fi
+    if [ -n "$getting_name" ]; then getting=1; else getting=0; fi
+    let pending="$total-$storecount-$getting"
+    let done="$buildcount-$broken"
+    let stored="$storecount-$buildcount-$building-$missing"
+
+    o="\33[H\33[0;${color_stats}m `printf '%-12s' \"$total tasks:\"`"
+    for i in done broken missing stored pending; do
+      eval "color=\"\$color_$i\"; n=\"\$$i\""
+      [ "$n" = "0" ] || o="$o\33[0;${color}m $n $i "
+    done
+    o="$o\33[0;${color_stats}m\33[K\12\12\12\12\12\33[0m"
+
+    echo -ne "$o"
+    cat $numdir/*/display
+
+    while :; do
+      let now="`date +%s`"
+
+      let elapsed="$now-$overall_start"
+      if [ -z "$overall_eta" ]; then
+        remain=""
+        totaltime=""
+      else
+        let remain="$overall_eta-$now"
+        [ "$remain" -lt 1 ] && remain="1"
+        let totaltime="$elapsed+$remain"
+      fi
+      hms elapsed
+      hms remain
+      hms totaltime
+
+      o="\33[2;1H"
+
+      o="$o\33[0;${color_stats}m"
+      if [ -n "$building_num" ]; then
+        let start="`cat $numdir/$building_num/install/start`"
+        let lcur="$now-$start"
+        eta="`cat $numdir/$building_num/install/eta 2>/dev/null`"
+        if [ -n "$eta" ]; then
+          let lmax="$eta-$start"
+        else
+          lmax=""
+        fi
+        hms lcur
+        hms lmax
+        bar "$lcur" "$lmax" 20
+        o="$o\33[0;${color_stats}m installing  \33[0;${color_building}m `printf '%-29.29s%9s%9s%4.4s' $building_name' \33[0;@m' $lcur_hms $lmax_hms $percent | sed -e s/@/$color_stats/`% $bar\33[0;${color_stats}m"
+      fi
+      o="$o\33[K\12"
+      if [ -n "$getting_num" ]; then
+        current="`du -sL $numdir/$getting_num/download/progress 2>/dev/null | cut -f1`"
+        max="`cat $numdir/$getting_num/download/estimate`"
+        bar "$current" "$max" 20
+        let start="`cat $numdir/$getting_num/download/start`"
+        let lcur="$now-$start"
+        eta="`cat $numdir/$getting_num/download/eta 2>/dev/null`"
+        if [ -n "$eta" ]; then
+          let lmax="$eta-$start"
+        elif [ -n "$current" -a -n "$max" -a "$current" -gt 0 ]; then
+          let lmax="$lcur*$max/$current"
+        else
+          lmax=""
+        fi
+        hms lcur
+        hms lmax
+        o="$o\33[0;${color_stats}m downloading \33[0;${color_getting}m `printf '%-29.29s%9s%9s%4.4s' $getting_name' \33[0;@m' $lcur_hms $lmax_hms $percent | sed -e s/@/$color_stats/`% $bar\33[0;${color_stats}m"
+      fi
+      o="$o\33[K\12"
+
+      bar "$elapsed" "$totaltime" "$COLUMNS"
+      o="$o\33[0;${color_stats}m $totaltime_hms estimated total time; $elapsed_hms elapsed; $remain_hms left; $percent% complete\33[K\12$bar\12\33[0m"
+
+      echo -ne "$o"
+
+      if "$1"; then
+        for i in 2 3; do
+          dd if=/dev/vcsa1 of="/dev/vcsa$i" bs=2 count="$ddcount" skip=2 seek=2 2>/dev/null
+        done
+      fi
+
+      [ "$ufile" -nt "$efile" ] || break
+      sleep 3
+      [ "$ufile" -nt "$efile" ] || break
+
+      while [ "$building_name/$getting_name/$pending/$stored" = "//0/0" ]; do
+        sleep 9999999 # done!
+      done
+    done
+  done
+
+  stty "$save"
+  echo -ne '\33[?25h\33[0m\33[999;1H\12'
+
+  if "$1"; then
+    for i in 2 3; do
+      dd if=/dev/zero of="/dev/vcsa$i" bs=2 count="$ddcount" seek=2 2>/dev/null
+    done
+  fi
+  echo
+  echo "Aborting."
+}
+
+abort()
+{
+  trap - sigint
+  : > "$ffile"
+  : > "$efile"
+}
+
+start()
+{
+  cd TOPDIR
+  prepare
+  trap abort sigint
+  if [ "TOPDIR" = "." ]; then
+    download > download.log 2>&1 &
+    install > install.log 2>&1 &
+    status false
+  else
+    openvt 2 "$0" install
+    openvt 3 "$0" download
+    openvt 4 "$0" shell
+    status true
+  fi
+}
+
+help()
+{
+  cat << "EOF"
+Hi!
+
+- Press Alt-F1 to switch back to the installer overview display.
+- The root directory is a RAM disk; use "chroot /mnt" to switch to the
+  toast linux system being installed on the hard disk.  (This will work
+  any time after we install a shell on the hard disk, which happens fairly
+  early on during the "setup" task.)
+- At least until the "toastinit" task finishes, be sure to invoke the
+  "toast" command only from the RAM disk, rather than running it directly
+  from the hard disk, especially if you want to manually build a package;
+  the wrapper script will set some important options and invoke choot
+  automatically.
+- Good luck!
+
+Type "help" (or "exit") to see this message again.
+
+Thanks!
+
+Jacques
+
+EOF
+}
+
+toast()
+{
+  cd TOPDIR
+  if ! [ -r "mnt/etc/toast.conf" ]; then
+    [ -z "$TOAST_NICE" ] && export TOAST_NICE="-5"
+    [ -z "$TOAST_ARMDIR" ] && export TOAST_ARMDIR="/usr"
+    [ -z "$TOAST_POSTARMPROG" ] && export TOAST_POSTARMPROG="postarm || ldconfig"
+    if [ -h "mnt/lib/ld-uClibc.so.0" ]; then
+      export TOAST_PRELOAD="false"
+      export TOAST_POSTARMPROG="true"
+    fi
+  fi
+  exec chroot mnt /bin/toast "$@"
+}
+
+postmortem()
+{
+  cd TOPDIR
+
+  let total=0
+  let count=0
+  for idir in tmp/setup/num/*/install; do
+    if [ -r "$idir/time" -a ! -r "$idir/failed" ]; then
+      let total="$total+`cat $idir/time`"
+      let count="$count+1"
+    fi
+  done
+
+  let i=0
+  while read name size time etc; do
+    let i="$i+1"
+    num="`printf %08d $i`"
+    dir="tmp/setup/num/$num"
+    [ -r "$dir/download/time" -a ! -r "$dir/download/failed" -a "$size" != 0 -a -d "mnt/toast/pkg/$name" ] && let size="12+`du -s mnt/toast/pkg/$name/*/archive | cut -f1`"
+    [ -r "$dir/install/time" -a ! -r "$dir/install/failed" ] && let time="`cat $dir/install/time`*10000*$count/$total"
+    echo "$name $size $time $etc"
+  done > postmortem.out < tmp/tasks
+
+  for dir in tmp/setup/num/*; do
+    if [ -r "$dir/install/time" -a ! -r "$dir/install/failed" ]; then
+      name="`cat $dir/name`"
+      num="`cat $dir/num`"
+      let estimated="`cat $dir/install/estimate`"
+      let actual="`cat $dir/install/time`*10000*$count/$total"
+      if [ "$estimated" -gt "$actual" ]; then
+        let delta="$estimated-$actual"
+      else
+        let delta="$actual-$estimated"
+      fi
+      echo "$delta $num $name $actual"
+    fi
+  done | sort -n | cut -d' ' -f2-
+}
+
+case "$0" in
+  help|*/help) help;;
+  toast|*/toast) toast "$@";;
+  setup|*/setup)
+    case "$1" in
+      download|install|shell|postmortem) trap abort sigint; "$1";;
+      "") start;;
+      *) echo "$0: unrecognized argument: $1" >&2;;
+    esac
+  ;;
+  *) echo "$0: unrecognized name" >&2;;
+esac
+---
+exit 0
+
 #!/usr/bin/perl
-exec $0 "$@"  # rerun under perl if running under sh (e.g. "sh configure")
-    if 0;     # ignore the above line if already running under perl
 
 use 5.006.0;
 use warnings;
@@ -123,7 +1697,7 @@
 
 WGET = wget
 
-FROMCONF = dev toast-linux.stub mkhd bochs-config toast.vmx
+FROMCONF = dev toast-linux.stub mkhd bochs-config toast.vmx sbin/setup
 FROMCONF2 = smartcat linux-config-smallk linux-config-largek busybox-config
 
 PKGS = TOOLCHAIN LINUX BUSYBOX E2FSPROGS NTFSPROGS PARTED DEVMAP LVM2 GENEXT2FS MTOOLS SYSLINUX CDRTOOLS
@@ -240,7 +1814,10 @@
 $(CDRTOOLS_ARCHIVE): ; $(WGET) $(CDRTOOLS_URL)
 
 clean:
-  rm -fr $(PKG_DIRS) symbols floppy* cd* root* toast-linux* $(FROMCONF) $(FROMCONF2) smallk largek
+  [ ! -S mnt/dev/log ] || umount mnt/dev
+  [ ! -d mnt/proc/1 ] || umount mnt/proc
+  [ ! -d mnt/sys/block ] || umount mnt/sys
+  rm -fr $(PKG_DIRS) symbols floppy* cd* root* toast-linux* $(FROMCONF) $(FROMCONF2) smallk largek sbin tmp mnt *.log
 
 vmclean:
   rm -f toast*.vm* toast*.sav nvram* vmware.log
@@ -410,6 +1987,9 @@
 
 toast-linux.1: toast-linux.stub
   pod2man $< > $@
+
+chroot: sbin/setup
+  TOAST_NICE=5 sbin/setup
 
 vmware: floppy.img cd.iso vmclean toast.vmx
   vmware-vdiskmanager -c -a buslogic -s 16gb -t 1 toast.vmdk