#! /bin/sh
# jigdo-easy: highly portable textmode full-screen menu-driven jigdo client
# Copyright 2001-2002 Richard Atterer, J.A. Bezemer
# License: GPL version 2

# NOTE: This code was tested on a multitude of systems, including many ancient
# ones. Be sure to re-test if you make any change, however small it may seem.

# Some defaults

jigdoOpts="--cache jigdo-file-cache.db"
mirrors="mirrors.jigdo"
tmpDir="jigdo-easy-tmp" # is rm -rf'd, DON'T use "." or similar!
tmplistFile="tmplist"
filesPerFetch=10

menuURL="http://cdimage.debian.org/~costar/jigdo/jigdo-easy-2.1/menu.jigdo"
submenu="Main"

if test "${OSTYPE#cygwin}" != "$OSTYPE"; then
    menuURL="http://cdimage.debian.org/~costar/jigdo/jigdo-easy2win-2.1/menu.jigdo"
    rcFile="./jigdo-easy.conf"
    LINES=25
    PATH="$PWD":"$PATH"
else
    rcFile="$HOME/.jigdo-easy"
fi

#______________________________________________________________________

# Compatibility/availability tests

# Check for programs
problem=false

testvar=false; ! $testvar 2>/dev/null \
    || { echo "Your shell does not interpret \`!' (negation) correctly"
	 echo " - please run this script with another shell."
         problem=true; }
testvar='[test]abc'; test "${testvar#\[test\]}" = "abc" \
    || { echo "Your shell does not correctly support advanced variable substitution"
	 echo " - please run this script with another shell."
         problem=true; }
wget --version >/dev/null 2>&1 \
    || { echo "Could not find a working \`wget' - please install it!"
         problem=true; }
test "`echo test | egrep '^(ab|te)' 2>/dev/null`" = "test" \
    || { echo "Could not find a working \`egrep' (or \`test') - please install it!"
         problem=true; }
test "`echo test | sed -e 's/es/tt/' 2>/dev/null`" = "tttt" \
    || { echo "Could not find a working \`sed' - please install it!"
         problem=true; }
test "`printf '%3d %s' 4 az 2>/dev/null`" = '  4 az' \
    || { echo "Could not find a correctly working \`printf' - please compile myprintf.c"
         problem=true; }

# jigdo-file may be in PWD, or maybe we're running from the source tree
ORIGPATH="$PATH"
jigdo-file --version >/dev/null 2>&1 || PATH="$ORIGPATH":"$PWD"
jigdo-file --version >/dev/null 2>&1 || PATH="$ORIGPATH":"`dirname "$0"`"/../src
usejigdoport=false
if ! jigdo-file --version >/dev/null 2>&1; then
    # Maybe jigdo-port is available
    PATH="$ORIGPATH"
    jigdo-port --version >/dev/null 2>&1 || PATH="$ORIGPATH":"$PWD"
    jigdo-port --version >/dev/null 2>&1 || PATH="$ORIGPATH":"`dirname "$0"`"/../src
    jigdo-port --version >/dev/null 2>&1 || PATH="$ORIGPATH":"`dirname "$0"`"/../jigdo-port
    jigdo-port --version >/dev/null 2>&1 || PATH="$ORIGPATH":"`dirname "$0"`"/jigdo-port
    if jigdo-port --version >/dev/null 2>&1; then
	# Okay, found
	usejigdoport=true
	jigdo_file() { jigdo-port "$@"; }
    else
        echo "Could not find both jigdo-file and jigdo-port - please install either!"
	problem=true
    fi
else
    jigdo_file() { jigdo-file "$@"; }
fi

# See if gzip is available, otherwise search for minigzip from zlib
ORIGPATH="$PATH"
if ! gzip --version >/dev/null 2>&1; then
    test "`echo test | minigzip -d 2>/dev/null`" = "test" || PATH="$ORIGPATH":"$PWD"
    test "`echo test | minigzip -d 2>/dev/null`" = "test" || PATH="$ORIGPATH":"$PWD"/zlib-1.1.3
    test "`echo test | minigzip -d 2>/dev/null`" = "test" || PATH="$ORIGPATH":"`dirname "$0"`"
    test "`echo test | minigzip -d 2>/dev/null`" = "test" || PATH="$ORIGPATH":"`dirname "$0"`"/zlib-1.1.3
    if test "`echo test | minigzip -d 2>/dev/null`" = "test"; then
	# Okay, found
	gzip() { minigzip "$@"; }
    else
        echo "Could not find both gzip and minigzip - please install either!"
	problem=true
    fi
fi

$problem && echo "" && exit 1

#______________________________________________________________________

# trust stty (if it works) more than $LINES (if available)
linesonscreen="`stty -a | sed -n -e 's/^.*rows[^0-9]*\([0-9]*\).*$/\1/p'`"
! echo "$linesonscreen" | egrep '^[0-9][0-9]*$' >/dev/null \
    && linesonscreen="$LINES"
! echo "$linesonscreen" | egrep '^[0-9][0-9]*$' >/dev/null \
    && linesonscreen=24
#______________________________________________________________________

# read with readline, only if running bash >=2.03 (-e gives error on POSIX)
if test "${BASH_VERSION#[2-9].}" != "$BASH_VERSION"; then
    if test "${BASH_VERSION#2.0[012]}" = "$BASH_VERSION"; then
        read() { builtin read -e "$@"; }
    fi
fi
#______________________________________________________________________

# Check for existing true/false, workaround if necessary (may even be faster)
#true 2>/dev/null || { true() { return 0; } ; false() { return 1; } ; }
# Commented out because HP-UX posix-sh won't parse () after reserved words.
#______________________________________________________________________

# If IFS not set, set it to default (otherwise OLDIFS problems below)
test "$IFS" || IFS="`echo ' 	'`"    # space, tab (enter by echo)
#______________________________________________________________________

# zsh <3.1.3 has broken set -- "$@" handling (changelog 6 Jan 98) so only
# fetchAndMerge a single file there. ZSH_VERSION is defined since at least
# Oct 1994, or zsh 2.6; earlier versions (also?) used VERSION='zsh v2.3.0'
if test "${ZSH_VERSION#[0123].}" != "$ZSH_VERSION"; then
    if test "${ZSH_VERSION#[012].}" != "$ZSH_VERSION"; then
        filesPerFetch=1
    fi
    if test "${ZSH_VERSION#3.0.}" != "$ZSH_VERSION"; then
        filesPerFetch=1
    fi
    if test "${ZSH_VERSION#3.1.[012]}" != "$ZSH_VERSION"; then
        filesPerFetch=1
    fi
fi
if test "${VERSION#zsh}" != "$VERSION"; then
    filesPerFetch=1
fi
#______________________________________________________________________

# poor substitute for non-POSIX fmt (fmt is tape tool on HPUX...)
if test "`echo test | fmt -c -w97 2>/dev/null`" != "test" ; then
    # and SunOS <=4 doesn't do fold -s
    if test "`echo test | fold -s`" = "test" ; then
        fmt() {
	    { if test "$1" = "-c"; then
	        tr '\012' ' '; echo ""      # \012 is portable for \n
	    else
	        cat
	    fi
	    } | sed -e 's/   */ /g' | fold -s
        }
    else
        fmt() {
	    { if test "$1" = "-c"; then
	        tr '\012' ' '; echo ""      # \012 is portable for \n
	    else
	        cat
	    fi
	    } | sed -e 's/   */ /g' | fold
        }
    fi
fi
#______________________________________________________________________

# isURI <string>
# Returns 0 (true) if the supplied string is a HTTP/FTP URL, otherwise 1
isURI() {
    case "$1" in
        http:*|ftp:*|HTTP:*|FTP:*|file:*|FILE:*) return 0;;
        *) return 1;
    esac
}
#______________________________________________________________________

# fetch <URL>...
# Download one or more files, storing them in the current dir
fetch() {
    if test "$#" -eq 0; then return 0; fi
    wget --user-agent="jigdo-easy/2.1 ($wgetVersion)" \
         --no-directories --timestamping "$@" || return 1
    # (older?) wget is buggy, will --continue even if newer (--timestamping)
}
wgetVersion=`wget --version 2>/dev/null | (read ver; echo $ver)`
#______________________________________________________________________

# Given URLs, fetch them into $tmpDir, then merge them into image
fetchAndMerge() {
    (mkdir "$tmpDir"; cd "$tmpDir"
     wget --user-agent="jigdo-easy/2.1 ($wgetVersion)" \
          --no-directories --no-parent "$@")
    # wget: if downloading two different "linux"-es in one run,
    # we want them separate, not --continue'd or --timestamping'd;
    # dummy option --no-parent to keep same minimal argcount for
    # wget-replacing function (Sun/IRIX).
    # Merge into the image
    if ! $usejigdoport; then
	jigdo_file $jigdoOpts make-image $ijtOpts "$tmpDir"
    else
	jigdo_file $jigdoOpts make-image $ijtOpts "$tmpDir"/*
    fi
    jigdoErr="$?"
    if test "$jigdoErr" -ge 2; then
        echo ""
        echo "jigdo-file failed with code $jigdoErr - aborting."
        echo ""
        exit 1
    fi
    # Delete tmpDir, to avoid taking up more space than necessary
    rm -rf "$tmpDir"
}
#______________________________________________________________________

# Prompt user to input value, assign result to $REPLY. If user just
# presses Return, assign supplied default value instead.
# input <prompt string> <default value>
input() {
    prompt=""
    if test "$2"; then prompt=" [$2]"; fi
    printf "%s%s: " "$1" "$prompt"
    read REPLY
    if test -z "$REPLY"; then REPLY="$2"; fi
}
#______________________________________________________________________

# getEntry <section> <label>
# Reads a jigdo file from $jigdo and outputs value of first matching entry
getEntry() {
    insection=false
    egrep '^[ 	]*([[]|'"$2"'[ 	]*=)' < "$jigdo" \
    | while read inp; do
	if test "${inp#\[}" != "$inp"; then insection=false; fi
	if test "${inp#\[$1\]}" != "$inp"; then
	    insection=true
	elif $insection; then
            label="${inp%%=*}"; label="${label%% *}"; label="${label%%	*}" # space, tab
	    if test "$label" = "$2"; then
            	echo "`echo "$inp" | sed -e 's/^[^=]*=//; s/^[ 	]*//'`"  # id.
		break
	    fi
	fi
    done
}
#______________________________________________________________________

# Output a horizontal rule
hrule() {
    clear
    echo ' Jigsaw Download "Easy"  Copyright (C) 2001-2002 R. Atterer, J.A. Bezemer  GPL2'
    echo ""
    if test "$image"; then
	echo "File : $image"
	echo "Label: $shortinfo"
	echo "Info : $longinfo" | fmt -s
	echo ""
    fi
}
#______________________________________________________________________

# Download template, unless already downloaded/checked-for-currentness
# in this session
fetchTemplate() {
    if $fetchedTemplate; then return 0; fi
    echo 'Downloading .template file, one moment please...'
    echo ""
    fetch "$templateURI"
    # Does template exist now?
    if test ! -r "$template"; then
        echo ""
        echo "Error: could not fetch \`$template'"
        echo ""
        echo "Note: This may happen when the automatic random server selection has"
        echo "selected a server that is not available at this moment. Please try"
        echo "again in a few minutes. Thanks for your patience."
        echo ""
        exit 1
    fi
}
fetchedTemplate=false
#______________________________________________________________________

# Write $rcFile
saveoptions() {
    printf "jigdo='%s'\ndebianMirror='%s'\nnonusMirror='%s'\n" \
        "$jigdo" "$debianMirror" "$nonusMirror" >"$rcFile"
}
#______________________________________________________________________

# Get list from $tmplistFile, print it, read input (number or text) to $REPLY.
# listinput <lines-on-screen> <startline> <prompt> <defaultval>
# <startline> is 1-based.
# Parameters $3 and further are actually passed to input(), above.
listinput() {
    lines="$1"
    startline="$2"
    shift; shift
    { {
        num=1
        while read inp; do
            printf "%3d.\n      %s" "$num" "$inp" | fmt -c -w79
	    num=$(($num+1))
        done < "$tmplistFile"
        echo ""
    } | {
	line="$startline"   # = where this line is going to be printed
	OLDIFS="$IFS"
	IFS=""
	while read inp; do
	    if test "$line" -ge "$lines"; then
	        printf "[Enter]"
		read REPLY 0<&3 >/dev/null 2>/dev/null
	        printf "\r       \r"
	        line=1
	    fi
	    echo "$inp"
	    line="$(($line+1))"
	done
	IFS="$OLDIFS"
    }; } 3<&0

    input "$@"
    # Handle numbers
    if test "$REPLY" && test -z "`echo "$REPLY" | sed -e 's/[0-9]//g'`"; then
        # Avoid head and tail when we can easily do it ourselves.
	num=1
	while read inp; do
	    test "$num" -eq "$REPLY" && REPLY="$inp" && break
	    num=$(($num+1))
	done < "$tmplistFile"
    fi  
}

#______________________________________________________________________

# "Main"

hrule

# Load preferences file, if present
if test -r "$rcFile"; then
#    echo "Loading settings from \`$rcFile'"
    . "$rcFile"
fi

# No cmd line argument, then show menu.
# Ignore the (possibly) saved setting, which works very confusing
# in the new menu system.

# If commandline argument, assume jigdo (+ subimage number)...
jigdo="$1"
subimage=1
test "$2" && subimage="$2"

# ...unless it's a menu
if echo "$1" | egrep '/menu.jigdo' >/dev/null 2>&1; then
    menuURL="${jigdo%%\|*}"
    submenu="${jigdo#*\|}"
    { test -z "$submenu" || test "$submenu" = "$jigdo"; } && submenu="Main"
    jigdo=""
    set --
fi

mirrorsfetched=false

oldmenuURL=""
firstmenu=true

while test -z "$jigdo"; do
    # Get menu file
    if test "$menuURL" != "$oldmenuURL"; then
	rm -f menu.jigdo   # defy --timestamping
        hrule
        echo "CD IMAGE SELECTION"
        echo "------------------"
        echo ""
        echo "Fetching menu..."
        echo ""
	fetch "$menuURL"
	if test ! -r menu.jigdo; then
	    echo ""
	    echo "Error: could not fetch the menu."
            echo ""
	    echo "Note: This may happen when the menu server has to serve many many"
	    echo "users at the same time. Please try again in a few minutes. Thanks"
	    echo "for your patience."
            echo ""
	    exit 1
	fi

	# Try to decompress
	rm -f menu.jigdo.unpacked
	if gzip -d < menu.jigdo > menu.jigdo.unpacked 2>/dev/null; then
	    rm -f menu.jigdo
	    mv menu.jigdo.unpacked menu.jigdo
	else
	    rm -f menu.jigdo.unpacked
	fi

	oldmenuURL="$menuURL"
    fi

    hrule
    echo "CD IMAGE SELECTION"
    echo "------------------"
    echo ""
    firstmenuline=6
    if $firstmenu; then
        echo "Use the menu below to specify which CD image you want to download."
	echo "Alternatively, enter a .jigdo URL or the name of a local .jigdo file directly."
        echo "To resume a half-finished download, simply specify the same image."
	echo ""
	firstmenu=false
	firstmenuline=10
    fi

    rm -f "$tmplistFile"
    inmenu=false
    newmenu=false
    jigdofound=false
    titleprinted=false
    defaultopt=""

    mirrorsURL=""
    overridetemplateURL=""
    subimage=1
    subigrep=""
    REPLY=""

    while read inp; do
	if $inmenu; then
	    if test "${inp#\[}" != "$inp"; then break; fi
            label="${inp%%=*}"; label="${label%% *}"; label="${label%%	*}" # space, tab
            value="`echo "$inp" | sed -e 's/^[^=]*=//; s/^[ 	]*//'`"  # id.
	    case "$label" in
		"Title") echo "$value"; firstmenuline="$(($firstmenuline+1))"
			 titleprinted=true;;
		"Option") echo "$value" >> "$tmplistFile";;
		"Default") defaultopt="$value";;

		"Menu") REPLY="$value"; newmenu=true; break;;

		"Mirrors") mirrorsURL="$value";;
		"Template") overridetemplateURL="$value";;
		"SubImage") subimage="$value";; # numeric; overriden by SubIGrep
		"SubIGrep") subigrep="$value";; # egrep pattern, full-line match
		"Jigdo") REPLY="$value"; jigdofound=true; break;; # note: break!
	    esac
	fi
	if test "${inp#\[Menu:$submenu\]}" != "$inp"; then
	    inmenu=true
	fi
    done < menu.jigdo

    if ! $inmenu; then
	REPLY="$1"; shift
	newmenu=true
	if test -z "$REPLY"; then
	    echo ""
	    echo "Error in menu $menuURL: $submenu not found."
            echo ""
	    exit 1
	fi
    fi

    if ! $newmenu && ! $jigdofound; then
        # Remember this menu for Back function
        set -- "$menuURL|$submenu" "$@"
	test "$#" -gt 1 && echo "Back" >> "$tmplistFile"
	if $titleprinted; then
	    echo ""
	    firstmenuline="$(($firstmenuline+1))"
	fi
	listinput "$linesonscreen" "$firstmenuline" "Choice/.jigdo" "$defaultopt"
	if test "$REPLY" = "q" || test "$REPLY" = "quit" || test "$REPLY" = "exit" \
	    || test "$REPLY" = "Quit" || test "$REPLY" = "Exit"; then exit
	elif test "$REPLY" = "Back" || test "$REPLY" = "back"; then
	    shift; REPLY="$1"; shift
	    newmenu=true
	elif isURI "$REPLY"; then
	    if echo "$REPLY" | egrep '/menu.jigdo' >/dev/null; then newmenu=true
	    elif test "${REPLY%.jigdo}" != "$REPLY"; then jigdofound=true
	    else
		# default to .jigdo, even if different extension
		jigdofound=true;
	    fi
	elif test -r "$REPLY"; then jigdofound=true
	fi
    fi

    if $jigdofound; then
	jigdo="$REPLY"
    elif $newmenu; then
	menuURL="${REPLY%%\|*}"
	submenu="${REPLY#*\|}"
	{ test -z "$submenu" || test "$submenu" = "$REPLY"; } && submenu="Main"
    else
	submenu="$REPLY"
    fi
done
rm -f menu.jigdo

# Jigdo can be either URL or filename. Maybe download file
if isURI "$jigdo"; then
    hrule
    echo "CD IMAGE SELECTION"
    echo "------------------"
    echo ""
    echo "Downloading .jigdo file, one moment please..."
    echo ""
    if ! fetch "$jigdo"; then
        # Old jigdo might still exist, but we should abort if it couldn't
        # be timestamp-checked.
        echo ""
        echo "Error: could not download \`$jigdo'"
        echo ""
        echo "Note: This may happen when the automatic random server selection has"
        echo "selected a server that is not available at this moment. Please try"
        echo "again in a few minutes. Thanks for your patience."
        echo ""
        exit 1
    fi
    jigdo=`basename "$jigdo"`
fi
# Does jigdo exist now?
if test ! -r "$jigdo"; then
    echo ""
    echo "Error: file \`$jigdo' does not exist!"
    echo ""
    exit 1
fi

# Try to decompress it. In case of error, assume that it wasn't compressed
rm -f "$jigdo".unpacked
if gzip -d < "$jigdo" > "$jigdo".unpacked 2>/dev/null; then
    rm -f "$jigdo"
    jigdo="$jigdo".unpacked
else
    rm -f "$jigdo".unpacked
fi

hrule
echo "WORKING"
echo "-------"
echo ""

# Get subimage info (based on getEntry, which isn't used any more)
subcounter=0
found=false
insection=false

# Don't do this in a pipe=subshell since we're setting global vars
rm -f "$jigdo".temp
egrep '^[ 	]*([[]|(Filename|Template|ShortInfo|Info)[ 	]*=)' \
  < "$jigdo" > "$jigdo".temp

while read inp; do
    if test "${inp#\[}" != "$inp"; then
        insection=false
        if $found; then break; fi
    fi
    if test "${inp#\[Image\]}" != "$inp"; then
	printf '.'
    	insection=true
	image=""
	templateURI=""
	shortinfo=""
	longinfo=""
	subcounter="$(($subcounter+1))"
	! test "$subigrep" && test "$subcounter" -eq "$subimage" && found=true
    elif $insection; then
	if test "$subigrep"; then
	    echo "$inp" | egrep "$subigrep" >/dev/null 2>&1 && found=true
	fi
        label="${inp%%=*}"; label="${label%% *}"; label="${label%%	*}" # space, tab
	value="`echo "$inp" | sed -e 's/^[^=]*=//; s/^[ 	]*//'`"  # id.
	test "$label" = "Filename" && image="$value"
	test "$label" = "Template" && templateURI="$value"
	test "$label" = "ShortInfo" && shortinfo="$value"
	test "$label" = "Info" && longinfo="$value"
    fi
done < "$jigdo".temp

rm -f "$jigdo".temp

test "$overridetemplateURL" && templateURI="$overridetemplateURL"

template=`basename "$templateURI"`
list="$image.list"
echo ""

# switches to pass to jigdo-file, specifying the image, jigdo and template
ijtOpts="--image=$image --jigdo=$jigdo --template=$template"

ready=false

# Ask user for any parts on local filesystems
while ! $ready; do
    hrule
    echo "LOCAL FILES"
    echo "-----------"
    echo ""
    echo "If you already have a previous version of the image you are"
    echo "downloading, jigdo can re-use files on the old image that are also"
    echo "present on the new image, and you do not need to download them"
    if test "${OSTYPE#cygwin}" != "$OSTYPE"; then
	echo "again. If you have an older but similar CD, insert it in the CD-ROM"
	echo "drive, and enter \`D:\\' (assuming the drive is D:). When done, this"
	echo "question will appear again to let you re-use even more. To stop re-using"
	echo "and proceed to the downloading of any remaining files, press Enter."
	echo "Note: do NOT use this option if you have a local Debian FTP mirror,"
	echo "that's the next question."
	echo ""
	echo "If you've never used Debian before, just press Enter."
	echo ""
	printf "Files/directories to scan: "
	read -r files
    else
	echo "again. If you have an older but similar CD, mount it in and enter"
	echo "the path to it, for example \`/mnt/cdrom'. When done, this question"
	echo "will appear again to let you re-use even more. To stop re-using and"
	echo "proceed to the downloading of any remaining files, press Enter."
	echo "Note: do NOT use this option if you have a local Debian FTP mirror,"
	echo "that's the next question."
	echo ""
	echo "If you've never used Debian before, just press Enter."
	echo ""
	printf "Files/directories to scan: "
	read files
    fi
    if test -z "$files"; then break; fi

    hrule
    echo "FETCHING TEMPLATE"
    echo "-----------------"
    echo ""

    fetchTemplate
    fetchedTemplate=true

    hrule
    echo "CONSTRUCTING IMAGE"
    echo "------------------"
    echo ""

    if ! $usejigdoport; then
	jigdo_file $jigdoOpts make-image $ijtOpts $files
    else
        find $files -type f -print \
          | jigdo_file $jigdoOpts make-image $ijtOpts --files-from=-
    fi
    jigdoErr="$?"
    if test "$jigdoErr" -eq 0; then
	# All files were present on local filesystem
	ready=true
    elif test  "$jigdoErr" -ge 2; then
        echo ""
        echo "jigdo-file failed with code $jigdoErr - aborting."
        echo ""
        exit 1
    fi
done

# Deal with left-over tmpdir from previous, interrupted download
if ! $ready && test -r "$tmpDir"; then
    hrule
    echo "WARNING"
    echo "-------"
    echo ""
    echo "The temporary directory \`$tmpDir' already exists. It was probably created"
    echo "during a previous jigdo-easy run, but you may also have created it"
    echo "yourself. Its contents ARE GOING TO BE DELETED (possibly after having"
    echo "been copied to the image, if they are of interest for it). If you do"
    echo "not want this to happen, press Ctrl-C now. Otherwise, press Enter to"
    echo "proceed."
    echo ""
    printf '> '
    read REPLY
fi

# Crude check for whether any entry in the [Parts] section uses a
# "Debian" or "Non-US" label. If yes, start Debian mirror selection
# below.
usesDebian=false
if egrep -l '^[^=]+= *["'\'']?Debian:' "$jigdo" >/dev/null; then
    usesDebian=true
fi
usesNonus=false
if egrep -l '^[^=]+= *["'\'']?Non-US:' "$jigdo" >/dev/null; then
    usesNonus=true
fi

# Download files and merge them into the image. We instruct wget to
# download 10 files at a time and then merge them. This way, compared
# to downloading everything, the peak disc space usage is not twice
# the size of the final image.
while ! $ready; do

    # Extra options to pass to jigdo-file for server selection
    uriOpts=""

    if $usesDebian; then
        hrule
        echo "DEBIAN MIRROR"
        echo "-------------"
        echo ""
        echo "The jigdo file refers to files stored on Debian mirrors. Please"
        echo "choose a Debian mirror as follows:"
        echo ""
	echo "- Local mirror, in the form \`file:/opt/mirrors/debian/', or"
        echo ""
	echo "- Complete URL, in the form \`ftp://ftp.debian.org/debian/', or"
        echo ""
	echo "- Search term to search through the list of mirrors (regexp), for"
        echo "  example \`de' (country code for Germany) or \`United States'"
        echo "  or \`sunsite'. Use \`.' to get a list of all mirrors."
        echo ""
        input "Debian mirror/search" "$debianMirror"
	if ! isURI "$REPLY"; then
	    if ! $mirrorsfetched && test "$mirrorsURL"; then
		mirrorsfetched=true
		rm -f "$mirrors"   # defy --timestamping
		hrule
		echo "DEBIAN MIRROR"
		echo "-------------"
		echo ""
		echo "Downloading mirrors list, one moment please..."
		echo ""
		if ! fetch "$mirrorsURL"; then
	            echo ""
	            echo "Error: could not fetch the mirrors list"
        	    echo ""
	            echo "Note: This may happen when the automatic random server selection has"
	            echo "selected a server that is not available at this moment. Please try"
	            echo "again in a few minutes. Thanks for your patience."
	            echo ""
	            exit 1
		fi

		# Try to decompress
		rm -f "$mirrors".unpacked
		if gzip -d < "$mirrors" > "$mirrors".unpacked 2>/dev/null; then
		    rm -f "$mirrors"
		    mv "$mirrors".unpacked "$mirrors"
		else
		    rm -f "$mirrors".unpacked
		fi
	    fi
	    while true; do
                # Special-case two-letter country codes
                case "$REPLY" in [a-z][a-z]) REPLY="[. ]$REPLY[/. ]";; esac
                egrep -i "$REPLY" "$mirrors" | sed -n -e 's/^Debian=//p' \
		    > "$tmplistFile"
                hrule
                echo "DEBIAN MIRROR"
                echo "-------------"
                echo ""
                echo "Known mirrors matching your search term:"
                echo ""
	        listinput "$linesonscreen" 12 "Debian mirror/search" "$debianMirror"
		REPLY="${REPLY%% *}"  # keep only URL
                if isURI "$REPLY"; then
		    break;
                fi
            done
	fi
        # Turn any "file:/opt/mirror" into "file:/opt/mirror/"
        debianMirror=`echo $REPLY | sed -e 's%^\(.*[^/]\)$%\1/%'`
        saveoptions
        uriOpts="--uri Debian='$debianMirror'"
    fi

    if $usesNonus; then
        hrule
        echo "NON-US MIRROR"
        echo "-------------"
	echo ""
        echo "The jigdo file also refers to files stored on Debian's separate Non-US"
	echo "mirrors. Please choose such a mirror as follows:"
        echo ""
	echo "- Local mirror, in the form \`file:/opt/mirrors/debian-non-US/', or"
        echo ""
	echo "- Complete URL, in the form \`ftp://non-us.debian.org/debian-non-US/', or"
        echo ""
	echo "- Search term to search through the list of mirrors (regexp), for"
        echo "  example \`de' (country code for Germany) or \`Finland' or \`sunsite'."
	echo "  Use \`.' to get a list of all mirrors."
        echo ""
        input "Non-US mirror/search" "$nonusMirror"
	if ! isURI "$REPLY"; then
	    if ! $mirrorsfetched && test "$mirrorsURL"; then
		mirrorsfetched=true
		rm -f "$mirrors"   # defy --timestamping
		hrule
		echo "NON-US MIRROR"
		echo "-------------"
		echo ""
		echo "Downloading mirrors list, one moment please..."
		echo ""
		if ! fetch "$mirrorsURL"; then
	            echo ""
	            echo "Error: could not fetch the mirrors list"
        	    echo ""
	            echo "Note: This may happen when the automatic random server selection has"
	            echo "selected a server that is not available at this moment. Please try"
	            echo "again in a few minutes. Thanks for your patience."
	            echo ""
	            exit 1
		fi

		# Try to decompress
		rm -f "$mirrors".unpacked
		if gzip -d < "$mirrors" > "$mirrors".unpacked 2>/dev/null; then
		    rm -f "$mirrors"
		    mv "$mirrors".unpacked "$mirrors"
		else
		    rm -f "$mirrors".unpacked
		fi
	    fi
	    while true; do
                # Special-case two-letter country codes
                case "$REPLY" in [a-z][a-z]) REPLY="[. ]$REPLY[/. ]";; esac
                egrep -i "$REPLY" "$mirrors" | sed -n -e 's/^Non-US=//p' \
		    > "$tmplistFile"
                hrule
                echo "NON-US MIRROR"
                echo "-------------"
                echo ""
                echo "Known mirrors matching your search term:"
                echo ""
	        listinput "$linesonscreen" 12 "Non-US mirror/search" "$nonusMirror"
		REPLY="${REPLY%% *}"  # keep only URL
                if isURI "$REPLY"; then
		    break;
                fi
            done
	fi
        # Turn any "file:/opt/mirror" into "file:/opt/mirror/"
        nonusMirror=`echo $REPLY | sed -e 's%^\(.*[^/]\)$%\1/%'`
        saveoptions
        uriOpts="$uriOpts --uri Non-US='$nonusMirror'";
    fi

    hrule
    echo "FETCHING TEMPLATE"
    echo "-----------------"
    echo ""

    fetchTemplate
    fetchedTemplate=true

    hrule
    echo "CONSTRUCTING IMAGE"
    echo "------------------"
    echo ""

    # Output list of missing files
    jigdo_file $jigdoOpts print-missing $ijtOpts $uriOpts >"$list"
    jigdoErr="$?"
    if test "$jigdoErr" -ge 2; then
        echo ""
        echo "jigdo-file failed with code $jigdoErr - aborting."
        echo ""
        exit 1
    fi
    echo "Created \`$list'"

    # If a "file:" URI was given instead of a server URL, try to merge
    # any files into the image.
    echo "Merging parts from \`file:' URIs, if any..."
    egrep -v '^(http|HTTP|ftp|FTP):' <"$list" \
    | jigdo_file $jigdoOpts make-image $ijtOpts --files-from=-
    jigdoErr="$?"
    if test "$jigdoErr" -ge 2; then
        echo ""
        echo "jigdo-file failed with code $jigdoErr - aborting."
        echo ""
        exit 1
    fi

    # Try to download and merge any remaining URIs in list
    set --
    egrep '^(http|HTTP|ftp|FTP):' <"$list" \
    | while true; do
        if read uri; then
            # Download and merge $filesPerFetch parts at a time
            set -- "$@" "$uri"
            if test "$#" -ge "$filesPerFetch"; then
                fetchAndMerge "$@"
                set --
            fi
        else
            # End of list reached - download and merge remaining parts
            if test "$#" -gt 0; then fetchAndMerge "$@"; fi
            break
        fi
    done

    if test -r "$image"; then break; fi

    hrule
    echo "PROBLEM"
    echo "-------"
    echo ""
    echo "Oops - not all files could be downloaded..."
    echo ""
    echo "Depending on the situation, it may help to just restart the download."
    if $usesDebian || $usesNonus; then
    echo "Also, you could try changing to another Debian or Non-US server, in"
    echo "case the one you used was not updated recently."
    fi
    echo ""
    echo "On the other hand, it may also be that some required files have"
    echo "disappeared. If the image is still available on an rsync server, you"
    echo "can try to complete it that way. For another option, read the README."
    echo ""
    echo "If you want to restart, press Enter; otherwise press Ctrl-C or close"
    echo "this window (if running in one)."
    echo ""
    printf '> '
    read REPLY

done


hrule
echo "FINISHED!"
echo "---------"
echo ""
echo "The fact that you got this far is a strong indication that the"
echo "image was generated correctly. I will perform an additional, final"
echo "check, which you can interrupt safely with Ctrl-C if you do not want"
echo "to wait."
echo ""
rm -f "$list" "$tmplistFile" "$mirrors"
jigdo_file $jigdoOpts verify $ijtOpts
rm -f "$template" "$jigdo"
echo ""
