tazlito annotate live.cgi @ rev 426
Update loram http
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Tue Jun 28 11:24:00 2016 +0200 (2016-06-28) |
parents | 639fcd94f19b |
children | da648e687bb6 |
rev | line source |
---|---|
pascal@320 | 1 #!/bin/sh |
pascal@320 | 2 # |
pascal@320 | 3 # CGI interface for SliTaz Live systems using Tazlito and TazUSB. |
pascal@320 | 4 # |
al@399 | 5 # Copyright (C) 2011-2015 SliTaz GNU/Linux - BSD License |
pascal@320 | 6 # |
pascal@320 | 7 |
al@399 | 8 if [ "$1" == 'call' ]; then |
pascal@320 | 9 case "$2" in |
al@399 | 10 merge_cleanup) |
al@399 | 11 mv -f $3.merged $3 |
al@399 | 12 for i in $4/*; do |
al@399 | 13 umount -d $i |
al@399 | 14 done |
al@399 | 15 rm -rf $4 |
al@399 | 16 exit ;; |
pascal@320 | 17 esac |
pascal@320 | 18 fi |
pascal@320 | 19 |
al@399 | 20 |
pascal@320 | 21 # Common functions from libtazpanel |
al@399 | 22 |
pascal@320 | 23 . lib/libtazpanel |
pascal@320 | 24 get_config |
pascal@320 | 25 |
al@399 | 26 |
pascal@382 | 27 #------ |
pascal@382 | 28 # menu |
pascal@382 | 29 #------ |
pascal@382 | 30 |
pascal@382 | 31 case "$1" in |
pascal@382 | 32 menu) |
al@399 | 33 TEXTDOMAIN_original="$TEXTDOMAIN" |
pascal@382 | 34 export TEXTDOMAIN='tazlito' |
pascal@382 | 35 cat <<EOT |
pascal@401 | 36 <li><a data-icon="cd" href="live.cgi">$(_ 'Live')</a> |
pascal@382 | 37 <menu> |
al@399 | 38 <li><a data-icon="" href="live.cgi?liveusb" data-root>$(_ 'Create a live USB key')</a></li> |
al@399 | 39 <li><a data-icon="" href="live.cgi#liveiso" data-root>$(_ 'Create a live CD-ROM')</a></li> |
pascal@400 | 40 <li><a data-icon="" href="live.cgi#hybrid">$(_ 'Create a hybrid ISO')</a></li> |
al@399 | 41 <li><a data-icon="" href="live.cgi#loram" data-root>$(_ 'Convert ISO to loram')</a></li> |
al@399 | 42 <li><a data-icon="" href="live.cgi#meta" data-root>$(_ 'Build a meta ISO')</a></li> |
pascal@382 | 43 </menu> |
pascal@382 | 44 </li> |
pascal@382 | 45 EOT |
al@399 | 46 export TEXTDOMAIN="$TEXTDOMAIN_original" |
pascal@382 | 47 exit |
pascal@382 | 48 esac |
pascal@382 | 49 |
pascal@382 | 50 |
al@399 | 51 TEXTDOMAIN='tazlito' |
al@399 | 52 TITLE=$(_ 'Live') |
pascal@384 | 53 header |
pascal@320 | 54 |
al@399 | 55 |
pascal@320 | 56 # Build arguments to create a meta iso using 'tazlito merge' command |
al@399 | 57 |
al@399 | 58 merge_args() { |
al@399 | 59 tmp="$1" |
pascal@320 | 60 first=true |
pascal@320 | 61 i=1 |
pascal@320 | 62 while [ -n "$(GET input$i)" ]; do |
pascal@320 | 63 echo "$(stat -c "%s" $(GET input$i)) $(GET input$i) $(GET ram$i)" |
pascal@320 | 64 $((i++)) |
al@399 | 65 done | sort -nr | \ |
al@399 | 66 while read size file ram; do |
pascal@320 | 67 if $first; then |
pascal@320 | 68 cp $file $(GET metaoutput) |
pascal@320 | 69 echo -n "$ram $(GET metaoutput) " |
pascal@320 | 70 first=false |
pascal@320 | 71 continue |
pascal@320 | 72 fi |
al@399 | 73 dir="$tmp/$(basename $file)" |
al@399 | 74 mkdir "$dir" |
al@399 | 75 mount -o loop,ro "$file" "$dir" |
pascal@320 | 76 echo -n "$ram $dir/boot/rootfs.gz " |
pascal@320 | 77 done |
pascal@320 | 78 } |
pascal@320 | 79 |
al@399 | 80 |
pascal@320 | 81 # |
pascal@320 | 82 # Commands executed in Xterm first |
pascal@320 | 83 # |
pascal@320 | 84 |
pascal@320 | 85 case " $(GET) " in |
pascal@320 | 86 *\ loramoutput\ *) |
al@399 | 87 export output='raw' |
al@399 | 88 DISPLAY=':0.0' XAUTHORITY='/var/run/slim.auth' \ |
pascal@320 | 89 $TERMINAL $TERM_OPTS \ |
al@399 | 90 -T "$(_ 'Convert ISO to loram')" \ |
al@399 | 91 -e "tazlito build-loram $(GET input) $(GET loramoutput) $(GET type)" & |
al@399 | 92 ;; |
al@399 | 93 |
pascal@320 | 94 *\ meta\ *) |
pascal@320 | 95 tmp=/tmp/$(basename $0).$$ |
pascal@320 | 96 cleanup="sh $0 call merge_cleanup $(GET output) $tmp" |
al@399 | 97 export output='raw' |
al@399 | 98 DISPLAY=':0.0' XAUTHORITY='/var/run/slim.auth' \ |
pascal@320 | 99 $TERMINAL $TERM_OPTS \ |
al@399 | 100 -T "$(_ 'Build a meta ISO')" \ |
pascal@320 | 101 -e "tazlito merge $(merge_args $tmp); \ |
al@399 | 102 _ 'ENTER to quit'; read i; \ |
al@399 | 103 $cleanup" & |
al@399 | 104 ;; |
al@399 | 105 |
pascal@320 | 106 *\ hybrid\ *) |
al@399 | 107 export output='raw' |
al@399 | 108 DISPLAY=':0.0' XAUTHORITY='/var/run/slim.auth' \ |
pascal@320 | 109 $TERMINAL $TERM_OPTS \ |
al@399 | 110 -T "$(_ 'Create a hybrid ISO')" \ |
al@399 | 111 -e "iso2exe $(GET input)" & |
al@399 | 112 ;; |
pascal@320 | 113 esac |
pascal@320 | 114 |
al@399 | 115 |
pascal@320 | 116 # |
pascal@320 | 117 # Commands |
pascal@320 | 118 # |
pascal@320 | 119 |
pascal@320 | 120 case " $(GET) " in |
al@399 | 121 |
pascal@320 | 122 *\ create\ *) |
pascal@320 | 123 # |
pascal@320 | 124 # Create a flavor file and ISO in options with all settings |
pascal@320 | 125 # Step by step interface and store files in cache. |
pascal@320 | 126 # |
al@399 | 127 xhtml_header |
al@399 | 128 _ 'TODO' |
al@399 | 129 ;; |
al@399 | 130 |
pascal@320 | 131 *\ liveusb\ *) |
al@399 | 132 TITLE="$(_ 'SliTaz LiveUSB')" |
al@399 | 133 xhtml_header "$(_ 'Create Live USB SliTaz systems')" |
al@399 | 134 cat <<EOT |
al@399 | 135 <section> |
al@399 | 136 <header>$(_ 'SliTaz LiveUSB')</header> |
pascal@320 | 137 |
al@399 | 138 <form method="get" action="$SCRIPT_NAME" class="wide"> |
al@399 | 139 <div> |
al@399 | 140 $(_ "Generate SliTaz LiveUSB media and boot in RAM! Insert a Live CD \ |
al@399 | 141 into the CD-ROM drive, select the correct device and press Generate.") |
al@399 | 142 </div> |
pascal@320 | 143 |
al@399 | 144 <input type="hidden" name="liveusb" /> |
al@399 | 145 <footer> |
al@399 | 146 $(_ 'USB Media to use:') |
al@399 | 147 <select name="gen" id="gen"> |
pascal@320 | 148 EOT |
pascal@320 | 149 # List disk if there is a plugged USB device |
pascal@320 | 150 if [ -d /proc/scsi/usb-storage ]; then |
al@399 | 151 for dev in /sys/block/sd*; do |
al@399 | 152 # removable writable sd* device: |
al@399 | 153 if [ "$(cat $dev/removable)" == '1' -a "$(cat $dev/ro)" == '0' ]; then |
al@399 | 154 echo "<optgroup label='$(cat $dev/device/vendor) $(cat $dev/device/model):'>" |
al@399 | 155 for part in $dev/sd*; do |
al@399 | 156 [ ! -d "$part" ] && break |
al@399 | 157 linuxdev=$(readlink -f /dev/block/$(cat $part/dev)) |
al@399 | 158 cat <<EOT |
al@399 | 159 <option value='$linuxdev'>$(basename $linuxdev) [$(blkid -o value -s TYPE "$linuxdev")] |
al@399 | 160 $(blkid -o value -s LABEL "$linuxdev") ($(cat $part/size | blk2h))</option> |
al@399 | 161 EOT |
al@399 | 162 done |
al@399 | 163 echo '</optgroup>' |
al@399 | 164 fi |
pascal@320 | 165 done |
pascal@320 | 166 else |
al@399 | 167 echo "<option value=''>$(_ 'Not found')</option>" |
pascal@320 | 168 fi |
al@399 | 169 |
al@399 | 170 cat <<EOT |
al@399 | 171 </select> |
al@399 | 172 <button type="submit" data-icon="removable">$(_ 'Generate')</button> |
al@399 | 173 </footer> |
al@399 | 174 </form> |
al@399 | 175 </section> |
pascal@320 | 176 EOT |
al@399 | 177 |
al@399 | 178 gen="$(GET gen)" |
al@399 | 179 if [ -n "$gen" ]; then |
al@399 | 180 cat <<EOT |
al@399 | 181 <script>document.getElementById("gen").value = "$gen";</script> |
al@399 | 182 |
al@399 | 183 <section> |
al@399 | 184 <header>tazusb gen-liveusb $gen</header> |
al@399 | 185 <pre> |
pascal@320 | 186 EOT |
pascal@320 | 187 # No pipe here so output is displayed in realtime |
al@399 | 188 yes | tazusb gen-liveusb $gen |
al@399 | 189 cat <<EOT |
al@399 | 190 </pre> |
al@399 | 191 </section> |
al@399 | 192 EOT |
al@399 | 193 fi |
al@399 | 194 |
al@399 | 195 ;; |
al@399 | 196 |
psychomaniak@383 | 197 *\ write_iso\ *) |
psychomaniak@383 | 198 xhtml_header |
psychomaniak@383 | 199 |
psychomaniak@383 | 200 LaunchedByTazpanel="y" \ |
psychomaniak@383 | 201 tazlito writeiso $(GET write_iso) > /tmp/tazlitowriteiso 2>&1 & |
psychomaniak@383 | 202 |
psychomaniak@383 | 203 until [ -f /rootfs.gz ]; do |
psychomaniak@383 | 204 sleep 1 |
psychomaniak@383 | 205 done |
al@399 | 206 cat <<EOT |
psychomaniak@383 | 207 <fieldset> |
psychomaniak@383 | 208 $(head /tmp/tazlitowriteiso | sed "s|$|<p></p>|g" | sed '/.gvfs/d') |
psychomaniak@383 | 209 <li id="fssize"> </li> |
psychomaniak@383 | 210 EOT |
psychomaniak@383 | 211 until [ ! -f /rootfs.gz ]; do |
psychomaniak@383 | 212 sleep 1 |
al@399 | 213 cat <<EOT |
psychomaniak@383 | 214 <script type="text/javascript"> |
psychomaniak@383 | 215 document.getElementById('fssize').innerHTML = "<h4>$(boldify $(du -mh /rootfs.gz | cut -f1))</h4>"; |
psychomaniak@383 | 216 </script> |
psychomaniak@383 | 217 EOT |
psychomaniak@383 | 218 done |
psychomaniak@383 | 219 if [ -f /rootfs.gz ]; then |
psychomaniak@383 | 220 until [ ! -f /rootfs.gz ]; do |
psychomaniak@383 | 221 sleep 1 |
psychomaniak@383 | 222 done |
psychomaniak@383 | 223 fi |
psychomaniak@383 | 224 cat <<EOT |
psychomaniak@383 | 225 <script type="text/javascript"> |
psychomaniak@383 | 226 document.getElementById('fssize').innerHTML = "$(boldify $(du -mh /home/slitaz/distro/rootcd/boot/rootfs.gz | cut -f1))"; |
psychomaniak@383 | 227 </script> |
psychomaniak@383 | 228 /home/slitaz/distro/rootcd/boot/rootfs.gz |
psychomaniak@383 | 229 </fieldset> |
psychomaniak@383 | 230 EOT |
psychomaniak@388 | 231 ls -l /home/slitaz/distro/rootcd/boot/rootfs.gz |
psychomaniak@383 | 232 until [ -f /tmp/.write-iso* ]; do |
psychomaniak@383 | 233 sleep 1 |
psychomaniak@383 | 234 done |
psychomaniak@383 | 235 echo "<fieldset>" |
psychomaniak@383 | 236 if [ -f /tmp/.write-iso ]; then |
psychomaniak@383 | 237 newline |
psychomaniak@383 | 238 tail /tmp/tazlitowriteiso | grep ISO |
psychomaniak@383 | 239 while [ -f /tmp/.write-iso ]; do sleep 1 ; done |
psychomaniak@383 | 240 elif [ -f /tmp/.write-iso-error ]; then |
psychomaniak@383 | 241 tail -n8 /tmp/tazlitowriteiso | grep -vE 'ENTER|----' |
psychomaniak@383 | 242 fi |
psychomaniak@383 | 243 tail -n5 /tmp/tazlitowriteiso | sed "s|$|<p></p>|g" |
psychomaniak@388 | 244 ls -l /home/slitaz/distro |
psychomaniak@383 | 245 echo "</fieldset>" |
al@399 | 246 echo "Use ' <code>tazlito emu-iso</code> ' to check it" |
al@399 | 247 ;; |
al@399 | 248 |
pascal@320 | 249 *) |
pascal@320 | 250 # |
pascal@320 | 251 # Default xHTML content |
pascal@320 | 252 # |
al@399 | 253 TITLE="$(_ 'SliTaz Live Systems')" |
al@399 | 254 xhtml_header "$(_ 'Create and manage Live CD or USB SliTaz systems')" |
pascal@320 | 255 |
pascal@400 | 256 [ $(id -u) -eq 0 ] && cat <<EOT |
pascal@320 | 257 |
al@399 | 258 <section id="liveiso"> |
al@399 | 259 <header>$(_ 'Write a Live CD')</header> |
pascal@320 | 260 |
al@399 | 261 <form method="get" action="$SCRIPT_NAME" class="wide"> |
al@399 | 262 <div> |
al@399 | 263 $(_ "The command writeiso will generate an ISO image of the current \ |
pascal@320 | 264 filesystem as is, including all files in the /home directory. It is an easy \ |
pascal@320 | 265 way to remaster a SliTaz Live system, you just have to: boot, modify, \ |
al@399 | 266 writeiso.") |
al@399 | 267 </div> |
pascal@320 | 268 |
al@399 | 269 <table> |
al@399 | 270 <tr><td> |
al@399 | 271 $(_ 'Compression type:') |
al@399 | 272 <select name="write_iso"> |
al@399 | 273 <option value="lzma">lzma</option> |
pascal@402 | 274 <option value="gzip">gzip</option> |
al@399 | 275 <option value="none">$(_ 'none')</option> |
al@399 | 276 </select> |
al@399 | 277 </td></tr> |
al@399 | 278 </table> |
al@399 | 279 EOT |
pascal@320 | 280 |
pascal@400 | 281 if [ $(id -u) -eq 0 -a ! -d /media/cdrom/boot/isolinux -a ! -f /boot/*slitaz* ]; then |
al@399 | 282 msg warn "$(_ 'Cannot find SliTaz ISO/CD mounted in /media/cdrom (You will get only rootfs.gz)')" |
al@399 | 283 fi |
pascal@320 | 284 |
al@399 | 285 inputiso="$(GET input)"; inputiso="${inputiso:-/root/}" |
al@399 | 286 loramoutput="$(GET loramoutput)"; loramoutput="${loramoutput:-/root/loram.iso}" |
pascal@320 | 287 |
pascal@400 | 288 [ $(id -u) -eq 0 ] && cat <<EOT |
al@399 | 289 <footer> |
al@399 | 290 <button type="submit" data-icon="cd">$(_ 'Write ISO')</button> |
al@399 | 291 </footer> |
al@399 | 292 </form> |
al@399 | 293 </section> |
psychomaniak@383 | 294 |
pascal@320 | 295 |
al@399 | 296 <section><header>$(_ 'Live CD tools')</header> |
pascal@320 | 297 |
pascal@320 | 298 |
al@399 | 299 <section id="loram"> |
al@399 | 300 <header>$(_ 'Convert ISO to loram')</header> |
pascal@320 | 301 |
al@399 | 302 <form method="get" action="$SCRIPT_NAME#loram" class="wide"> |
al@399 | 303 <div> |
al@399 | 304 $(_ "This command will convert an ISO image of a SliTaz Live CD to a \ |
pascal@400 | 305 new ISO image requiring less RAM to run.") (-30%) |
al@399 | 306 </div> |
pascal@320 | 307 |
al@399 | 308 <table> |
al@399 | 309 <tr><td> |
al@399 | 310 $(_ 'ISO to convert') |
al@409 | 311 $(file_chooser 'input' "$inputiso" 'cd' 'application/x-cd-image') |
al@399 | 312 </td></tr> |
al@399 | 313 <tr><td> |
al@399 | 314 <input type="radio" name="type" value="ram" id="type1" checked /> |
al@399 | 315 <label for="type1">$(_ 'The filesystem is always in RAM')</label> |
al@399 | 316 </td></tr> |
al@399 | 317 <tr><td> |
al@399 | 318 <input type="radio" name="type" value="smallcdrom" id="type2" /> |
al@399 | 319 <label for="type2">$(_ 'The filesystem may be on a small CD-ROM')</label> |
al@399 | 320 </td></tr> |
al@399 | 321 <tr><td> |
al@399 | 322 <input type="radio" name="type" value="cdrom" id="type3" /> |
al@399 | 323 <label for="type3">$(_ 'The filesystem may be on a large CD-ROM')</label> |
al@399 | 324 </td></tr> |
al@399 | 325 <tr><td> |
al@399 | 326 $(_ 'ISO to create') |
al@399 | 327 <input type="text" accept=".iso" name="loramoutput" value="$loramoutput" /> |
al@399 | 328 </td></tr> |
al@399 | 329 </table> |
pascal@320 | 330 |
al@399 | 331 <script> |
al@399 | 332 EOT |
al@399 | 333 case "$(GET type)" in |
al@399 | 334 smallcdrom) sel='type2';; |
al@399 | 335 cdrom) sel='type3';; |
al@399 | 336 *) sel='type1';; |
al@399 | 337 esac |
pascal@400 | 338 [ $(id -u) -eq 0 ] echo "document.getElementById('$sel').checked = true;" |
pascal@400 | 339 [ $(id -u) -eq 0 ] && cat <<EOT |
al@399 | 340 </script> |
pascal@320 | 341 |
al@399 | 342 <footer> |
al@399 | 343 <button type="submit" data-icon="cd">$(_ 'Convert ISO to loram')</button> |
al@399 | 344 </footer> |
al@399 | 345 </form> |
al@399 | 346 </section> |
pascal@320 | 347 |
pascal@400 | 348 EOT |
pascal@400 | 349 cat <<EOT |
al@399 | 350 |
al@399 | 351 <section id="hybrid"> |
al@399 | 352 <header>$(_ 'Build a hybrid ISO')</header> |
al@399 | 353 |
al@399 | 354 <form method="get" action="$SCRIPT_NAME#hybrid" class="wide"> |
al@399 | 355 <div> |
al@399 | 356 $(_ "Add a master boot sector and an EXE header to the ISO image.") |
pascal@400 | 357 <ul> |
pascal@401 | 358 <li>$(_ "Create a bootable image for a USB key, a memory card, a harddisk or a SSD.")</li> |
pascal@400 | 359 <li>$(_ "With the .EXE suffix, it will run under DOS (16 bits) or Windows (32 bits).")</li> |
pascal@401 | 360 <li>$(_ "Add the ISO filesystem md5 digest and the boot CRC in the ISO boot area.")</li> |
pascal@401 | 361 <li>$(_ "Does not alter the ISO filesystem or the ISO image size.")</li> |
pascal@400 | 362 </ul> |
al@399 | 363 </div> |
al@399 | 364 |
al@399 | 365 <table> |
al@399 | 366 <tr><td> |
al@399 | 367 $(_ 'ISO to convert') |
al@409 | 368 $(file_chooser 'input' '' 'cd' 'application/x-cd-image') |
al@399 | 369 </td></tr> |
al@399 | 370 </table> |
al@399 | 371 |
al@399 | 372 <footer> |
al@399 | 373 <button type="submit" name="hybrid" data-icon="cd">$(_ 'Build a hybrid ISO')</button> |
al@399 | 374 </footer> |
al@399 | 375 </form> |
al@399 | 376 </section> |
al@399 | 377 |
pascal@400 | 378 EOT |
pascal@400 | 379 [ $(id -u) -eq 0 ] && cat <<EOT |
al@399 | 380 |
al@399 | 381 <section id="meta"> |
al@399 | 382 <header>$(_ 'Build a meta ISO')</header> |
al@399 | 383 |
al@399 | 384 <form method="get" action="$SCRIPT_NAME#meta"> |
al@399 | 385 <div> |
al@399 | 386 $(_ "Combines several ISO flavors like nested Russian dolls. The \ |
al@399 | 387 amount of RAM available at startup will be used to select the utmost one.") |
al@399 | 388 </div> |
al@399 | 389 |
al@399 | 390 <table class="wide"> |
pascal@320 | 391 EOT |
al@399 | 392 i='' |
pascal@320 | 393 while [ -n "$(GET addmeta)" ]; do |
pascal@320 | 394 [ -n "$(GET input$i)" ] || break |
pascal@320 | 395 j=$(($i + 1)) |
pascal@400 | 396 [ $(id -u) -eq 0 ] && cat <<EOT |
al@399 | 397 <tr> |
al@399 | 398 <td> |
al@399 | 399 $(_ 'ISO number %s:' "$j") $(GET input$i) |
al@399 | 400 <input type="hidden" name="input$j" value="$(GET input$i)" /> |
al@399 | 401 </td> |
al@399 | 402 <td> |
al@399 | 403 $(_ 'Minimum RAM:') $(GET ram$i) |
al@399 | 404 <input type="hidden" name="ram$j" value="$(GET ram$i)" /> |
al@399 | 405 </td> |
al@399 | 406 </tr> |
pascal@320 | 407 EOT |
pascal@320 | 408 i=$j |
pascal@320 | 409 done |
pascal@320 | 410 metaoutput="$(GET metaoutput)" |
pascal@320 | 411 [ -n "$metaoutput" ] || metaoutput="/root/meta.iso" |
pascal@320 | 412 |
pascal@400 | 413 [ $(id -u) -eq 0 ] && cat <<EOT |
al@399 | 414 <tr> |
al@399 | 415 <td> |
al@399 | 416 $(_ 'ISO to add') |
al@409 | 417 $(file_chooser 'input' '' 'cd' 'application/x-cd-image') |
al@399 | 418 </td> |
al@399 | 419 <td> |
al@399 | 420 $(_ 'Minimum RAM:') |
al@399 | 421 <input type="text" name="ram" value="128M" /> |
al@399 | 422 <button type="submit" name="addmeta" value="addmeta" data-icon="add">$(_ 'Add to the list')</button> |
al@399 | 423 </td> |
al@399 | 424 </tr> |
al@399 | 425 <tr> |
al@399 | 426 <td> |
al@399 | 427 $(_ 'ISO to create') |
al@399 | 428 <input type="text" name="metaoutput" value="$metaoutput" /> |
al@399 | 429 </td> |
al@399 | 430 <td> |
al@399 | 431 </td> |
al@399 | 432 </tr> |
al@399 | 433 </table> |
pascal@320 | 434 |
al@399 | 435 <footer> |
al@399 | 436 <button type="submit" name="meta" value="meta" data-icon="cd">$(_ 'Build a meta ISO')</button> |
al@399 | 437 </footer> |
al@399 | 438 </form> |
al@399 | 439 </section> |
al@399 | 440 |
al@399 | 441 </section> |
pascal@320 | 442 EOT |
pascal@320 | 443 ;; |
pascal@320 | 444 esac |
pascal@320 | 445 |
pascal@320 | 446 xhtml_footer |
pascal@320 | 447 exit 0 |