Minor tweaks to jigdo-lite for the windows 0.8.0a release
[jigdo.git] / scripts / jigdo-lite
1 #! /bin/sh
2 # Poor man's jigdo - download and assemble Jigsaw Download files
3 # Copyright 2001-2009 Richard Atterer
4 # Copyright 2016-2021 Steve McIntyre
5 # Portability improvements by J.A. Bezemer, Jan 2002
6 # License: GPL version 2
7
8 # These 4 variables can be overridden in ~/.jigdo-lite if necessary:
9 jigdoOpts="--cache jigdo-file-cache.db"
10 wgetOpts="-nv --passive-ftp --dot-style=mega --continue --timeout=30"
11 mirrors="mirrors.jigdo"
12 tmpDir="."
13
14 filesPerFetch=30
15 maxMissing=30 # Don't try fallback servers if x% or more of files missing
16 rcFile="$HOME/.jigdo-lite"
17
18 unset GREP_OPTIONS
19
20 if test "x$OSTYPE" = "xmsys"; then
21   windows=true
22   OSTYPE=Windows
23   mirrors="jigdo-bin/mirrors.jigdo"
24   rcFile="./jigdo-lite-settings.txt"
25   egrep() { grep -E "$@"; }
26   expr() { echo "$(($@))"; }
27   filesPerFetch=30 # What's the command line length limit?
28   nl='\r\n'
29 else
30   windows=false
31   nl='\n'
32 fi
33 #______________________________________________________________________
34
35 # read with readline, only if running bash >=2.03 (-e gives error on POSIX)
36 readLine="read"
37 if test "x$BASH_VERSION" != "x"; then
38   if test "x${BASH_VERSION#[2-9].}" != "x$BASH_VERSION"; then
39     if test "x${BASH_VERSION#2.0[012]}" = "x$BASH_VERSION"; then
40       readLine="read -e -r"
41     fi
42   fi
43 else
44   # Non-bash: Check whether "read -r" supported
45   if (echo | read -r REPLY 2>/dev/null); then
46     readLine="read -r"
47   fi
48 fi
49 #______________________________________________________________________
50
51 # isURI <string>
52 # Returns 0 (true) if the supplied string is a HTTP/HTTPS/FTP/FILE
53 # URL, otherwise 1
54 isURI() {
55   case "$1" in
56     [hH][tT][tT][pP]:*) return 0;;
57     [hH][tT][tT][pP][sS]:*) return 0;;
58     [fF][tT][pP]:*) return 0;;
59     [fF][iI][lL][eE]:*) return 0;;
60     *) return 1;
61   esac
62 }
63 #______________________________________________________________________
64
65 strEqual() { test "x$1" = "x$2"; }
66 strNotEqual() { test "x$1" != "x$2"; }
67 strEmpty() { test "x$1" = "x"; }
68 strNotEmpty() { test "x$1" != "x"; }
69 #______________________________________________________________________
70
71 # fetch <URL>...
72 # Download a file, storing it in the current dir
73 fetch() {
74   if test "$#" -eq 0; then return 0; fi
75   wget --user-agent="$userAgent" $wgetOpts "$@" || return 1
76 }
77 #______________________________________________________________________
78
79 # Given URLs, fetch them into $imageTmp, then merge them into image
80 fetchAndMerge() {
81   if test "$#" -eq 0; then return 0; fi
82   fetch --force-directories --directory-prefix="$imageTmp" -- "$@"
83   # Merge into the image
84   $jigdoFile $jigdoOpts --no-cache make-image --image="$image" \
85     --jigdo="$jigdoF" --template="$template" "$imageTmp"
86   jigdoErr="$?"
87   if test "$jigdoErr" -ge 3; then
88     echo "jigdo-file failed with code $jigdoErr - aborting."
89     $error 1
90   fi
91   # Delete imageTmp, to avoid taking up more space than necessary
92   rm -rf "$imageTmp"
93   return 0
94 }
95 #______________________________________________________________________
96
97 # Prompt user to input value, assign result to $REPLY. If user just
98 # presses Return, assign supplied default value instead.
99 # input <prompt string> <default value>
100 input() {
101   prompt=""
102   REPLY=""
103   if strNotEmpty "$2"; then prompt=" [$2]"; fi
104   printf "%s%s: " "$1" "$prompt"
105   if $nonInteractive; then echo; else $readLine REPLY; fi
106   if strEmpty "$REPLY"; then REPLY="$2"; fi
107 }
108 #______________________________________________________________________
109
110 # Read from $jigdoF and create a menu of images contained in the file.
111 # If invoked just as "imageMenu", print out the menu. If invoked as
112 # "imageMenu 5", set $image and $templateURI to the filename/URI of
113 # the 5th menu entry.
114 # The scan for [Image] sections stops when at least one such section
115 # has been read and a non-[Image] section follows. This is not
116 # correct, but speeds things up a lot because in many cases the large
117 # [Parts] section does not have to be scanned.
118 imageMenu() {
119   imageSel="$1"
120   curImageCount=0
121   section=""
122   exec 3<"$jigdoF"
123   l=""
124   while true; do
125     case "$l" in
126       "[Image]"*)
127         # Read image section contents
128         unset image templateURI templateMD5 templateSHA256 shortInfo info
129         while $readLine l <&3; do
130           case "$l" in
131             "["*"]"*) break;;
132             Filename=*) image="`echo $l | sed -e 's/^Filename= *//; s%[['\\''\"$\\\`|&/]%%g'`";;
133             Template=*) templateURI="`echo $l | sed -e 's/^Template= *//; s%[['\\''\"$\\\`|&]%%g'`";;
134             Template-MD5Sum=*) templateMD5="`echo $l | sed -e 's/^Template-MD5Sum= *//; s%[['\\''\"$\\\`|&/]%%g'`";;
135             Template-MD5Sum=*) templateMD5="`echo $l | sed -e 's/^Template-MD5Sum= *//; s%[^a-zA-Z0-9_-]%%g'`";;
136             Template-SHA256Sum=*) templateSHA256="`echo $l | sed -e 's/^Template-SHA256Sum= *//; s%[['\\''\"$\\\`|&/]%%g'`";;
137             Template-SHA256Sum=*) templateSHA256="`echo $l | sed -e 's/^Template-SHA256Sum= *//; s%[^a-zA-Z0-9_-]%%g'`";;
138             ShortInfo=*) shortInfo="`echo $l | sed -e 's/^ShortInfo= *//; s%[[$\\\`|]%%g'`";;
139             Info=*) info="`echo $l | sed -e 's/^Info= *//; s%[['\\''\"$\\\`|]%%g'`";;
140           esac
141         done
142         # Image section read, check for validity
143         if strNotEmpty "$image" && strNotEmpty "$templateURI"; then
144           curImageCount="`expr $curImageCount + 1`"
145           if strNotEmpty "$imageSel"; then
146             # Return info for image selected via $imageSel
147             if test "$imageSel" -eq "$curImageCount"; then exec 3<&-; return 0; fi
148           else
149             # Print image menu
150             if strEmpty "$shortInfo"; then
151               printf "%3d: %s\n" "$curImageCount" "$image"
152             else
153               printf "%3d: %s (%s)\n" "$curImageCount" "$shortInfo" "$image"
154             fi
155           fi
156         fi
157         case "$l" in "[Image]"*) continue;; esac
158         # Abort early, avoid reading [Parts]
159         imageCount="$curImageCount"; exec 3<&-; return 0;;
160       *)
161         # Skip other parts of the file
162         while $readLine l <&3; do
163             case "$l" in "["*"]"*) break;; esac
164         done
165         case "$l" in "["*"]"*) continue;; esac
166         imageCount="$curImageCount"; exec 3<&-; return 0;;
167     esac
168   done
169   imageCount="$curImageCount"
170   exec 3<&-
171   return 0
172 }
173 #______________________________________________________________________
174
175 # Output a horizontal rule
176 hrule() {
177   echo
178   echo "-----------------------------------------------------------------"
179 }
180 #______________________________________________________________________
181
182 # Download template, unless already present in current dir
183 fetchTemplate() {
184   if $fetchedTemplate; then return 0; fi
185   echo
186
187   template=`basename "$templateURI"`
188
189   if strEmpty "$templateMD5" && strEmpty "$templateSHA256" ; then
190     echo "[WARNING - \`Template-MD5Sum' and \`Template-SHA256Sum' missing from image section]"
191     echo
192   fi
193   if test -r "$template" && strNotEmpty "$templateMD5"; then
194     set -- `$jigdoFile md5sum --report=quiet "$template"`
195     if test "$1" = "$templateMD5"; then
196       echo "Not downloading .template file - \`$template' already present"
197       fetchedTemplate=true
198       return 0
199     fi
200   if test -r "$template" && strNotEmpty "$templateSHA256"; then
201     set -- `$jigdoFile sha256sum --report=quiet "$template"`
202     if test "$1" = "$templateSHA256"; then
203       echo "Not downloading .template file - \`$template' already present"
204       fetchedTemplate=true
205       return 0
206     fi
207   fi
208 #  elif test -r "$template"; then
209 #    echo "Not downloading .template file - \`$template' already present"
210 #    fetchedTemplate=true
211 #    return 0
212   fi
213   if isURI "$templateURI"; then
214     # Absolute template URL
215     echo 'Downloading .template file'
216 #    rm -f "$template"
217     fetch --continue -- "$templateURI"
218   elif isURI "$url"; then
219     # Template URI is relative to absolute jigdo URL
220     echo 'Downloading .template file'
221 #    rm -f "$template"
222     fetch --continue -- `echo "$url" | sed 's%[^/]*$%%'`"$templateURI"
223   else
224     # Template URI is relative to local jigdo filename
225     if $windows; then
226       # This is a bit broken - we ought to replace / with \ in templateURI too
227       template=`echo "$url" | sed 's%[^\]*$%%'`"$templateURI"
228     else
229       template=`echo "$url" | sed 's%[^/]*$%%'`"$templateURI"
230     fi
231   fi
232   fetchedTemplate=true
233   # Does template exist now?
234   if test ! -r "$template"; then
235     echo "File \`$template' does not exist!"
236     $error 1
237   fi
238   if strEmpty "$templateMD5" && strEmpty "$templateSHA256" ; then return 0; fi
239   if strNotEmpty "$templateMD5"; then
240     set -- `$jigdoFile md5sum --report=quiet "$template"`
241     if strEqual "$1" "$templateMD5"; then return 0; fi
242   fi
243   if strNotEmpty "$templateSHA256"; then
244     set -- `$jigdoFile sha256sum --report=quiet "$template"`
245     if strEqual "$1" "$templateSHA256"; then return 0; fi
246   fi
247   echo "Error - template checksum mismatch!"
248   echo "The .template file does not belong to the .jigdo file - the"
249   echo "chances are high that the image generation process will break."
250   echo "I will abort now. If you know better than me and want this error"
251   echo "to be ignored, enter the string \"42\" to proceed."
252   echo
253   echo "Note that you might get this error if you resumed the download of a"
254   echo ".template file, and that .template file has changed on the server in"
255   echo "the meantime. In this case, you may be able to fix the problem by"
256   echo "deleting the .template file and restarting jigdo-lite."
257   input ""
258   case $REPLY in *42*) return 0;; esac
259   $error 1
260 }
261 #______________________________________________________________________
262
263 # Write $rcFile
264 saveOptions() {
265   printf "jigdo='%s'${nl}debianMirror='%s'${nl}nonusMirror='%s'${nl}" \
266     "$jigdo" "$debianMirror" "$nonusMirror" >"$rcFile"
267   printf "tmpDir='%s'${nl}jigdoOpts='%s'${nl}" \
268     "$tmpDir" "$jigdoOpts" >>"$rcFile"
269   printf "wgetOpts='%s'${nl}scanMenu='%s'${nl}" \
270     "$wgetOpts" "$scanMenu" >>"$rcFile"
271   printf "filesPerFetch='%s'${nl}" \
272     "$filesPerFetch" >>"$rcFile"
273 }
274 #______________________________________________________________________
275
276 finished() {
277   hrule
278 echo "Finished!"
279 if $batch; then true; else
280 echo "The fact that you got this far is a strong indication that \`$image'"
281 echo "was generated correctly. I will perform an additional, final check,"
282 echo "which you can interrupt safely with Ctrl-C if you do not want to wait."
283 fi
284 echo
285   $jigdoFile verify --image="$image" --jigdo="$jigdoF" --template="$template" \
286     $jigdoOpts
287   return 0
288 }
289 #______________________________________________________________________
290
291 # $0 is an URL or filename. Download/process it.
292 selectImage() {
293   url="$1"
294
295   # Arg can be either URL or filename. Maybe download file
296   if isURI "$url"; then
297     jigdoF=`basename "$url"`
298     echo
299     if test -r "$jigdoF"; then
300       echo "Not downloading .jigdo file - \`$jigdoF' already present"
301     else
302       echo "Downloading .jigdo file"
303       fetch -- "$url"
304     fi
305   else
306     jigdoF="$url"
307   fi
308   # Does jigdo exist now?
309   if test ! -r "$jigdoF"; then
310     echo "File \`$jigdoF' does not exist!"
311     $error 1
312   fi
313   # Try to gunzip it. In case of error, assume that it wasn't gzipped
314   if gzip -cd "$jigdoF" >"$jigdoF.unpacked" 2>/dev/null; then
315     jigdoF="$jigdoF.unpacked"
316   else
317     rm -f "$jigdoF.unpacked"
318   fi
319   #________________________________________
320
321   if $batch; then
322     # Batch - download all images
323     hrule
324     echo "Images offered by \`$url':"
325     imageMenu # print out menu, set $imageCount
326     imageNr=1
327     while test "$imageNr" -le "$imageCount"; do
328       imageMenu "$imageNr" # set $image and $templateURI
329       hrule
330       if test "$imageCount" -eq 1; then
331         echo "Batch mode: Will download \`$image'"
332       else
333         echo "Batch mode: Will download \`$image' (image $imageNr out of $imageCount)"
334       fi
335       imageDownload
336       imageNr="`expr $imageNr + 1`"
337       askQuestions=false
338     done
339
340   else
341
342     # Interactive - ask
343     while true; do
344       hrule
345       echo "Images offered by \`$url':"
346       imageMenu # print out menu, set imageCount
347       if test "$imageCount" -eq 1; then
348         imageMenu "1" # set $image and $templateURI
349         imageDownload
350         break # Only 1 image - don't loop asking for images to download
351       else
352         input "Number of image to download" ""
353         if strEmpty "$REPLY"; then continue; fi
354         if test "$REPLY" -ge 1 -a "$REPLY" -le "$imageCount"; then
355           imageMenu "$REPLY" # set $image and $templateURI
356           imageDownload || return 1
357         fi
358       fi
359     done
360
361   fi
362   case "$jigdoF" in *.unpacked) rm -f "$jigdoF";; esac
363 }
364 #______________________________________________________________________
365
366 scanFiles() {
367   # If --scan on command line, never ask, just scan that path
368   if strNotEmpty "$opt_filesToScan"; then
369     echo "Path to scan: $opt_filesToScan"
370     if $batch; then return 0; fi
371     # Retrieve template if necessary, then supply files
372     fetchTemplate || return 1
373     $jigdoFile make-image --image="$image" --jigdo="$jigdoF" \
374       --template="$template" $jigdoOpts "$opt_filesToScan"
375     jigdoErr="$?"
376     if test "$jigdoErr" -eq 0 -a -r "$image"; then
377       finished
378       $error 0 # All files were present on local filesystem
379     elif test "$jigdoErr" -ge 3; then
380       echo "jigdo-file failed with code $jigdoErr - aborting."
381       $error 1
382     fi
383     return 0
384   fi
385
386   # Ask user for any parts on local filesystems
387   while true; do
388     hrule
389     echo "If you already have a previous version of the CD you are"
390     echo "downloading, jigdo can re-use files on the old CD that are also"
391     echo "present in the new image, and you do not need to download them"
392     if $windows; then
393     echo "again. Enter the path to the old CD ROM's contents (e.g. \`d:\\')."
394     else
395     echo "again. Mount the old CD ROM and enter the path it is mounted under"
396     echo "(e.g. \`/mnt/cdrom')."
397     fi
398     echo "Alternatively, just press enter if you want to start downloading"
399     echo "the remaining files."
400     shift "$#" # Solaris /bin/sh doesn't understand "set --"
401     set -- $scanMenu
402     if strNotEmpty "$1"; then
403       echo
404       echo "You can also enter a single digit from the list below to"
405       echo "select the respective entry for scanning:"
406       echo "  1: $1"
407       if strNotEmpty "$2"; then echo "  2: $2"; fi
408       if strNotEmpty "$3"; then echo "  3: $3"; fi
409       if strNotEmpty "$4"; then echo "  4: $4"; fi
410       if strNotEmpty "$5"; then echo "  5: $5"; fi
411     fi
412     input "Files to scan"; filesToScan="$REPLY"
413     if strEmpty "$filesToScan"; then return 0; fi
414     # Do not add supplied string to menu if...
415     case "$filesToScan" in
416       *" "*|*"'"*|*'`'*|*'"'*|*'$'*) ;; # ...it has bad chars
417       1) filesToScan="$1";;
418       2) filesToScan="$2";;
419       3) filesToScan="$3";;
420       4) filesToScan="$4";;
421       5) filesToScan="$5";;
422       *) case " $1 $2 $3 $4 $5 " in
423         *" $filesToScan "*) ;; # ...it is already in the menu
424         *)  set -- "$filesToScan" $scanMenu
425           scanMenu="$1 $2 $3 $4 $5"
426           saveOptions;;
427       esac;;
428     esac
429     if strEmpty "$filesToScan"; then continue; fi
430
431     # In batch mode, postpone template download, scan later
432     if $batch; then return 0; fi
433
434     # Retrieve template if necessary, then supply files
435     fetchTemplate || return 1
436     $jigdoFile make-image --image="$image" --jigdo="$jigdoF" \
437       --template="$template" $jigdoOpts "$filesToScan"
438     jigdoErr="$?"
439     if test "$jigdoErr" -eq 0 -a -r "$image"; then
440       finished
441       $error 0 # All files were present on local filesystem
442     elif test "$jigdoErr" -ge 3; then
443       echo "jigdo-file failed with code $jigdoErr - aborting."
444       $error 1
445     fi
446   done
447 }
448 #______________________________________________________________________
449
450 selectServers() {
451   if $askQuestions; then true; else return; fi
452
453   # Crude check for whether any entry in the [Parts] section uses a
454   # "Debian" or "Non-US" label. If yes, start Debian mirror selection
455   # below.
456   if $batch; then
457     # If in batch mode, always ask the server questions; even though
458     # the current .jigdo file might not use Debian servers, a later
459     # one might, but we can't ask then.
460     usesDebian=true
461     usesNonus=true
462   else
463     usesDebian=false
464     if egrep '^[^=]+= *["'\'']?Debian:' <"$jigdoF" >/dev/null; then
465       usesDebian=true
466     fi
467     usesNonus=false
468     if egrep '^[^=]+= *["'\'']?Non-US:' <"$jigdoF" >/dev/null; then
469       usesNonus=true
470     fi
471   fi
472
473   # Extra options to pass to jigdo-file for server selection
474   uriOpts=""
475
476   while $usesDebian; do
477     hrule
478     echo "The jigdo file refers to files stored on Debian mirrors. Please"
479     echo "choose a Debian mirror as follows: Either enter a complete URL"
480     echo "pointing to a mirror (in the form"
481     echo "\`ftp://ftp.debian.org/debian/'), or enter any regular expression"
482     echo "for searching through the list of mirrors: Try a two-letter"
483     echo "country code such as \`de', or a country name like \`United"
484     echo "States', or a server name like \`sunsite'."
485     input "Debian mirror" "$debianMirror"
486     # Special-case two-letter country codes
487     case "$REPLY" in [a-z][a-z]) REPLY="[. ]$REPLY[/. ]";; esac
488     if isURI "$REPLY"; then
489       # Turn any "file:/opt/mirror" into "file:/opt/mirror/"
490       debianMirror=`echo $REPLY | sed -e 's%^ *\([^ ]*[^/ ]\)/*\( .*\)*$%\1/%'`
491       saveOptions
492       uriOpts="--uri Debian='$debianMirror'"
493       break;
494     fi
495     egrep -i "$REPLY" "$mirrors" | sed -n -e 's/^Debian=//p'
496     echo
497     echo "An up-to-date copy of the above list is available at"
498     echo "ftp://ftp.debian.org/debian/README.mirrors.txt"
499   done
500
501   while $usesNonus; do
502     hrule
503     echo "The jigdo file also refers to the Non-US section of the Debian"
504     echo "archive. Please repeat the mirror selection for Non-US. Do not"
505     echo "simply copy the URL you entered above; this does not work because"
506     echo "the path on the servers differs!"
507     input "Debian non-US mirror" "$nonusMirror"
508     case "$REPLY" in [a-z][a-z]) REPLY="[. ]$REPLY[/. ]";; esac
509     if isURI "$REPLY"; then
510       # Turn any "file:/opt/mirror" into "file:/opt/mirror/"
511       nonusMirror=`echo $REPLY | sed -e 's%^ *\([^ ]*[^/ ]\)/*\( .*\)*$%\1/%'`
512       saveOptions
513       uriOpts="$uriOpts --uri Non-US='$nonusMirror'";
514       break;
515     fi
516     egrep -i "$REPLY" "$mirrors" | sed -n -e 's/^Non-US=//p'
517     echo
518     echo "An up-to-date copy of the above list is available at"
519     echo "ftp://ftp.debian.org/debian/README.non-US"
520   done
521 }
522 #______________________________________________________________________
523
524 # $image: image filename
525 # $templateURI: Absolute/relative URI from .jigdo file
526 # $info: Info=... entry from .jigdo file
527 imageDownload() {
528
529   fetchedTemplate=false
530
531   if strNotEmpty "$info"; then
532     printf "\nFurther information about \`%s':\n" "$image"
533     echo "$info"
534   fi
535   list="$image.list"
536
537   # Create name of temporary dir, by stripping extension from $image
538   imageTmp="$tmpDir/`echo $image | sed 's%\.\(tmp|iso|raw\)%%'`.tmpdir"
539   if test -f "$imageTmp" -o "x$imageTmp" = "x$image"; then
540     imageTmp="$imageTmp.tmpdir"
541   fi
542
543   # Deal with leftover tmpdir from previous, interrupted download
544   if $askQuestions && test -d "$imageTmp"; then
545     hrule
546     echo "The temporary directory \`$imageTmp' already exists. Its contents"
547     echo "ARE GOING TO BE DELETED (possibly after having been copied to the"
548     echo "image, if they are of interest for it). If you do not want this"
549     echo "to happen, press Ctrl-C now. Otherwise, press Return to proceed."
550     input ""
551   fi
552
553   if $askQuestions; then
554     # Ask questions and scan dirs, set up $filesToScan
555     scanFiles || return 1
556     if $batch; then selectServers; fi
557   fi
558
559   if $batch && strNotEmpty "$filesToScan$opt_filesToScan"; then
560     # Retrieve template if necessary, then supply files. One of the
561     # two variables $filesToScan and $opt_filesToScan is always empty
562     fetchTemplate || return 1
563     $jigdoFile make-image --image="$image" --jigdo="$jigdoF" \
564       --template="$template" $jigdoOpts "$filesToScan$opt_filesToScan"
565     jigdoErr="$?"
566     if test "$jigdoErr" -eq 0 -a -r "$image"; then
567       finished
568       return 0 # All files were present on local filesystem
569     elif test "$jigdoErr" -ge 3; then
570       echo "jigdo-file failed with code $jigdoErr - aborting."
571       return 1
572     fi
573   fi
574
575   # Read any files from non-empty tmpDir. Don't delete tmpDir yet, as
576   # wget may resume some half-finished files
577   if test -d "$imageTmp"; then
578     fetchTemplate || return 1
579     # Merge into the image
580     $jigdoFile $jigdoOpts --no-cache make-image --image="$image" \
581       --jigdo="$jigdoF" --template="$template" "$imageTmp"
582   fi
583
584   # Download files and merge them into the image. We instruct wget to
585   # download 10 files at a time and then merge them. This way, compared
586   # to downloading everything, the peak disc space usage is not twice
587   # the size of the final image.
588   while true; do
589
590     if $batch; then true; else selectServers; fi
591     fetchTemplate || return 1
592     hrule
593
594     # If a "file:" URI was given instead of a server URL, try to merge
595     # any files into the image.
596     echo "Merging parts from \`file:' URIs, if any..."
597     $jigdoFile print-missing-all --image="$image" --jigdo="$jigdoF" \
598         --template="$template" $jigdoOpts $uriOpts \
599     | egrep -v '^([a-zA-Z0-9.+_-]+:|$)' \
600     | $jigdoFile make-image --image="$image" --jigdo="$jigdoF" \
601         --template="$template" $jigdoOpts --files-from=-
602     jigdoErr="$?"
603     if test "$jigdoErr" -ge 3; then
604       echo "jigdo-file failed with code $jigdoErr - aborting."
605       $error 1
606     fi
607
608     # First try to download all files using the first URL in the
609     # print-missing-all list. If any files remain missing, add another
610     # pass, this time try to download the missing files using the 2nd
611     # URL, and so on.
612     noMorePasses=false
613     for pass in x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx; do
614       $jigdoFile print-missing-all --image="$image" --jigdo="$jigdoF" \
615         --template="$template" $jigdoOpts $uriOpts \
616       | egrep -i '^(http:|https:|ftp:|$)' >"$list"
617       missingCount=`egrep '^$' <"$list" | wc -l | sed -e 's/ *//g'`
618       # Accumulate URLs in $@, pass them to fetchAndMerge in batches
619       shift "$#" # Solaris /bin/sh doesn't understand "set --"
620       count=""
621       exec 3<"$list"
622       while $readLine url <&3; do
623         count="x$count"
624         if strEmpty "$url"; then count=""; continue; fi
625         if test "$count" != "$pass"; then continue; fi
626         if $noMorePasses; then
627           hrule
628           echo "$missingCount files not found in previous pass, trying"
629           echo "alternative download locations:"
630           echo
631         fi
632         noMorePasses=false
633         set -- "$@" "$url"
634         if test "$#" -ge "$filesPerFetch"; then
635           if fetchAndMerge "$@"; then true; else exec 3<&-; return 1; fi
636           shift "$#" # Solaris /bin/sh doesn't understand "set --"
637         fi
638       done
639       exec 3<&-
640       if test "$#" -ge 1; then fetchAndMerge "$@" || return 1; fi
641       if $noMorePasses; then break; fi
642       if test -r "$image"; then break; fi
643       noMorePasses=true
644     done
645
646     rm -f "$list"
647     if test -r "$image"; then break; fi
648
649     hrule
650     echo "Aaargh - $missingCount files could not be downloaded. This should not"
651     echo "happen! Depending on the problem, it may help to retry downloading"
652     echo "the missing files."
653     if $batch; then return 1; fi
654     if $usesDebian || $usesNonus; then
655     echo "Also, you could try changing to another Debian or Non-US server,"
656     echo "in case the one you used is out of sync."
657     fi
658     echo
659     echo "However, if all the files downloaded without errors and you"
660     echo "still get this message, it means that the files changed on the"
661     echo "server, so the image cannot be generated."
662     if $usesDebian || $usesNonus; then
663     echo "As a last resort, you could try to complete the CD image download"
664     echo "by fetching the remaining data with rsync."
665     fi
666     echo
667     echo "Press Return to retry downloading the missing files."
668     echo "Press Ctrl-C to abort. (If you re-run jigdo-lite later, it will"
669     echo "resume from here, the downloaded data is not lost if you press"
670     echo "Ctrl-C now.)"
671     input ""
672
673   done
674   finished
675 }
676 #======================================================================
677
678 echo
679 echo 'Jigsaw Download "lite"'
680 echo "Copyright (C) 2001-2009  |  jigdo@"
681 echo "Richard Atterer          |  atterer.org"
682 echo "Copyright (C) 2016-2019"
683 echo "Steve McIntyre <93sam@debian.org>"
684
685 jigdoFile="jigdo-file"
686 jigdo-file --version >/dev/null 2>/dev/null
687 if test "$?" -ne 0; then
688     # Using ./jigdo-file is possibly a security risk, so only use if
689     # nothing else is there
690     if test -x "./jigdo-file"; then jigdoFile="./jigdo-file"; fi
691 fi
692 jigdoFileSameDir="`dirname $0`/jigdo-file"
693 if test -x "$jigdoFileSameDir"; then jigdoFile="$jigdoFileSameDir"; fi
694
695 mirrorsSameDir="`dirname $0`/$mirrors"
696 if test -r "$mirrorsSameDir"; then mirrors="$mirrorsSameDir"; fi
697
698 # Check for programs
699 if $windows; then
700     jigdoFile=jigdo-file
701 else
702     for prog in wget egrep sed gzip wc expr; do
703         which "$prog" >/dev/null \
704             || echo "Could not find program \`$prog' - please install it!"
705     done
706 fi
707
708 userAgent="jigdo-lite/`$jigdoFile --version 2>/dev/null | ($readLine jf v ver; echo $ver)` (`wget --version 2>/dev/null | ($readLine ver; echo $ver)`; $OSTYPE)"
709
710 # Load preferences file, if present
711 if test -f "$rcFile"; then
712     echo "Loading settings from \`$rcFile'"
713     mirrorsX="$mirrors"
714     . "$rcFile"
715     mirrors="$mirrorsX"
716     # When upgrading from versions <0.6.9, update value of tmpDir
717     if strEqual "$tmpDir" "tmp" || strEqual "$tmpDir" "temp"; then
718         tmpDir="."
719     fi
720 fi
721
722 # If running for the first time, try to read mirror info from sources.list
723 if strEmpty "$debianMirror$nonusMirror" && test -f "/etc/apt/sources.list"; then
724     echo "Getting mirror information from /etc/apt/sources.list"
725     while $readLine deb url dist rest; do
726         case "$deb $dist" in
727             "deb "*/non-US)
728                 test "$nonusMirror" = "" && \
729                 nonusMirror=`echo "$url"|sed 's%^copy://%file://%; s%//*$%/%'`;;
730             "deb "*)
731                 test "$debianMirror" = "" && \
732                 debianMirror=`echo "$url"|sed 's%^copy://%file://%; s%//*$%/%'`;;
733         esac
734     done <"/etc/apt/sources.list"
735 fi
736 #________________________________________
737
738 # Process command line switches
739 batch=false
740 nonInteractive=false
741 while true; do
742   case "$1" in
743   --help|-h)
744     echo
745     echo "Usage: $0 [OPTIONS] [FILES or URLS...]"
746     echo "  -h  --help       Print this message"
747     echo "  -v  --version    Output version information"
748     echo "      --scan PATH  Don't ask for \"Files to scan\", use this path"
749     echo "      --noask      \"Press Return automatically\" for all "
750     echo "                   questions, accepting the offered defaults"
751     exit 0;;
752   --version|-v)
753     echo
754     echo "$userAgent"
755     exit 0;;
756   --scan)
757     opt_filesToScan="$2"
758     shift 2;;
759   --noask)
760     nonInteractive=true
761     shift 1;;
762   *)
763     break;;
764     esac
765 done
766 #________________________________________
767
768 # No cmd line argument => prompt user
769 if test "$#" -eq 0; then
770     hrule
771     echo "To resume a half-finished download, enter name of .jigdo file."
772     echo "To start a new download, enter URL of .jigdo file."
773     echo "You can also enter several URLs/filenames, separated with spaces,"
774     echo "or enumerate in {}, e.g. \`http://server/cd-{1_NONUS,2,3}.jigdo'"
775     input "jigdo" "$jigdo"
776     jigdo="$REPLY"
777     set -- "$REPLY"
778     saveOptions
779 fi
780 # Expand "a{b,c{x,y}}" into "ab acx acy". How's that for a sed script?
781 # Test cases:
782 # a{b,c{x,y},d{,2}}   FAILS
783 # fl{a,e,i,o,u}b
784 # {wo{x,}of}
785 # {a,b}x{1,2}
786 set -- `echo "$*" | sed '
787 :a
788 s%{\([^,]*\)}%\1%g
789 s%{\(\([^{},]*,\)*\)\([^{},]*\){\([^,{}]*\),\{0,1\}\([^{}]*\)}\([^{}]*\)}%{\1\3\4,\3{\5}\6}%
790 t a
791 :b
792 s%{\([^,]*\)}%\1%g
793 s%\([^{ ]*\){\([^,{}]*\),\{0,1\}\([^{}]*\)}\([^ ]*\)%\1\2\4 \1{\3}\4%
794 t b'`
795 if test "$#" -gt 1; then
796     hrule
797     echo "You have asked me to process several files/URLs:"
798     for file in "$@"; do echo "  $file"; done
799     batch=true
800     echo
801     echo "Entering batch mode"
802     error="return"
803 else
804     error="exit"
805 fi
806 #________________________________________
807
808 askQuestions=true
809 for url in "$@"; do
810     selectImage "$url"
811 done
812 exit 0