Imported Debian patch 2.5.0-1 debian/2.5.0-1
authorBdale Garbee <bdale@gag.com>
Mon, 3 Apr 2006 07:28:17 +0000 (00:28 -0700)
committerBdale Garbee <bdale@gag.com>
Tue, 20 May 2008 04:47:04 +0000 (22:47 -0600)
311 files changed:
AUTHORS
ChangeLog
Makefile.am
Makefile.in
NEWS
README
acinclude.m4
amplot/Makefile.am
amplot/Makefile.in
autogen [new file with mode: 0755]
changer-src/Makefile.am
changer-src/Makefile.in
changer-src/chg-disk.sh.in
changer-src/chg-multi.sh.in
changer-src/chg-scsi-chio.c
changer-src/chg-scsi.c
changer-src/libscsi.h
changer-src/scsi-aix.c
changer-src/scsi-bsd.c
changer-src/scsi-cam.c
changer-src/scsi-changer-driver.c
changer-src/scsi-chio.c
changer-src/scsi-hpux.c
changer-src/scsi-hpux_new.c
changer-src/scsi-irix.c
changer-src/scsi-linux.c
changer-src/scsi-solaris.c
changer-src/sense.c
client-src/Makefile.am
client-src/Makefile.in
client-src/amandad-krb4.c [deleted file]
client-src/amandad.c
client-src/amandad.h [new file with mode: 0644]
client-src/amandates.c
client-src/amqde.c [deleted file]
client-src/calcsize.c
client-src/client_util.c
client-src/client_util.h
client-src/findpass.c
client-src/findpass.h
client-src/getfsent.c
client-src/getfsent.h
client-src/killpgrp.c
client-src/noop.c [new file with mode: 0644]
client-src/rundump.c
client-src/runtar.c
client-src/selfcheck.c
client-src/sendbackup-dump.c
client-src/sendbackup-gnutar.c
client-src/sendbackup-krb4.c [deleted file]
client-src/sendbackup-krb4.h [deleted file]
client-src/sendbackup.c
client-src/sendbackup.h
client-src/sendsize.c
client-src/versionsuffix.c
common-src/Makefile.am
common-src/Makefile.in
common-src/alloc.c
common-src/amanda.h
common-src/amfeatures.c
common-src/amfeatures.h
common-src/amflock.c
common-src/amregex.h
common-src/arglist.h
common-src/bsd-security.c [new file with mode: 0644]
common-src/clock.c
common-src/clock.h
common-src/debug.c
common-src/dgram.c
common-src/dgram.h
common-src/error.c
common-src/event.c [new file with mode: 0644]
common-src/event.h [new file with mode: 0644]
common-src/file.c
common-src/fileheader.c
common-src/fileheader.h
common-src/genversion.c
common-src/getcwd.c
common-src/krb4-security.c
common-src/krb4-security.h [deleted file]
common-src/krb5-security.c [new file with mode: 0644]
common-src/match.c
common-src/packet.c [new file with mode: 0644]
common-src/packet.h [new file with mode: 0644]
common-src/pipespawn.c
common-src/pipespawn.h
common-src/protocol.c
common-src/protocol.h
common-src/queue.h [new file with mode: 0644]
common-src/rsh-security.c [new file with mode: 0644]
common-src/security.c
common-src/security.h [new file with mode: 0644]
common-src/sl.c
common-src/sl.h
common-src/snprintf.c
common-src/ssh-security.c [new file with mode: 0644]
common-src/statfs.c
common-src/stream.c
common-src/stream.h
common-src/strerror.c
common-src/strstr.c
common-src/tapelist.c [new file with mode: 0644]
common-src/tapelist.h [new file with mode: 0644]
common-src/token.c
common-src/token.h
common-src/util.c
common-src/util.h
common-src/version.c
common-src/version.h
common-src/versuff.c
common-src/versuff.c.in
common-src/writev.c [new file with mode: 0644]
config/Makefile.in
config/acinclude.m4i
config/config.guess
config/config.h.in
config/config.sub
config/libtool.m4i
config/ltmain.sh
configure
configure.in
contrib/gsc/README [new file with mode: 0644]
contrib/gsc/cfggsc.c [new file with mode: 0644]
contrib/gsc/defgsc.c [new file with mode: 0644]
contrib/gsc/gsc.add [new file with mode: 0644]
contrib/gsc/gscdd.c [new file with mode: 0644]
contrib/gsc/gscdds.h [new file with mode: 0644]
contrib/gsc/makefile [new file with mode: 0644]
contrib/gsc/tstinq.c [new file with mode: 0644]
contrib/gsc/ucfggsc.c [new file with mode: 0644]
contrib/set_prod_link.pl
contrib/sst/Makefile
contrib/sst/sst.c
debian/amanda-client.files
debian/amanda-client.lintian
debian/amanda-common.dirs
debian/amanda-common.lintian
debian/amanda-server.files
debian/amanda-server.lintian
debian/changelog
debian/control
debian/rules
docs/Makefile.in
docs/kerberos.txt
docs/y2k.txt
dumper-src/Makefile.am [new file with mode: 0644]
dumper-src/Makefile.in [new file with mode: 0644]
dumper-src/generic-dumper.pl.in [new file with mode: 0644]
dumper-src/gnutar.pl.in [new file with mode: 0644]
example/Makefile.am
example/Makefile.in
example/amanda.conf.chg-scsi.in [deleted file]
example/amanda.conf.in
example/chg-mcutil.conf
example/chg-scsi-hpux.conf.in [deleted file]
example/chg-scsi-linux.conf.in [deleted file]
example/chg-scsi-solaris.conf.in [deleted file]
man/Makefile.am
man/Makefile.in
man/amadmin.8
man/amaespipe.8 [new file with mode: 0644]
man/amanda.8
man/amanda.conf.5
man/amcheck.8
man/amcheckdb.8
man/amcleanup.8
man/amcrypt.8 [new file with mode: 0644]
man/amdd.8
man/amdump.8
man/amfetchdump.8 [new file with mode: 0644]
man/amflush.8
man/amgetconf.8
man/amlabel.8
man/ammt.8
man/amoverview.8
man/amplot.8
man/amrecover.8
man/amreport.8
man/amrestore.8
man/amrmtape.8
man/amstatus.8
man/amtape.8
man/amtapetype.8
man/amtoc.8
man/amverify.8
man/amverifyrun.8
man/entities/global.entities [new file with mode: 0644]
man/entities/xinclude.dtd [new file with mode: 0644]
man/xml-source/amadmin.8.xml [new file with mode: 0644]
man/xml-source/amaespipe.8.xml [new file with mode: 0755]
man/xml-source/amanda.8.xml [new file with mode: 0644]
man/xml-source/amanda.conf.5.xml [new file with mode: 0644]
man/xml-source/amcheck.8.xml [new file with mode: 0644]
man/xml-source/amcheckdb.8.xml [new file with mode: 0644]
man/xml-source/amcleanup.8.xml [new file with mode: 0644]
man/xml-source/amcrypt.8.xml [new file with mode: 0755]
man/xml-source/amdd.8.xml [new file with mode: 0644]
man/xml-source/amdump.8.xml [new file with mode: 0644]
man/xml-source/amfetchdump.8.xml [new file with mode: 0644]
man/xml-source/amflush.8.xml [new file with mode: 0644]
man/xml-source/amgetconf.8.xml [new file with mode: 0644]
man/xml-source/amlabel.8.xml [new file with mode: 0644]
man/xml-source/ammt.8.xml [new file with mode: 0644]
man/xml-source/amoverview.8.xml [new file with mode: 0644]
man/xml-source/amplot.8.xml [new file with mode: 0644]
man/xml-source/amrecover.8.xml [new file with mode: 0644]
man/xml-source/amreport.8.xml [new file with mode: 0644]
man/xml-source/amrestore.8.xml [new file with mode: 0644]
man/xml-source/amrmtape.8.xml [new file with mode: 0644]
man/xml-source/amstatus.8.xml [new file with mode: 0644]
man/xml-source/amtape.8.xml [new file with mode: 0644]
man/xml-source/amtapetype.8.xml [new file with mode: 0644]
man/xml-source/amtoc.8.xml [new file with mode: 0644]
man/xml-source/amverify.8.xml [new file with mode: 0644]
man/xml-source/amverifyrun.8.xml [new file with mode: 0644]
man/xslt/expand-sambadoc.xsl [new file with mode: 0644]
man/xslt/man.xsl [new file with mode: 0644]
man/xslt/settings.xsl [new file with mode: 0644]
patches/tar-1.12.patch
recover-src/Makefile.am
recover-src/Makefile.in
recover-src/amrecover.c
recover-src/amrecover.h
recover-src/display_commands.c
recover-src/extract_list.c
recover-src/help.c
recover-src/set_commands.c
recover-src/uparse.y
recover-src/uscan.c
recover-src/uscan.l
regex-src/cclass.h
regex-src/cname.h
regex-src/debug.c
regex-src/engine.c
regex-src/main.c
regex-src/regcomp.c
regex-src/regerror.c
regex-src/regexec.c
restore-src/Makefile.am
restore-src/Makefile.in
restore-src/amfetchdump.c [new file with mode: 0644]
restore-src/amidxtaped.c
restore-src/amrestore.c
restore-src/restore.c [new file with mode: 0644]
restore-src/restore.h [new file with mode: 0644]
server-src/Makefile.am
server-src/Makefile.in
server-src/amadmin.c
server-src/amaespipe.sh.in [new file with mode: 0755]
server-src/amcheck.c
server-src/amcleanupdisk.c
server-src/amcrypt.sh.in [new file with mode: 0755]
server-src/amflush.c
server-src/amindex.c
server-src/amindex.h
server-src/amindexd.c
server-src/amlabel.c
server-src/amlogroll.c
server-src/amoverview.pl.in
server-src/amstatus.pl.in
server-src/amtape.c
server-src/amtoc.pl.in
server-src/amtrmidx.c
server-src/amtrmlog.c
server-src/amverify.sh.in
server-src/changer.c
server-src/changer.h
server-src/chunker.c [new file with mode: 0644]
server-src/conffile.c
server-src/conffile.h
server-src/disk_history.c
server-src/disk_history.h
server-src/diskfile.c
server-src/diskfile.h
server-src/driver.c
server-src/driverio.c
server-src/driverio.h
server-src/dumper-krb4.c [deleted file]
server-src/dumper.c
server-src/find.c
server-src/find.h
server-src/getconf.c
server-src/holding.c
server-src/holding.h
server-src/infofile.c
server-src/infofile.h
server-src/list_dir.c
server-src/list_dir.h
server-src/logfile.c
server-src/logfile.h
server-src/planner.c
server-src/reporter.c
server-src/server_util.c
server-src/server_util.h
server-src/tapefile.c
server-src/tapefile.h
server-src/taper.c
server-src/taperscan.c [new file with mode: 0644]
server-src/taperscan.h [new file with mode: 0644]
tape-src/Makefile.am
tape-src/Makefile.in
tape-src/ammt.c
tape-src/output-file.c
tape-src/output-file.h
tape-src/output-null.c
tape-src/output-null.h
tape-src/output-tape.c
tape-src/output-tape.h
tape-src/tapeio.c
tape-src/tapeio.h
tape-src/tapetype.c

diff --git a/AUTHORS b/AUTHORS
index 503d58a07ae8b0961960a70c646a32e0640d7079..1c7e95f924249df2907f82b5e885c1f470f07153 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,5 +1,5 @@
 This file lists the current members of the Amanda Development Team,
-i.e., people who have write access to the sources of Amanda.
+i.e., people who have write access to the sources of Amanda. 
 
 Please avoid sending e-mail with Amanda-related questions directly to
 them; your questions are likely to be answered much faster if you post
@@ -42,5 +42,13 @@ and supporter
 
 - Stefan G. Weichinger <monitor@oops.co.at>: documentation, active supporter
 
+- John Franks (jrfranks@zmanda.com>: active developer and supporter
+
+- Paddy Sreenivasan (paddy@zmanda.com>: active developer and supporter
+
+- Kevin Till (kevin.till@zmanda.com>: active developer and supporter
+
+- Ian Turner (ian@zmanda.com>: active developer and supporter
+
 Many other people have contributed to the development of Amanda; check
 the ChangeLog for their names and e-mail addresses.
index db19ab8e25c082666d32d95fe04f5d14b502f6c1..4da905bfe5187d0411b059ec3eabd756ea5ff476 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2006-03-28  Jean-Louis Martineau <martineau@zmanda.com>
+       * Amanda 2.5.0 released.
+       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.5.0).
+       * NEWS: Update for 2.5.0
+
+2006-03-22  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/dumper.c: wait for compress/index/encryp subprocess.
+
+2006-03-22  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/amstatus.pl.in: Parse PARTIAL reply.
+
+2006-03-22  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/driver.c: Put '#define HOLD_DEBUG' in comment.
+
+2006-03-21  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/chunker.c: Don't loop on startup_chunker.
+       * server-src/dumper.c: Don't wait for all children, some process (ssh)
+         might not terminate.
+
+2006-03-17  Ian Turner <ian@zmanda.com>
+       * server-src/taper.c (read_file): When finished flushing a 
+         chunked dump, print information about the whole dump, not just 
+         the last chunk. Also, fix some memory leaks.
+
+2006-03-16  Kevin Till <ktill@zmanda.com>
+       * server-src/amverify.sh.in: check for EOI. amrestore only 
+         reports EOI for some tapetypes.
+
+2006-03-15  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/conffile.c: Fix heritage of auth.
+
+2006-03-14  Kevin Till <ktill@@zmanda.com>
+       * example/amanda.conf.in: add dumptype custom-compress. 
+         add ssh,krb5 as valid input for auth. 
+        * man/xml-source/amanda.conf.5.xml: give reference to 
+         custom-compress, encrypt-fast dumptypes.
+
+2006-03-14  Jean-Louis Martineau <martineau@zmanda.com>
+       * common-src/amfeatures.h: Rename fe_amidxtaped_FEEDME to
+                                         fe_amrecover_FEEDME
+       * common-src/amfeatures.c (am_init_feature_set): Set
+                                                        fe_amrecover_FEEDME.
+       * restore-src/restore.h (search_tapes): Add their_features parameter.
+       * restore-src/amfetchdump.c: Add NULL pointer to search_tapes call.
+       * restore-src/amidxtaped.c: Add their_features to search_tapes call.
+       * restore-src/restore.c (search_tapes): Send FEEDME only if client
+                                               support it.
+
+2006-03-11  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/driverio.c : Fix errors found using Coverity tools.
+
+2006-03-10  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/taperscan.c: Fix Coverity fix.
+
+2006-03-10  Jean-Louis Martineau <martineau@zmanda.com>
+       * changer-src/scsi-changer-driver.c:
+                                        Fix errors found using Coverity tools.
+       * server-src/diskfile.c: Fix errors found using Coverity tools.
+       * server-src/planner.c: Fix errors found using Coverity tools.
+       * server-src/taperscan.c: Fix errors found using Coverity tools.
+
+2006-03-10  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/driverio.c: Undo my bad fix.
+       * server-src/infofile.c: Fix errors found using Coverity tools.
+       * tape-src/tapetype.c: Fix errors found using Coverity tools.
+
+2006-03-09  Jean-Louis Martineau <martineau@zmanda.com>
+       * restore-src/restore.c: Fix errors found using Coverity tools.
+
+2006-03-09  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/holding.c: Fix John fix.
+
+2006-03-09  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/driverio.c: Fix errors found using Coverity tools.
+       * server-src/planner.c: Fix John fix.
+
+2006-03-09  John Franks <jrfranks@zmanda.com>
+       * changer-src/chg-scsi.c:        Fix errors found using Coverity tools.
+       * changer-src/scsi-changer-driver.c:
+                                        Fix errors found using Coverity tools.
+       * changer-src/sense.c:           Fix errors found using Coverity tools.
+       * client-src/sendbackup-dump.c:  Fix errors found using Coverity tools.
+       * client-src/sendbackup.c:       Fix errors found using Coverity tools.
+       * recover-src/display_commands.c:Fix errors found using Coverity tools.
+       * regex-src/regcomp.c:           Fix errors found using Coverity tools.
+       * restore-src/restore.c:         Fix errors found using Coverity tools.
+       * server-src/amindexd.c:         Fix errors found using Coverity tools.
+       * server-src/diskfile.c:         Fix errors found using Coverity tools.
+       * server-src/driver.c:           Fix errors found using Coverity tools.
+       * server-src/driverio.c:         Fix errors found using Coverity tools.
+       * server-src/infofile.c:         Fix errors found using Coverity tools.
+       * server-src/planner.c:          Fix errors found using Coverity tools.
+       * server-src/taper.c:            Fix errors found using Coverity tools.
+       * server-src/taperscan.c:        Fix errors found using Coverity tools.
+       * server-src/conffile.c:         Change report default to use at least
+                                        one space between every column.
+
+2006-03-08  Jean-Louis Martineau <martineau@zmanda.com>
+       * client-src/amandad.c: Fix coverity bug.
+       * client-src/calcsize.c: Fix coverity bug.
+       * client-src/client_util.c: Fix coverity bug.
+       * client-src/sendbackup.c: Fix coverity bug.
+       * client-src/sendsize.c: Fix coverity bug.
+       * common-src/bsd-security.c: Fix coverity bug.
+       * common-src/file.c: Fix coverity bug.
+       * common-src/fileheader.c: Fix coverity bug.
+       * common-src/pipespawn.c: Fix coverity bug.
+       * recover-src/extract_list.c: Fix coverity bug.
+       * restore-src/restore.c: Fix coverity bug.
+       * server-src/amindexd.c: Fix coverity bug.
+       * server-src/conffile.c: Fix coverity bug.
+       * server-src/diskfile.c: Fix coverity bug.
+       * server-src/driverio.c: Fix coverity bug.
+       * server-src/dumper.c: Fix coverity bug.
+       * server-src/planner.c: Fix coverity bug.
+       * server-src/reporter.c: Fix coverity bug.
+
+2006-03-07  Paddy Sreenivasan <paddy@zmanda.com>
+       * man/xml-source/amanda.8.xml: added amaespipe and amcrypt.
+
+2006-03-07  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/taper.c: Don't log a multi-line message in no-tape case.
+
+2006-03-06  John Franks <jrfranks@zmanda.com>
+       * recover-src/extract_list.c:
+         1) Don't add '.' directory twice to tar extract list.
+         2) Don't prepend extra '/' to extract patterns starting with '/'.
+          3) Convert "/" extract pattern to "*" equivalent.
+
+2006-03-06  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/taperscan.c (scan_slot): append slotstr to
+         ct->error_message.
+       * server-src/taperscan.c: Add a '\n' after each slot error message.
+
+2006-03-06  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/reporter.c (handle_error): Handle error from taper.
+
+2006-03-06  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/taper.c (label_tape): Set errstr and return 0 if no
+         valid tape are available.
+
+2006-03-03  Ian Turner <ian@zmanda.com>
+       * common-src/amanda.h: New macros MAX_TAPE_LABEL_LEN and 
+         MAX_TAPE_LABEL_BUF.
+       * common-src/amfeatures.h: New amfeature fe_amidxtaped_FEEDME
+       * recover-src/extract_list.c: Accept port number with CONNECT; 
+         implement fe_amidxtaped_FEEDME.
+       * restore-src/amidxtaped.c: Introduce port number with CONNECT. 
+         (closes SF bug 1431623)
+       * restore-src/restore.c: Implement fe_amidxtaped_FEEDME.
+         (closes SF bug 1421433)
+       * restore-src/restore.h: Properly name rst_flags.
+
+2006-02-28  Jean-Louis Martineau <martineau@zmanda.com>
+       * common-src/bsd-security.c (bsd_connect, netfd_read_callback, main):
+         Set bh->proto_handle to NULL after allocating bh.
+       * common-src/bsd-security.c (bsd_close): Donothing if
+         bh->proto_handle == NULL.
+
+2006-02-28  Jean-Louis Martineau <martineau@zmanda.com>
+       * common-src/protocol.c (s_repwait): Decrease p->timeout on receive
+                                            of a PREP.
+
+2006-02-28  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/driver.c: Print dumper TRY_AGAIN message.
+
+2006-02-28  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/planner.c: Don't print estimate size if estimate failed.
+
+2006-02-25  Ian Turner <ian@zmanda.com>
+       * man/Makefile.am: Don't use static patterns (as they are not 
+         portable), use implicit rules instead.
+
+2006-02-20  Kevin Till <ktill@zmanda.com>
+       * common-src/krb4-security.c: changes needed for krb4/5 to compile. Thanks to
+                                     Orion Poplawski.
+       * common-src/krb5-security.c: ditto.
+
+2006-02-16  Kevin Till <ktill@zmanda.com>
+       * example/amanda.conf.in: dumptype option is "encrypt"
+       * man/xml-source/amanda.conf.5.xml: ditto
+       * server-src/holding.c: util.h is include'd twice
+       * common-src/ssh-security.c: set correct debug print 
+
+2006-02-10  Kevin Till <ktill@zmanda.com>
+       * man/xml-source/amanda.8.xml: replace informaltable with literallayout 
+
+2006-02-13  John Franks <jrfranks@zmanda.com>
+       * server-src/driver.c: Pring a more precise message when taper
+         returns an error.  Include error message from taper in log.
+         Print out "protocol error" if taper returns a bogus command.
+
+2006-02-10  Kevin Till <ktill@zmanda.com>
+       * man/xml-source/amanda.conf.5.xml: add note about first character of a 
+                       tapetype string must be alphabet
+
+2006-02-10  John Franks <jrfranks@zmanda.com>
+       * server-src/taper.c: Call error() if an invalid string is read
+         by syncpipe_getstr().
+2006-02-09  John Franks <jrfranks@zmanda.com>
+       * Makefile.am, */Makefile.am:  Corrections generated by David Braun
+         dustybird@users.sourceforge.net to properly set source directories
+         for remote (VPATH) builds.
+       * man/Makefile.am:  Fixed man page builds to use proper source and
+         build paths.
+       * autogen: Force rebuilding everything and print only syntax errors.
+         (Errors are seen occasionally in system autogen files...)
+       * configure.in: Eliminate possibility of empty string in shell tests.
+         fix quoting of '[' and ']' characters in help messages.
+         Fix default value for DUMPER_DIR to pick up EPREFIX correctly.
+2006-02-08  Ian Turner <ian@zmanda.com>
+       * server-src/driver.c (handle_taper_result): Properly handle 
+         SPLIT_NEEDNEXT case. Thanks to Josef Wolf for finding this bug.
+         Also reindent.
+
+2006-02-06 Kevin Till <ktill@zmanda.com> 
+       * restore-src/restore.c: fix comment formatting on version 1.2.1
+
+2006-02-06 Kevin Till <ktill@zmanda.com>
+       * configure.in: Bug 1423731, SSH_SECURITY set only when --with-ssh-security used
+       * server-src/Makefile.am:: not to install planner/dumper setuid-root --with-ssh-security
+       * server-src/amcheck.c:    ditto
+       * server-src/dumper.c:     ditto
+       * restore-src/restore.c:    add missing "}"
+       
+2006-02-06  Ian Turner <ian@zmanda.com>
+       * restore-src/amidxtaped.c: Properly handle changers, 
+         tape-label checking, and tape prompting in amrecover, 
+         amindexd, and amidextaped. Thanks to Paul Bijnens 
+         <pbijnens@users.sourceforge.net> for the patch.
+       * restore-src/restore.c: ditto.
+       * server-src/amindexd.c: ditto.
+
+2006-02-04  Paddy Sreenivasan <paddy@zmanda.com>
+        * man/xml-source/amfetchdump.8.xml
+        * man/xml-source/amcrypt.8.xml
+        * man/xml-source/amanda.conf.5.xml
+        * man/xml-source/amanda.8.xml
+        * man/xml-source/amaespipe.8.xml
+        * man/entities/global.entities: Merged changes from xml-docs tree
+
+2006-02-03  John Franks <jrfranks@zmanda.com>
+       * server-src/taper.c: Fix null string printout in CHUNKERSUCCESS log line.
+
+2006-02-03  Ian Turner <ian@zmanda.com>
+       * server-src/amadmin.c (main): Don't free conf_tapelist too 
+         early. Thanks to Cédric Lucantis
+         <cedric-lucantis@users.sourceforge.net> for the patch.
+
+2006-02-02 Kevin Till <ktill@zmanda.com>
+       * man/xml-source/amanda.8.xml: fix formatting. <informaltable> problem 
+                                      to be fixed.
+       * man/xml-source/amrecover.8.xml: add note on client-encrypted tapes.
+
+2006-02-02  Ian Turner <ian@zmanda.com>
+       * recover-src/extract_list.c (extract_files_child): Run tar with 
+         --numeric-owner if we are extracting a non-sambafied tar file. 
+         Thanks to Paul Bijnens <pbijnens@users.sourceforge.net> for 
+         the patch. Thanks also to Mark Schaefer for suggesting this 
+         change.
+
+2006-02-01  Jean-Louis Martineau <martineau@zmanda.com>
+       * restore-src/restore.c: Use OFF_T_FMT to printf off_t variable,
+         cast size_t to am64_t and use AM64_FMT to printf them.
+
+2006-01-31  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/driver.c (dumper_result): Reset sched(dp)->attempted to 0
+         before adding it to tapeq.
+
+2006-01-27  Ian Turner <ian@zmanda.com>
+       * configure.in: Add new option --without-xsltproc (and
+         --with-xsltproc), which turns off (or forces) the use of xsltproc to
+         build manpages. Thanks to Paul Bijnens
+         <pbijnens@users.sourceforge.net> for suggesting this feature.
+
+2006-01-27  Ian Turner <ian@zmanda.com>
+       * restore-src/amfetchdump.c: Properly clean up logfiles. Also, 
+         run as user amanda even if we are started as some other user.
+         Thanks to Paul Bijnens <pbijnens@users.sourceforge.net> for the 
+         patch.
+
+2006-01-25  Paddy Sreenivasan <paddy@zmanda.com>
+        * common-src/amanda.h:     Removed unnecessary header include files.
+
+2006-01-25  Kevin Till<ktill@zmanda.com>
+       * server-src/amadmin.c: fix for sourceforge bug 1412698
+                               add missing parameters to "amadmin x disklist"
+       * server-src/amstatus.pl.in: untaint user input, enforce known path.
+       * server-src/amoverview.pl.in: untaint user input (bug 1353481)
+
+2006-01-25  Kevin Till<ktill@zmanda.com>
+       * man/xml-source/amanda.conf.5.xml: fix formatting (<para> is not compatible 
+                                           with some tag) add supported auth types.
+
+2006-01-25  Kevin Till<ktill@zmanda.com>
+       * common-src/bsd-security.c: move check_security to bsd_security.c, 
+                                     fix faulty return
+                                    Thanks to Paul Bijnens
+       * restore-src/amidxtaped.c:  ditto
+       * server-src/amindexd.c:     ditto and no need to tell client 
+                                     about reason for denial
+       * common-src/amanda.h:       add proto of check_security
+       * server-src/conffile.c:     don't list CRYPT in the summary report 
+                                     for now
+       * restore-src/restore.c:     set outfd correctly for amfetchdump cases
+                                    Thanks to Paul Bijnens
+
+2006-01-24  Ian Turner <ian@zmanda.com>
+       * man/xml-source/amanda.conf.5.xml: Put documentation of 
+         split-dump options in the right place. Thanks to Paul Bijnens 
+         <pbijnens@users.sourceforge.net> for the fix.
+       * man/xml-source/amanda.8.xml: ditto.
+
+2006-01-23  Ian Turner <ian@zmanda.com>
+       * server-src/taperscan.c (find_brand_new_tape_label): Start 
+         brand new tape labels at 1 instead of 0. Thanks to Paul 
+         Bijnens <pbijnens@users.sourceforge.net> for the fix.
+
+2006-01-18  Jean-Louis Martineau <martineau@zmanda.com>
+       * Amanda 2.5.0b2 released.
+       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.5.0b2).
+       * NEWS: Update for 2.5.0b2
+       
+2006-01-15  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/disk_history.c: Fix memory leak.
+
+2006-01-15  Jean-Louis Martineau <martineau@zmanda.com>
+       * common-src/bsd-security.c: Fix memory leak.
+       * common-src/tapelist.c: Fix memory leak.
+       * restore-src/amidxtaped.c: Fix memory leak.
+       * restore-src/restore.c: Fix memory leak.
+       * server-src/amindexd.c: Fix memory leak.
+       * server-src/conffile.c: Fix memory leak.
+       * server-src/disk_history.c: Fix memory leak.
+       * server-src/find.c: Fix memory leak.
+
+2006-01-13  John Franks <jrfranks@zmanda.com>
+       * client-src/amandad.c:      Remove SO_LINGER and TCP_NDELAY.
+                                    Loop on I/O if EINTR or EAGAIN.
+       * client-src/noop.c:         Loop on I/O if EINTR or EAGAIN.
+       * client-src/sendbackup.c:   Remove SIGPIPE handler.
+                                    Loop on I/O if EINTR or EAGAIN.
+                                    Check for EPIPE on writes.
+       * common-src/bsd-security.c: Loop on I/O if EINTR or EAGAIN.
+       * common-src/stream.c:       Remove SO_LINGER and TCP_NDELAY.
+       * common-src/util.c:         Loop on I/O if EINTR or EAGAIN.
+       * recover-src/amrecover.c:   Write commanda atomically in sigint handler
+       * recover-src/extract_list.c:Remove SIGPIPE handler.
+                                    Loop on I/O if EINTR or EAGAIN.
+                                    Check for EPIPE on writes.
+                                    Remove shutdown functions.
+       * restore-src/amfetchdump.c: Remove SIGPIPE handler.
+       * restore-src/amidxtaped.c:  Remove SO_LINGER and TCP_NDELAY.
+                                    Remove SIGPIPE handler.
+                                    read_file_header does not return if it
+                                    Fix infinite loop on EOF or error and
+                                    fail if memory reallocation failure in
+                                    get_client_line_fd.
+       * restore-src/restore.c:     Remove SIGPIPE handler.
+                                    Loop on I/O if EINTR or EAGAIN.
+                                    Remove shutdown functions.
+                                    Simplify read loop.
+       * restore-src/restore.h:     Change read_file_header to return void
+       * server-src/amcheck.c:      Use fullread() to handel EINTR etc.
+                                    Remove unused variable.
+       * server-src/changer.c:      Remove SO_LINGER and TCP_NDELAY.
+                                     Use fullwrite on socket.
+       * server-src/driverio.c:     Remove SO_LINGER and TCP_NDELAY.
+       * server-src/taper.c:        Use fullwrite() to write data.
+                                    Use fullread() to read data.
+       * tape-src/output-file.c;    Use fullwrite() to write data.
+
+2006-01-13  Jean-Louis Martineau <martineau@zmanda.com>
+       * server-src/amcheck.c (start_server_check): Remove unused variable
+         errstr.
+       * restore-src/restore.c (restore): Remove unused variable s, l and
+         dataeof.
+
+2006-01-12  Jean-Louis Martineau <martineau@zmanda.com>
+       * recover-src/extract_list.c (send_to_tape_server): Do only on write.
+       * restore-src/amidxtaped.c (get_client_line_fd): New function to read
+         one complete line from an fd.
+
+2006-01-09  John Franks <jrfranks@zmanda.com>
+       * common-src/amanda.h:  Include tcp.h
+       * client-src/amandad.c: Set TCP_NODELAY and SO_LINGER on sockets.
+       * common-src/dgram.c:   No linger on datagrams
+       * common-src/stream.c:  Set TCP_NODELAY and SO_LINGER on sockets.
+       * common-src/util.c:    Fix fullwrite to return # of bytes written
+                               before failure.
+       * example/amanda.conf.in: Cleanup exclude list template.
+                               Use configure directlries instead of /usr/local
+       * recover-src/extract_list.c: Cleanup read loops.
+                               Use real fullwrite instead of inline versions.
+                               Remove extra setting of LINGER on socket.
+       * restore-src/amidxtaped.c: Set TCP_NODELAY and SO_LINGER on sockets.
+       * restore-src/restore.c:Use real fullwrite instead of inline versions.
+       * server-src/changer.c: Set TCP_NODELAY and SO_LINGER on sockets.
+       * server-src/chunker.c: Use real fullwrite instead of inline versions.
+       * server-src/driverio.c:Set TCP_NODELAY and SO_LINGER on sockets.
+       * server-src/dumper.c:  Use real fullwrite instead of inline versions.
+
+2006-01-09  Ian Turner <ian@zmanda.com>
+       * changer-src/scsi-changer-driver.c: If there is a problem opening
+         the device during GenericRewind, don't retry for 201 minutes; give
+         up after only 200 seconds.
+
+2006-01-09  Ian Turner <ian@zmanda.com>
+       * server-src/taperscan.c: When doing taper-scan algorithm, properly
+         accept new tapes.
+
+2006-01-09  Ian Turner <ian@zmanda.com>
+       * tape-src/tapeio.c: Generate a more reasonable message when
+       reading an empty tape label on brand-new tapes.
+
+2006-01-09  Ian Turner <ian@zmanda.com>
+       * server-src/amcheck.c: Actually do what the documentation for 
+         amcheck -w says; that is, overwrite labels on tapes.
+
+2006-01-06  Kevin Till<ktill@zmanda.com>
+       * server-src/amcheck.c: check if encrypt or compress program is 
+         executable. Check encrypt/compress configuration.
+       * server-src/dumper.c: kill encrypt child when dump is stopped
+       * server-src/amcrypt.sh.in: check for aespipe
+       * server-src/amaespipe.sh.in: adjust PATH
+       * man/xml-source/amtapetype.8.xml: fix format problem.
+
+2006-01-06  Jean-Louis Martineau <martineau@zmanda.com>
+       * recover-src/extract-list.c: Remove 'U' argument for gtar extraction.
+
+2006-01-06  Jean-Louis Martineau <martineau@zmanda.com>
+       * restore-src/restore.c (flush_open_outputs): Another shutdown is
+         required.
+
+2006-01-05  John Franks <jrfranks@zmanda.com>
+       * recover-src/extract_list.c: Extend linger timeouts to 60 seconds.
+          Use shutdown() on sockets.
+         Retry reads in case of EINTR or EAGAIN.
+       * common-src/stream.c: set linger on correct socket.
+         Extend linger timeouts to 60 seconds.
+       * restore-src/restore.c: Fix compiler warnings.
+       * Call shutdown in more cases.
+
+2006-01-05  John Franks <jrfranks@zmanda.com>
+       * client-src/amandad.c: Set SO_LINGER on sockets.
+       * common-src/dgram.c:   Set SO_LINGER on sockets.
+       * common-src/stream.c:  Set SO_LINGER on sockets.
+       * common-src/util.c:    Return any bytes already read on error or EOF.
+       * recover-src/extract_list.c: Set SO_LINGER on data socket.
+          Fix printf of unterminated string data.
+         Check return codes on socket header reads.
+       * restore-src/amidxtaped.c: Set SO_LINGER on sockets.
+         Check return codes on socket header reads.
+       * restore-src/restore.c:
+         Flush newline after operator prompt.
+       * common-src/debug.c:
+         Fix memory leak when debug file name already exists.
+         Print error text upon hard open() error.
+         Allow group members read only access to log files.
+
+2006-01-05  Kevin Till<ktill@zmanda.com>
+        * restore-src/restore.c: handle sigpipe. Some program (e.g. bzip2) closes reading pipe
+          early when it sees trailing garbage after EOF.
+
+2006-01-02  Jean-Louis Martineau <martineau@zmanda.com>
+       * common-src/amanda.h: Add a FD_COPY macro.
+       * recover-src/extract_list.c (writer_intermediary): Don't use
+         writer_intermediary, do the select locally.
+
+2006-01-02  Jean-Louis Martineau <martineau@zmanda.com>
+       * restore-src/restore.c (flush_open_outputs): Call shutdown before
+         close.
+
+2005-12-30  John Franks <jrfranks@zmanda.com>
+       * recover-src/extract_list.c:
+         Fix double clearing of buffer during normal read path.
+       * restore-src/amidxtaped.c
+         Actually initialize changer if it is needed.  (Set use_changer
+          before checking it...)
+        * Fix control messages being sent down the data pipe when
+          restoring to client that does not support split dumps.
+        * Print error and exit if a split dump is needed during restore
+         and client can not handle it. 
+
+2005-12-30  Ian Turner <ian@zmanda.com>
+       * common-src/fileheader.c: Remove xx/UNKNOWN split-dump header 
+         syntax, in favor of xx/-1.
+
+2005-12-29  John Franks <jrfranks@zmanda.com>
+       * Index: recover-src/display_commands.c
+         Fix list deletion which did not update list root with NULL pointer.
+         Make free_dir_item() a non-recursive function to prevent stack bloat.
+         Fix list insertion code which inserts item in list initializes entry.
+       * Index: recover-src/extract_list.c
+         Fix to initialize lditem before using it...
+         Prevent multiple frees of cmd string.
+         Do not free err which is only initialized with static string pointers.
+         Fix typo which caused newstralloc() to free the wrong memory.
+       * Index: server-src/amindexd.c
+         Fix Compiler warning of unused variable.
+       * Index: server-src/taperscan.c
+         Fix Compiler warning of bogus format specifier.
+  
+2005-12-29  Kevin Till<ktill@zmanda.com>
+       * man/xml-source/amcrypt.8.xml: add new amcrypt man page
+       * man/xml-source/amaespipe.8.xml: add new amaespipe man page
+
+2005-12-29  Ian Turner <ian@zmanda.com>
+       * man/xml-source/amanda.conf.5.xml: Document label_new_tapes 
+         config option.
+
+2005-12-28  Ian Turner <ian@zmanda.com>
+       * recover-src/amrecover.h: Use dynamic strings in struct DIR_ITEM.
+       * recover-src/display_commands.c: ditto
+       * recover-src/extract_list.c: ditto. Also use dynamic strings in
+         struct EXTRACT_LIST and struct EXTRACT_LIST_ITEM.
+
+2005-12-28  Ian Turner <ian@zmanda.com>
+       * common-src/amfeatures.h: Add three new amfeatures:
+         fe_amindexd_marshall_in_OLSD, fe_amindexd_marshall_in_ORLD,
+         fe_amindexd_marshall_in_DHST.
+       * common-src/amfeatures.c: ditto.
+       * server-src/amindexd.c: Talk well to older clients.
+
+2005-12-23  Ian Turner <ian@zmanda.com>
+       * server-src/taperscan.c: Don't crash if find_brand_new_tape_label
+         returns NULL. Also, don't return NULL from
+         find_brand_new_tape_label without a good excuse.
+       
+2005-12-23  Kevin Till <ktill@zmanda.com>
+       * client-src/client_util.c: change server_decrypt_option to
+         server-decrypt-option
+       * client-src/sendbackup.c:  change client_decrypt_option to
+         client-decrypt-option
+       * server-src/dumper.c:      ditto
+       * common-src/amfeatures.c:  add crypt related amfeaturs
+       * common-src/amfeatures.h:  ditto  
+       * server-src/diskfile.c:    amfeatures checking and warns on
+         mis-configuration
+
+2005-12-23  Paddy Sreenivasan <paddy@zmanda.com>
+         * restore-src/restore.c:
+         * server-src/amtape.c:
+         * server-src/taperscan.c : Make scan_init static function
+
+2005-12-23  John Franks <jrfranks@zmanda.com>
+       * server-src/taper.c: Reduce I/O's system call overhead by 30%
+          in main read / write loop. 
+
+2005-12-23  John Franks <jrfranks@zmanda.com>
+       * recover-src/restore.c  Remove inapproriate aclose which caused
+          broken restore pipe.
+       * recover-src/extract_list.c  Fix and cleanup read_buffer()
+          mainly to fix hole that drops parital buffer of data if end
+          of file is reached or an error occured..  Touched up calling
+          functions to make sure EOF/timeouts are handled correctly.
+          Increased normal path read timeout value from on second to
+          whatever READ_TIMEOUT is set to.
+
+2005-12-22  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * restore-src/restore.c (restore): Remova an aclose.
+
+2005-12-22  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * restore-src/amidxtaped.c (cleanup): Function registered with atexit
+         to remove the log file.
+
+2005-12-20  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/Makefile.am (noinst_HEADERS): Add taperscan.h.
+
+2005-12-20  John Franks <jrfranks@zmanda.com>
+
+       * restore-src/restore.c: Remove unused variables.
+                                Fix uninitialize reference to bytes_read.
+       * server-src/amcheck.c:  Remove unused variables.
+                                Include taperscan.h for missing prototype.
+       * server-src/amtape.c:   Remove unused variables.
+                                Include taperscan.h for missing prototype.
+       * server-src/taper.c:    Remove unused variables.
+                                Minor indenting changes.
+       * server-src/taperscan.c:Remove unused variables.
+                                Fix typo which assigns NULL rather than
+                                 checks for NULL.
+                                Commented out reference to auto_pos which
+                                 is assigned but never used...
+
+2005-12-20  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * common-src/fileheader.c (parse_file_header): Parse '/' in part.
+       * common-src/fileheader.c (build_header): Add space ' ' before "part".
+
+2005-12-20  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/reporter.c: Fix report of output size.
+
+2005-12-19  Ian Turner <ian@zmanda.com>
+       * server-src/taperscan.c: Check that automatic tape labels satisfy
+       the labelstr.
+
+2005-12-19  Ian Turner <ian@zmanda.com>
+       * server-src/fileheader.c: Fix broken split-dump file headers.
+
+2005-12-18  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Paul Bijnens
+
+       * server-src/amcheck.c: Tapelist file is regular file.
+
+2005-12-17  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * restore-src/restore.c (get_block): Return a ssize_t.
+       * restore-src/restore.c: convert ssize_t to long for printing.
+       * restore-src/restore.c (restore>): Remove unused variable, outpipe,
+          outpipe2, i.
+
+2005-12-17  John R. Franks <jrfranks@zmanda.com>
+
+       * restore-src/restore.h (read_file_header, restore): Return a ssize_t
+         instead of using a global variable bytes_read.
+       * restore-src/restore.c: Use local variable instead of global
+         bytes_read. Many memory management fixe. Fixe pipe handling,
+       * restore-src/amrestore.c: Use new read_file_header and restore.
+       * restore-src/amfetchdump.c: Use new read_file_header and restore.
+
+2005-12-17  Jean-Louis Martineau <martineau@zmanda.com>
+       With Kevin Till <ktill@zmanda.com>
+
+       * common-src/fileheader.c (parse_file_header): Fix parsing of first
+         line.
+       * common-src/fileheader.c (build_header): Print crypt after programi
+          and only if it is needed.
+
+2005-12-14  Ian Turner <ian@zmanda.com>
+
+       * common-src/alloc.c: Add new function vstrextend, which extends an
+         existing string.
+       * common-src/amanda.h: Define vstrextend.
+       * example/amanda.conf.in: Document new option
+         label_new_tapes. Change default labelstr.
+       * man/xml-source/amcheck.8.xml: Emphasize the destructiveness of
+         amcheck -w.
+       * restore-src/restore.c: Use the new changer_find interface.
+       * server-src/Makefile.am: Add new file taperscan.c
+       * server-src/amcheck.c: Use the taper-scan algorithm in taperscan.c,
+         instead of the previous separate amcheck implementation.
+       * server-src/amtape.c: Use the taper-scan algorithm in taperscan.c,
+         instead of the previous separate amtape implementation. Also, use
+         the new changer_find interface for other kinds of tape finding.
+       * server-src/changer.c: Eliminate changer_scan. Change the API to
+         changer_find, so that callers can pass a user-data object, instead
+         of using globals.
+       * server-src/changer.h: Declare and document new changer_find
+         interface.
+       * server-src/conffile.c: Add new config option label_new_tapes.
+       * server-src/conffile.h: ditto.
+       * server-src/taper.c: Use the taper-scan algorithm in taperscan.c,
+         instead of the previous separate taper implementation. Also,
+         combine tape-label-reading for ZFTAPE and non-ZFTAPE drives (the
+         difference only matters on writing).
+       * server-src/taperscan.c: Refactor the taper-scan algorithm from
+         taper, amtape, and amcheck. Implement label_new_tapes feature.
+       * server-src/taperscan.h: Declare and document new taperscan
+         interface.
+       * tape-src/tapeio.c: Notice the difference between a non-Amanda tape
+         and some other tape-reading problem.
+       * tape-src/tapeio.h: New declarations.
+
+2005-12-13  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/reporter.c (handle_success): On a taper line, the outsize
+         should only count dump to tape, not flush.
+
+2005-12-13  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/amstatus.pl.in: Parse chunker DONE line to set output size.
+
+2005-12-09  John Franks <jrfranks@zmanda.com>
+
+       * client-src/Makefile.am: Do not include tape library if
+         configuring with --without-server option.
+       * recover-src/Makefile.am: Do not include tape library if
+         configuring with --without-server option.
+
+2005-12-08  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * configure.in: Move the size detection after detection of large
+         file support. That change the size of off_t.
+
+2005-12-08  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * common-src/amanda.h: Set OFF_T_FMT to printf format of a off_t.
+       * server-src/taper.c: Use OFF_T_FMT.
+
+2005-12-08  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * configure.in: Set LL_FMT correctly.
+       * server-src/conffile.c: Use LL_FMT.
+
+2005-12-08  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/conffile.c: Maxdumpsize is a AM64.
+       * server-src/planner.c: conf_maxdumpsize, total_size, tape_length and
+         tape_mark are am64_t.
+
+2005-12-08  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * configure.in: Check for sizeof of many type. Check printf format of
+         a 64-bit integers.
+       * common-src/amanda.h: Typedef am64_t to a 64 bits signed type,i
+         set AM64_FMT to the printf format of a am64_t variable.
+       * server-src/conffile.c: New AM64 type.
+       * server-src/conffile.h(getconf_am64): Prototype.
+
+2005-12-08  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * client-src/Makefile.am: Remove amqde.
+       * client-src/sendsize.c: Remove code to call amqde.
+       * client-src/amqde.c: Remove file.
+       * configure.in: Remove '--with-qde' option.
+
+2005-12-05  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/amindexd.c (reply, lreply, fast_lreply): Must use
+         str_buffer_sizebuf instead of sizeof(bug).
+
+2005-12-05  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/planner.c: Print the time in the FINISH line.
+       * server-src/reporter.c: The estimate time is based on the planner
+         FINISH line.
+
+2005-12-05  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * common-src/Makefile.am (bsdsecurity_LDADD): Add ssh-security.
+
+2005-12-05  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/holding.c (scan_holdingdisk): Static function.
+       * server-src/taper.c (signal_handler, install_signal_handlers): Ditto.
+       * server-src/reporter.c (output_strange,do_postscript_output): Ditto.
+
+2005-12-04  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/logfile.c (logtype_str): Add important ','.
+
+2005-12-03  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/planner.c (setup_estimate): Fix wrong order for argument.
+
+2005-12-03  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/driver.c (start_some_dumps): Don't test for
+         cur_idle == NOT_IDLE.
+
+2005-12-03  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/driverio.c (check_unfree_serial): New fonction to check
+         unfreed serial number.
+       * server-src/driverio.c (free_serial_dp): Set stable[s].dp to NULL.
+       * server-src/driverio.h (check_unfree_serial): Prototype.
+       * server-src/driver.c (main): Call check_unfree_serial.
+
+2005-12-02  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Franz Fischer
+
+       * config/acinclude.m4i: Fix for __alpha.
+
+2005-12-02  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * common-src/util.c: Debug must end with '\n'.
+
+2005-12-01  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * configure.in: Amanda support x86_64-unknown-linux-gnu.
+
+2005-11-30  Jean-Louis Martineau <martineau@zmanda.com>
+
+        * common-src/rsh-security.c (rsh_sendpkt): buf is a char array.
+        * common-src/ssh-security.c (rsh_sendpkt): buf is a char array.
+       * config/acinclude.m4i (AX_CREATE_STDINT_H): Newer macro.
+
+2005-11-30  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * client-src/rundump.c: undef USE_RUNDUMP before define.
+
+2005-11-30  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Franz Fischer
+
+       * client-src/amqde.c: Fix compiler warning.
+
+2005-11-30  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Franz Fischer
+
+       * common-src/event.h: Fix compiler warning.
+       * server-src/conffile.h: Fix compiler warning.
+
+2005-11-30  Kevin Till <ktill@zmanda.com>
+       
+       * client-src/client_util.c add server-side, client-side encryption
+         as well as custom compression. Custom compression patch is
+         orginally created by Matthieu Lochegnies.
+       * client-src/client_util.h Ditto
+       * client-src/selfcheck.c Ditto
+       * client-src/sendbackup-dump.c Ditto
+       * client-src/sendbackup-gnutar.c Ditto
+       * client-src/sendbackup.c Ditto
+       * client-src/sendbackup.h Ditto
+       * common-src/fileheader.c Ditto
+       * common-src/fileheader.h Ditto
+       * common-src/util.h Ditto
+       * example/amanda.conf.in Ditto
+       * man/xml-source/amanda.conf.5.xml Ditto
+       * restore-src/amrestore.c Ditto
+       * restore-src/restore.c Ditto
+       * server-src/conffile.c Ditto
+       * server-src/conffile.h Ditto
+       * server-src/diskfile.c Ditto
+       * server-src/diskfile.h Ditto
+       * server-src/dumper.c Ditto
+       
+2005-11-29  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * config/libtool.m4i: libtool 1.5.20
+       * config/ltmain.sh: libtool 1.5.20
+
+2005-11-29  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Franz Fischer
+
+       * common-src/fileheader.c (build_header): Declation before instruction.
+       * restore-src/amfetchdump.c: Don't use C++ style comment.
+       * restore-src/restore.c: Don't use C++ style comment.
+       * server-src/amindexd.c (reply, lreply, fast_lreply): buf must be
+          dynamicaly allocated.
+       * server-src/logfile.h: Don't use C++ style comment.
+       * server-src/taper.c (free_split_buffer): Test splitbuf against NULL.
+
+2005-11-22 Paddy Sreenivasan <paddy@zmanda.com>
+        * common-src/rsh-security.c: Fix x86_64 compile warnings.
+        * common-src/ssh-security.c: Fix x86_64 compile warnings.
+        * man/Makefile.am: Added EXTRA_XML files.
+        * man/xml-source/amanda.8.xml: Added spanning patch variables.
+        * man/xml-source/amrecover.8.xml: Added amfetchdump to SEE ALSO.
+        * xslt/global.entities: Removed file.
+
+2005-11-20  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Jon H. LaBadie
+
+       * changer-src/chg-disk.sh.in: Check permission on file access.
+
+2005-11-17  Paddy Sreenivasan <paddy@zmanda.com>
+        * man/entities/global.entities: New file. Added man page entities.
+        * man/entities/xinclude.dtd: New file.
+        * man/xslt/man.xsl: Correct include path for settings.xsl.
+
+2005-11-15  John R. Franks <jrfranks@zmanda.com>
+       * changer-src/scsi-changer-driver.c: Fix IA-64 compile warnings.
+       * common-src/rsh-security.c: Fix IA-64 compile warnings.
+       * common-src/ssh-security.c: Fix IA-64 compile warnings.
+       * regex-src/engine.c: Fix IA-64 compile warnings.
+       * regex-src/regexec.c: Fix IA-64 compile warnings.
+
+2005-11-15  Paddy Sreenivasan <paddy@zmanda.com>
+
+        * configure.in:  Changed defaults for tape_dev and nr_tape_dev.
+        * example/amanda.conf.in: Leave only changerfile definition
+          uncommented.
+        * man/xml-source/amanda.conf.5.xml: Updated defaults for 
+          tapedev and rawtapedev
+
+2005-11-10  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/planner.c: Fix incronly.
+
+2005-11-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * man/Makefile.am: Set man_MANS,
+
+2005-11-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * man/Makefile.am: Set man5_MANS and man8_MANS,
+         install-data-hook use them.
+
+2005-11-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+       Patch by Olivier Cherrier
+
+       * man/Makefile.am (install-data-hook): Set protection correclty
+         for man5 and man8.
+
+2005-10-29  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/util.c (bind_portrange): Increase port in all case.
+
+2005-10-27  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/conffile.c: Allow runtapes==0.
+       * server-src/driver.c: Use a global conf_runtapes. Don't start a
+         taper if runtapes==0.
+       * server-src/reporter.c: Don't print The next tapes if runtapes==0.
+
+
 2005-10-24  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * Amanda 2.4.5p1 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.5p1).
-       * NEWS: Update for 2.4.5p1.
+       * Amanda 2.5.0b1 released.
+       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.5.0b1).
+       * NEWS: Update for 2.5.0b1.
+
+2005-10-25  Ian Turner <ian@zmanda.com>
+       
+       * man/Makefile.am: include amfetchdump.8.
+       * man/xml-source/amadmin.8.xml: Add spanning-patch documentation.
+       * man/xml-source/amanda.8.xml: ditto
+       * man/xml-source/amrecover.8.xml: ditto
+       * man/xml-source/amfetchdump.8.xml: ditto (new file)
+       * man/xslt/global.entities: Add myself, Zmanda Inc.
+       
+2005-10-24  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * client-src/sendsize.c (getsize_wrapper): Add a NULL at the end of
+         the argvchild array.
+
+2005-10-20  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/server_util.c (getcmd): Print DEBUG to stderr.
+
+2005-10-20  Ian Turner <ian@zmanda.com>
+
+       * configure.in: Check for xsltproc.
+       * man/Makefile.am: Properly build, clean, and distribute generated
+         manpages from XML source.
+       * man/amadmin.8: Remove from CVS
+       * man/amanda.8: Remove from CVS
+       * man/amanda.conf.5: Remove from CVS
+       * man/amcheck.8: Remove from CVS
+       * man/amcheckdb.8: Remove from CVS
+       * man/amcleanup.8: Remove from CVS
+       * man/amdd.8: Remove from CVS
+       * man/amdump.8: Remove from CVS
+       * man/amflush.8: Remove from CVS
+       * man/amgetconf.8: Remove from CVS
+       * man/amlabel.8: Remove from CVS
+       * man/ammt.8: Remove from CVS
+       * man/amoverview.8: Remove from CVS
+       * man/amplot.8: Remove from CVS
+       * man/amrecover.8: Remove from CVS
+       * man/amreport.8: Remove from CVS
+       * man/amrestore.8: Remove from CVS
+       * man/amrmtape.8: Remove from CVS
+       * man/amstatus.8: Remove from CVS
+       * man/amtape.8: Remove from CVS
+       * man/amtapetype.8: Remove from CVS
+       * man/amtoc.8: Remove from CVS
+       * man/amverify.8: Remove from CVS
+       * man/amverifyrun.8: Remove from CVS
+       * man/xml-source/amadmin.8.xml: Add from xml-docs
+       * man/xml-source/amanda.8.xml: Add from xml-docs
+       * man/xml-source/amanda.conf.5.xml: Add from xml-docs
+       * man/xml-source/amcheck.8.xml: Add from xml-docs
+       * man/xml-source/amcheckdb.8.xml: Add from xml-docs
+       * man/xml-source/amcleanup.8.xml: Add from xml-docs
+       * man/xml-source/amdd.8.xml: Add from xml-docs
+       * man/xml-source/amdump.8.xml: Add from xml-docs
+       * man/xml-source/amflush.8.xml: Add from xml-docs
+       * man/xml-source/amgetconf.8.xml: Add from xml-docs
+       * man/xml-source/amlabel.8.xml: Add from xml-docs
+       * man/xml-source/ammt.8.xml: Add from xml-docs
+       * man/xml-source/amoverview.8.xml: Add from xml-docs
+       * man/xml-source/amplot.8.xml: Add from xml-docs
+       * man/xml-source/amrecover.8.xml: Add from xml-docs
+       * man/xml-source/amreport.8.xml: Add from xml-docs
+       * man/xml-source/amrestore.8.xml: Add from xml-docs
+       * man/xml-source/amrmtape.8.xml: Add from xml-docs
+       * man/xml-source/amstatus.8.xml: Add from xml-docs
+       * man/xml-source/amtape.8.xml: Add from xml-docs
+       * man/xml-source/amtapetype.8.xml: Add from xml-docs
+       * man/xml-source/amtoc.8.xml: Add from xml-docs
+       * man/xml-source/amverify.8.xml: Add from xml-docs
+       * man/xml-source/amverifyrun.8.xml: Add from xml-docs
+       * man/xslt/expand-sambadoc.xsl: Add from xml-docs
+       * man/xslt/global.entities: Add from xml-docs
+       * man/xslt/man.xsl: Add from xml-docs
+       * man/xslt/settings.xsl: Add from xml-docs
+
+2005-10-20  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/amstatus.pl.in: a FLUSH command can't be in an estimate
+         phase.
+       * server-src/driver.c: Start autoflush while waiting for estimate.
+       * server-src/planner.c: Write FLUSH line before estimate.
+
+2005-10-17  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by John R. Franks <jrfranks@zmanda.com>
+
+       * server-src/taper.c (create_split_buffer): Should not use sizeof().
+
+2005-10-17  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/taper.c (read_file): Move the putresult(DONE) to the
+         right place, some cleanup.
+
+2005-10-17  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/planner.c: Increase DEFAULT_DUMPRATE to 1024 K/s.
+
+2005-10-17  Ian Turner <ian@zmanda.com>
+
+       * Changelog: Fix line breaks.
+       * restore-src/restore.c: Give more useful FSF error messages.
+       * recover-src/extract_list.c: Do better error checking on passed port
+         number.
+       * common-src/tapelist.c: Do proper memory management of strings.
+         Otherwise really bad stuff happens.
+
+2005-10-17  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/taper.c: Set SIGPIPE to SIG_IGN, the code already
+         handle it correctly.
+
+2005-10-16  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/taper.c (signal_handler): Don't REMOVE_SHARED_MEMORY, it
+         is done by exit.
+
+2005-10-16  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * server-src/driverio.c (serial2disk): Print str if error.
+
+2005-10-15  Paddy Sreenivasan <paddy@zmanda.com>
+
+        * server-src/taper.c: Shared memory need not be removed in normal paths.
+          Done as part of atexit. 
+
+2005-10-15  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by John R. Franks <jrfranks@zmanda.com>
+
+       * changer-src/scsi-aix.c: calls to open/openx guages success by
+         checking for a file descriptor greater than 0.  0 is also a valid
+         descriptor so the check should be >= 0.
+         Calls to SCSI_OpenDevice does not check for error return.
+         Calls to SCSI_OpenDevice does not check for error return.
+         Calls to SCSI_OpenDevice does not check for error return.
+         Call to opendir() does not check for error.
+       * changer-src/scsi-hpux_new.c: Ditto.
+       * changer-src/scsi-irix.c: Ditto.
+       * changer-src/scsi-linux.c: Ditto.
+       * changer-src/scsi-solaris.c: Ditto.
+       * client-src/selfcheck.c: Call to open() does not check for error.
+       * client-src/sendbackup.c: Call to freopen() does not check for error.
+       * client-src/sendsize.c: Call to open() does not check for error.
+       * common-src/bsd-security.c: Call to open() does not check for error.
+       * common-src/file.c: Call to open() does not check for error.
+       * restore-src/amrestore.c: Calls to tape_open() do not always check
+         return code.  open() is called with open flags set to 0
+         (Call always fails with an EINVAL)
+       * restore-src/restore.c: fopen() return error check  is "fopen() < 0".
+         fopen returns a pointer and the proper check should be
+         "fopen() == NULL".
+         Call to open() does not check for error.
+       * tape-src/tapeio.c: tape_open() is called here and other places with a
+         variable number of arguments, and yet is not defined as a varargs
+         function...
+       * tape-src/tapeio.h: Prototype for tape_open.
+
+2005-10-15  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by Paddy Sreenivasan <paddy@zmanda.com>
+
+       * client-src/sendsize.c: Log message changes.
+       * server-src/taper.c: And an atexit function to detach shared memory.
+         Trap some signal and detach shared memory.
+
+2005-10-14  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * regex-src/regcomp.c (findmust): Initialized start to NULL.
+
+2005-10-14  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by John R. Franks <jrfranks@zmanda.com>
+
+       * regex-src/cclass.h: Fixed to add missing braces and reformat long
+         strings to fix in 80 columns.
+       * regex-src/cname.h: Fixed by adding braces and tidying up code a bit.
+       * regex-src/regcomp.c (p_ere): Initialized prevback and prevfwd to 0.
+         ifdef out unused mcsub, mcin and mcfind functions.
+         (findmust) Initialized newstart to NULL.
+       * regex-src/regerror.c: Adds missing braces.
+       * regex-src/regexec.c (nope): Use only in assert, so it is not only
+         defined if NDEBUG is not defined.
+
+2005-10-14  Jean-Louis Martineau <martineau@zmanda.com>
+       Patch by John R. Franks <jrfranks@zmanda.com>
+
+       * common-src/krb4-security.c (krb4_security_dummy): Rename from dummy,
+         it is not static int.
+       * common-src/krb5-security.c (krb5_security_dummy): Rename from dummy,
+         it is not static int.
+
+2005-10-13  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * common-src/util.c (bind_portrange): New argument proto.
+         Check for reserved port.
+       * common-src/util.h (bind_portrange): New prototype.
+       * common-src/bsd-security.c (bind_portrange): New prototype.
+       * common-src/dgram.c: Add "udp" as argument to bind_portrange.
+       * common-src/stream.c: Add "tcp" as argument to bind_portrange.
+
+2005-10-12  Jean-Louis Martineau <martineau@zmanda.com>
+
+       * restore-src/amidxtaped.c (check_security_buffer): i is a socklen_t.
+       * restore-src/amidxtaped.c (main): Remove i, fd, amrestore_path, pid,
+         isafile, stat_tape, tapename, s, fp, ch and errstr variable.
+
+2005-10-11  Ian Turner <ian@zmanda.com>
+       Patch by  Jean-Louis Martineau <martineau@zmanda.com>
+       
+       * restore-src/amfetchdump.c: Remove unused variable debug.
+        * restore-src/amidxtaped.c: Remove lock_logfile(), which is also 
+         in restore.c.
+       * restore-src/Makefile.am: Include libamanda twice, to fix build 
+         on some machines.
+
+2005-10-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * restore-src/Makefile (noinst_HEADERS): Add restore.h.
+       * restore-src/restore.c (search_tapes): Add the fourth argument to
+         read_file_header.
+
+2005-10-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/conffile.c: dpcur.s_split_diskbuffer must be initialize
+         to 0.
+       * server-src/reporter.c (handle_partial): Set repdata to the result
+         of handle_success.
+       * server-src/taper.c: Set the first-file.
 
 2005-10-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
        * server-src/taper.c (tape_writer_side): detach_buffers on normal exit.
 
+2005-10-10  Ian Turner <ian@zmanda.com>
+
+       * server-src/amtape.h: Apply tape-spanning patch by John Stange
+         <building@cs.umd.edu> as ported to 2.5.0 by Ian Turner, with
+         contributions by Christopher Pascoe <c.pascoe@itee.uq.edu.au>.
+       * configure.in: Ditto
+       * amplot/Makefile.am: Ditto
+       * changer-src/Makefile.am: Ditto
+       * client-src/Makefile.am: Ditto
+       * common-src/Makefile.am: Ditto
+       * common-src/amanda.h: Ditto
+       * common-src/amfeatures.c: Ditto
+       * common-src/amfeatures.h: Ditto
+       * common-src/fileheader.c: Ditto
+       * common-src/fileheader.h: Ditto
+       * common-src/match.c: Ditto
+       * common-src/tapelist.c: Ditto
+       * common-src/tapelist.h: Ditto
+       * example/amanda.conf.in: Ditto
+       * man/Makefile.am: Ditto
+       * recover-src/amrecover.c: Ditto
+       * recover-src/amrecover.h: Ditto
+       * recover-src/display_commands.c: Ditto
+       * recover-src/extract_list.c: Ditto
+       * restore-src/Makefile.am: Ditto
+       * restore-src/amfetchdump.c: Ditto
+       * restore-src/amfetchdump.h: Ditto
+       * restore-src/amidxtaped.c: Ditto
+       * restore-src/amrestore.c: Ditto
+       * restore-src/restore.c: Ditto
+       * restore-src/restore.h: Ditto
+       * server-src/Makefile.am: Ditto
+       * server-src/amadmin.c: Ditto
+       * server-src/amindexd.c: Ditto
+       * server-src/amoverview.pl.in: Ditto
+       * server-src/amtoc.pl.in: Ditto
+       * server-src/amverify.sh.in: Ditto
+       * server-src/changer.c: Ditto
+       * server-src/conffile.c: Ditto
+       * server-src/conffile.h: Ditto
+       * server-src/disk_history.c: Ditto
+       * server-src/disk_history.h: Ditto
+       * server-src/diskfile.c: Ditto
+       * server-src/diskfile.h: Ditto
+       * server-src/driver.c: Ditto
+       * server-src/driverio.c: Ditto
+       * server-src/find.c: Ditto
+       * server-src/find.h: Ditto
+       * server-src/holding.c: Ditto
+       * server-src/holding.h: Ditto
+       * server-src/logfile.c: Ditto
+       * server-src/logfile.h: Ditto
+       * server-src/planner.c: Ditto
+       * server-src/reporter.c: Ditto
+       * server-src/server_util.c: Ditto
+       * server-src/server_util.h: Ditto
+       * server-src/taper.c: Ditto
+
 2005-10-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/taper.c: Change message: on new tape due to
 
 2005-10-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-       Patch by John R. Franks
+       Patch by John R. Franks 
 
        * common-src/amflock.c (main): Don't call safe_fd, it's not needed
          during configure.
        * configure.in: '#include <sys/types.h>' in the check
          'for Linux like scsi support (sg)'
 
+2005-10-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * client-src/amandad.c (writebuf): Call waitpid in the parent.
+
+2005-10-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * client-src/amandad.c (service_delete): Remove call to sleep.
+       * common-src/bsd-security.c: Add bsdprintf. Add more debug.
+         The handle is used as a string, instead of 2 int.
+
+2005-10-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/rsh-security.c: rshprintf should call dbprint.
+       * common-src/ssh-security.c: rshprintf should call dbprint, add many
+         rshprintf.
+       * common-src/event.c: Add eventprintf, use it. Add debug_prefix_time
+         to the log. 
+
 2005-10-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * common-src/stream.c: len is a socklen_t.
        * restore-src/amidxtaped.c: Add socklen as a socklen_t.
        * tape-src/tapetype.c: Change printf format.
        * server-src/amlabel.c: Add a variable isa_zftape. init fd to -1.
+       * server-src/dumper.c: Init outfd to -1.
+       * common-src/file.c (areads_getbuf): First argument is const.
 
 2005-10-01  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/reporter.c: Don't trunk hostname/diskname in
          'FAILURE AND STRANGE DUMP SUMMARY' section.
 
+2005-10-01  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/chunker.c (main): Remove outfd.
+
 2005-09-30  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/conffile.c, server-src/diskfile.c, server-src/infofile.c,
          client-src/getfsent.c, common-src/statfs.c, common-src/token.c
-         (main): Remove fd declaration.
+          (main): Remove fd declaration.
 
 2005-09-30  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * config/ltmain.sh: Update from libtool-1.5.16.
        * config/libtool.m4i: Update from libtool-1.5.16.
 
+2005-09-30  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/bsd-security.c: Fix small bug.
+
 2005-09-22  John R. Jackson <jrj@purdue.edu>
 
        * configure.in: If --without-server is specified, either on the
        * client-src/sendsize.c: Ditto.
        * client-src/versionsuffix.c: Ditto.
        * common-src/amflock.c: Ditto.
-       * common-src/genversion.c: Ditto.
+       * common-src/rsh-security.c: Ditto.
+       * common-src/ssh-security.c: Ditto.
        * common-src/statfs.c: Ditto.
        * common-src/token.c: Ditto.
        * recover-src/amrecover.c: Ditto.
        * server-src/amtape.c: Ditto.
        * server-src/amtrmidx.c: Ditto.
        * server-src/amtrmlog.c: Ditto.
+       * server-src/chunker.c: Ditto.
        * server-src/conffile.c: Ditto.
        * server-src/diskfile.c: Ditto.
        * server-src/driver.c: Ditto.
-       * server-src/dumper.c: Ditto.
        * server-src/getconf.c: Ditto.
        * server-src/infofile.c: Ditto.
        * server-src/planner.c: Ditto.
        * server-src/reporter.c: Ditto.
        * server-src/taper.c: Ditto.
+       * server-src/dumper.c: Ditto plus remove incorrect chdir to hard
+         coded "/tmp/amanda".
 
 2005-09-20  John R. Jackson <jrj@purdue.edu>
 
        * client-src/sendbackup-dump.c: Ignore a new message from Solaris
          vxdump.
 
+2005-09-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/bsd-security.c: Generate a unique event_id, thei
+         proto_handle is not always unique.
+
 2005-09-15  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amverify.sh.in: Don't check for EOI, it's buggy.
        * server-src/planner.c: Don't use history with size < 0.
 
 2005-09-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-        Patch Paul Bijnens <paul.bijnens@xplanation.com>
+       Patch Paul Bijnens <paul.bijnens@xplanation.com>
 
-        * server-src/planner.c(delay_dumps): Delay incremental dump also
-        larger than tape.
+       * server-src/planner.c(delay_dumps): Delay incremental dump also
+         larger than tape.
 
 2005-09-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Orion Poplawski <orion@cora.nwra.com>
        * server-src/driver.c: Make tape_length and tape_left unsigned long.
 
 2005-07-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-       Bug found by John E Hein <jhein@timing.com>.
+       Patch by Stefan G. Weichinger <monitor@oops.co.at>
 
-       * server-src/amadmin.c: Fix of by one with NB_HISTORY.
-       * server-src/infofile.c: Fix of by one with NB_HISTORY.
+       * client-src/sendbackup-gnutar.c: Added RE for new Samba-releases.
 
-2005-06-23  Stefan G. Weichinger <monitor@oops.co.at>
+2005-07-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * client-src/sendbackup-gnutar.c: Added RE for new Samba-releases.
+       Bug found by John E Hein <jhein@timing.com>.
+       * server-src/amadmin.c: Fix of by one with NB_HISTORY.
+       * server-src/infofile.c:x: Fix of by one with NB_HISTORY.
 
 2005-06-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Jay Fenlason <fenlason@redhat.com>
        * client-src/sendsize.c: Fix dbprintf call.
 
 2005-06-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+           Stefan G. Weichinger <monitor@oops.co.at>
 
-       * server-src/amverifyrun.sh.in: Remove buggy space.
+       * example/amanda.conf.in: edited the default-value for the
+                                 holdingdisk-usage to "use -100 Mb".
+                                 The old value "use 290 Mb" didn't make much
+                                 sense anymore.
 
-2005-05-28  Stefan G. Weichinger <monitor@oops.co.at>
+2005-06-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * example/amanda.conf.in: edited the default-value for the
-                                 holdingdisk-usage to "use -100 Mb".
-                                 The old value "use 290 Mb" didn't make much
-                                 sense anymore.
+       * server-src/amverifyrun.sh.in: Remove buggy space.
 
 2005-05-17  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
 2005-05-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * man/Makefile.am (COMMON_MAN_PAGES, EXTRA_DIST): Add amadmin.8.
-       * man/*: Update from latest xml-doc.
-       * docs/Makefile.am (pkgdata_DATA): Add Appendix.txt, amanda.conf.5.txt
-         and howto-wrapper.txt.
-       * docs/* Update from latest xml-docs.
+       * example/amanda.conf.in: Update from 2.4.5.
 
-2005-05-05  Stefan G. Weichinger <monitor@oops.co.at>
+2005-05-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * example/amanda.conf.in: added description for parameter estimate.
+       * docs/*: New documentation from xml-docs.
+       * docs/Makefile.am (pkgdata_DATA): Update for new files.
 
-2005-04-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+2005-05-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * Amanda 2.4.5 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.5).
-       * NEWS: Update for 2.4.5.
+       * man/Makefile.am (COMMON_MAN_PAGES): Add amanda.conf.5.
 
-2005-04-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+2005-05-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * docs/*: Update from latest xml-docs.
+       * man/*: Use man pages form xml-docs.
+       * configure.in (AC_CONFIG_FILES): Remove all man pages.
+       * man/Makefile.am (EXTRA_DIST): Add amadmin.8 amanda.8 amanda.conf.5 
+         amcheck.8 amcheckdb.8 amcleanup.8 amdump.8 amflush.8 amgetconf.8
+         amlabel.8 amoverview.8 amreport.8 amrecover.8 amrmtape.8 amstatus.8
+         amtapetype.8 amtoc.8 amverify.8 amverifyrun.8
 
-2005-04-15  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+2005-05-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * docs/*: Update from latest xml-docs.
+       * common-src/rsh-security.c (net_read_fillbuf): Read only a packet,
+         nothing more.
+       * common-src/ssh-security.c (net_read_fillbuf): Read only a packet,
+         nothing more.
+       * common-src/rsh-security.c (conn_put): Don't kill the process, only do
+         a wait with WNOHANG.
+       * common-src/ssh-security.c (conn_put): Don't kill the process, only do
+         a wait with WNOHANG.
 
 2005-04-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * changer-src/chg-zd-mtx.sh.in: Improve handling of
          "Unknown Storage Element Loaded".
 
-2005-04-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * man/amcheckdb.8: Update from latest xml-docs.
-
-2005-04-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * docs/*: New documentation from xml-docs.
-       * docs/Makefile.am (pkgdata_DATA): Update for new files.
-
 2005-04-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        - https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=144052
 
        * client-src/sendsize.c (generic_calc_estimates): Use amname instead
          of dirname in message.
 
-2005-04-01  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * man/amanda.8, man/amdd.8, man/ammt.8: Updated.
-
-2005-03-31  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * man/Makefile.am (EXTRA_DIST): Add amadmin.8 amanda.8 amcheck.8
-         amcheckdb.8 amcleanup.8 amdump.8 amflush.8 amgetconf.8 amlabel.8
-         amoverview.8 amreport.8 amrecover.8 amrmtape.8 amstatus.8
-         amtapetype.8 amtoc.8 amverify.8 amverifyrun.8
-
-2005-03-31  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * man/*: use man pages form xml-docs.
-       * configure.in (AC_CONFIG_FILES): Remove all man pages.
-
-2005-03-31  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/dumper.c (update_dataptr): Open a new chunk file even if
-         size==0, the test must be (dataout < datain), which means we have
-         something to write.
-
-2005-03-29  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * NEWS: new amoverview -skipmissed option.
-
 2005-03-29  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/conffile.h: Rename getcont_unit_divisor to
          and send it to amandad. Write debuging message.
 
 2005-02-09  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-        Patch by Franz G. Fischer
+       Patch by Franz G. Fischer
 
        * server-src/conffile.c: Adds a value type LONG and a val_t.l long
          union member and changes get_number() to return long and
 
 2005-02-09  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * server-src/planner.c: Improve message if no incremental estimate.
-
-2005-01-23  Stefan G. Weichinger <monitor@oops.co.at> 
-       Patch by Jon LaBadie <jon@jgcomp.com>
-
-       * changer-src/chg-multi.sh.in: New header to explain the meaning of
-         the "multi" in "chg-multi".
+        * server-src/planner.c: Improve message if no incremental estimate.
 
 2004-12-21  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Christopher Pascoe <c.pascoe@itee.uq.edu.au>
 
 2004-11-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * NEWS: new displayunit global option to select the unit use to
-         display number: k=kilo, m=mega, g=giga, t=tera
+       * server-src/diskfile.c: Compilation fix.
+
+2004-11-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
        * server-src/conffile.c: Parse displayunit,
          new fonction getcont_unit_divisor().
        * server-src/conffile.h: Prototype of getcont_unit_divisor().
        * server-src/amcheck.c: Use displayunit to display holding disk size.
        * server-src/amstatus.pl.in: Use displayunit to display dump size.
        * server-src/reporter.c: use displayunit to display dump size.
-       * man/amanda.8.in: Document displayunit.
+       * Document displayunit.
 
 2004-11-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
        * changer-src/chg-zd-mtx.sh.in: Fix for library with barcode.
 
-
-2004-11-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/planner.c: Print the time in the FINISH line.
-       * server-src/reporter.c: The estimate time is based on the planner
-         FINISH line.
-
 2004-11-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * restore-src/amrestore.c: Read empty file.
 
-2004-11-10  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/driver.c (selectset): Make only one declaration in main.
-
 2004-11-10  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * tape-src/tapetype.c: Use new tape.
 
        * server-src/amstatus.pl.in: Display partial estimate.
 
-2004-11-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-       Patch by Orion Poplawski <orion@cora.nwra.com>
-
-       * server-src/amstatus.pl.in: a FLUSH command can't be in an estimate
-         phase.
-       * server-src/driver.c: Start autoflush while waiting for estimate.
-       * server-src/planner.c: Write FLUSH line before estimate.
-
 2004-11-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/diskfile.c (read_diskline): A spindle must be numerical.
 
-2004-10-22  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-        * Amanda 2.4.5b1 released.
-
 2004-10-21  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/holding.c (rename_tmp_holding): Always rename files.
 
        * man/amanda.8.in: Document 'estimate' dumptype option.
 
-2004-08-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * client-src/amqde.c: Change snprintf for ap_snprintf.
-
 2004-08-04  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amrmtape.sh.in: Understand history info.
 
+2004-08-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/driver.c: Typo.
+
 2004-08-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amstatus.pl.in: Parse CONTINUE and RQ-MORE-DISK line,
 
 2004-08-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * server-src/driverio.c (dumper_cmd): Print serial number for CONTINUE
-         command.
-       * server-src/driverio.c (disk2serial): Try to find a 'dp' before
-         allocating a new serial.
-       * server-src/dumper.c (update_dataptr): Read serial number for CONTINUE
-         command.
+       * server-src/driver.c (handle_dumper_result, handle_chunker_result):
+         Don't call free_serial().
+       * server-src/driver.c (dumper_result): Call free_serial_dp(dp).
+       * server-src/driverio.c (dumper_cmd): Remove CONTINUE cmd.
+        * server-src/driverio.c (chunker_cmd): Print serial number for CONTINUE
+          command.
+        * server-src/driverio.c (disk2serial): Try to find a 'dp' before
+          allocating a new serial.
+       * server-src/driverio.c (free_serial_dp): New function to remove the
+         serial for a dp.
+       * server-src/driverio.h (free_serial_dp): Prototype.
+        * server-src/chunker.c (databuf_flush): Read serial number for CONTINUE
+          command.
 
 2004-08-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
 2004-08-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-        * server-src/infofile.h (history_t): new struct.
-        * server-src/infofile.h (info_t): Add a history_t.
-        * server-src/infofile.c (read_txinfofile): Parse history data.
-        * server-src/infofile.c (write_txinfofile): Print history data.
-        * server-src/amadmin.c (export_one): export history data.
-        * server-src/amadmin.c (import_one): import history data.
-        * server-src/driverio.c (update_info_dumper): update history data.
+       * server-src/infofile.h (history_t): new struct.
+       * server-src/infofile.h (info_t): Add a history_t.
+       * server-src/infofile.c (read_txinfofile): Parse history data.
+       * server-src/infofile.c (write_txinfofile): Print history data.
+       * server-src/amadmin.c (export_one): export history data.
+       * server-src/amadmin.c (import_one): import history data.
+       * server-src/driverio.c (update_info_dumper): update history data.
 
 2004-05-10  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Paul Bijnens <paul.bijnens@xplanation.com>
        * configure.in: Use AX_CREATE_STDINT_H(common-src/amanda-int.h).
        * common-src/amanda.h: include "common-src/amanda-int.h".
        * changer-src/scsi-cam.c: Change u_int32_t for uint32_t.
-       * client-src/amandad-krb4.c: Change u_int32_t for uint32_t.
-       * common-src/krb4-security.c: Change u_int32_t for uint32_t.
-       * common-src/krb4-security.h: Change u_int32_t for uint32_t.
-       * common-src/protocol.h: Change u_int32_t for uint32_t.
-       * common-src/security.c: Change u_int32_t for uint32_t.
 
 2004-04-27  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 2004-04-26  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/driver.c (continue_dumps): Fix deadlock if holding disk
-         fill up when in degraded mode.
+       fill up when in degraded mode.
 
 2004-04-23  Eric Siegerman <eric_97@pobox.com>
 
        * server-src/diskfile.h: Define.
        * server-src/planner.c: Use.
        * man/amanda.8.in: Document.
-       * NEWS: bumpsize, bumppercent, bumpdays and bumpmult can be in a
-         dumptype.
 
 2004-04-22  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Fix by Paul Bijnens <paul.bijnens@xplanation.com>
 2004-04-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Fix by John Koyle <jkoyle@rfpdepot.com>
 
-       * common-src/protocol.c: Fix EAGAIN on Linux.
+       * common-src/dgram.c: Fix EAGAIN on Linux.
+
+2004-04-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/amadmin.c (bumpsize): Typo.
 
 2004-04-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/conffile.h: Define It.
        * server-src/planner.c (bump_thresh): New size_level_0 parameter,
          use the new bumppercent option.
-       * NEWS: Document it.
 
 2004-04-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
 2004-03-22  Stefan G. Weichinger <monitor@oops.co.at>
 
-        * server-src/amcheck.c (start_host): Added warning for hostname
+       * server-src/amcheck.c (start_host): Added warning for hostname
          localhost.
        * docs/TOP-TEN-QUESTIONS: added note about localhost-warning.
 
 
        * docs/TOP-TEN-QUESTIONS: New file.
 
+2004-03-17  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/reporter.c (handle_success): Set stats[i].coutsize
+         correctly.
+       * server-src/taper.c: Do not subtract tt_blocksize_kb from filesize.
+
+2004-03-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/ssh-security.c: New ssh security driver.
+       * common-src/Makefile.am (libamanda_la_SOURCES): Add ssh-security.c.
+       * common-src/security.c: Add ssh security driver.
+       * configure.in: Add --with-ssh-security. Define SSH_SECURITY.
+
 2004-03-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amcheck.c: Do labelstr check in correct order.
 
+2004-03-10  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       Use only one time event for all dumpers, no wait event.
+       start_some_dumps is called everytime a dumper or taper finish.
+       * server-src/driver.c (dumpers_ev_time): New global event.
+       * server-src/driver.c (start_some_dumps): Remove dumper argument,
+         can start many dump.
+       * server-src/driver.c (dumper_result): Call start_some_dumps instead
+         of event_wakeup.
+       * server-src/driver.c (handle_idle_wait): Remove function.
+       * server-src/driver.c (handle_dumpers_time): new handle for
+         dumpers_ev_time, it call start_some_dumps.
+       * server-src/driverio.h (dumper_t): Remove ev_wait.
+       * server-src/driverio.c (startup_dump_process): Don't set ev_wait.
+
+2004-03-09  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/fileheader.c (print_header): Fix fprintf use.
+       * client-src/amqde.c (parse_exclude_path): Fix = by ==.
+       * common-src/protocol.c (s_repwait): Fix compiler warning.
+       * common-src/rsh-security.c (runrsh): Fix compiler warning.
+
+2004-03-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/pipespawn.c (pipespawn): Remove passwdvar and passwdfd.
+
 2004-02-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Reported by Allen Liu <allen@bellglobal.com>
 
 
        * server-src/amcheck.c: Verify the tape is listed in the tapelist file.
        * server-src/taper.c: Ditto
-       * NEWS: * amanda will not use a tape if it's label is not in the
-                 tapelist file (eg. after an amrmtape).
 
 2004-02-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * common-src/amfeatures.c (am_init_feature_set): Add
          fe_partial_estimate.
        * common-src/amfeatures.h (am_feature_e): Add fe_partial_estimate.
-       * common-src/protocol.c: Handle PREP packet.
-       * common-src/protocol.h (pktype_t):  Add P_PREP.
+       * common-src/packet.c (pktypes[]): Add PREP.
+       * common-src/packet.h (pktype_t): Add P_PREP.
+       * common-src/protocol.c (action_t): Add A_CONTPEND.
+       * common-src/protocol.c: Handle P_PREP packet.
        * server-src/amstatus.pl.in: Parse "got partial result" line.
-       * server-src/planner.c: Handle PREP packet.
+       * server-src/planner.c: Handle P_PREP packet.
 
 2004-02-13  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Reported by Jason Brooks <jason.brooks@windriver.com>
        * server-src/planner.c: Flush today's dump with autoflush.
        * server-src/find.c: Find holding disk with timestamp.
        * server-src/find.h (find_result_t): Add timestamp field.
-       * NEWS: holding disk disk use timestamped directory.
-       * NEWS: autoflush flush today's dump.
 
 2004-02-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * configure.in: Call CF_WAIT_INT.
        * common-src/amanda.h: Try to make waitpid doesn't warn.
 
-2004-02-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.5b1).
-
 2004-01-29  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * Makefile.am (EXTRA_DIST): Add contrib/mkamandisk.
 
 2004-01-29  Christoph Pospiech <pospiech@de.ibm.com>
 
-        * configure.in (AC_CONFIG_FILES): Add changer-src/chg-iomega.pl.
-        * changer-src/Makefile.am (libexec_SCRIPTS) Add chg-iomega.
-        * changer-src/chg-iomega.pl.in: New changer script.
-        * docs/TAPE.CHANGERS: Document chg-iomega.
+       * configure.in (AC_CONFIG_FILES): Add changer-src/chg-iomega.pl.
+       * changer-src/Makefile.am (libexec_SCRIPTS) Add chg-iomega.
+       * changer-src/chg-iomega.pl.in: New changer script.
+       * docs/TAPE.CHANGERS: Document chg-iomega.
        * contrib/mkamandisk: Script to format iomega disk.
-       * NEWS: New chg-iomega changer script.
 
 2004-01-29  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * example/amanda.conf.in: Update record documentation.
        * man/amanda.8.in: Update record documentation.
 
-2004-01-13  Greg Troxel  <gdt@t...>
-
-       * common-src/krb4-security.c (errstr;): Make krb4 work on 64-bit
-         platforms.  Essentially, change 'unsigned long' to u_int32_t for
-         on-the-wire representation of checksums, declaring that the wire
-         protocol is defined by existing use of unsigned long on 32-bit
-         machines.
-
-         Modify the data/control handshake similarly, defining a
-         'net_timeval' that uses int32_t rather than long.  Cleanup a latent
-         bug in handshake code that didn't cause trouble before when
-         everything was the same type.
-
-         This change preserves interoperability with the previous code
-         on 32 bit machines.  (It is likely that 64/64 interoperability
-         was ok, but unlikely that it was important to anyone, given
-         the low population of amanda-krb users.)
-
 2004-01-14  Stefan G. Weichinger <monitor@oops.co.at>
 
        * docs/INSTALL: Add config for xinetd.
 
-2004-01-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * Amanda 2.4.4p2 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.4p2).
-
-
 2004-01-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/planner.c (handle_result): Detect bad estimate (-1).
        * server-src/planner.c (analyze_estimate): Don't schedule level
          if the estimate is bad.
 
-2003-12-19  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * client-src/Makefile.am (EXTRA_DIST): Add amandad-krb4.c,
-         sendbackup-krb4.c and sendbackup-krb4.h.
-       * common-src/Makefile.am (EXTRA_DIST): Add krb4-security.c and
-         krb4-security.h.
-       * server-src/Makefile.am (EXTRA_DIST): Add dumper-krb4.c.
-       * NEWS: Kerberos 4 support integrated and functional again.
-
-2003-12-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-       patch by Greg Troxel <gdt@ir.bbn.com>
-             and Beverly Schwartz <bschwart@bbn.com>
-
-       Original *krb4* files are taken form the amanda-krb repository.
-
-       Add kerberos 4 support.
-       * client-src/amandad-krb4.c: New file.
-       * client-src/amandad.c: Fix close of req_pipe[0]/rep_pipe[1].
-       * client-src/sendbackup-krb4.c: New file.
-       * client-src/sendbackup-krb4.h: New file.
-       * client-src/sendbackup.c: Use options->krb4_auth.
-       * common-src/amanda.h: Fix for initgroups.
-       * common-src/krb4-security.c: New file.
-       * common-src/krb4-security.h: New file.
-       * common-src/token.h: Use HAVE_SHQUOTE_DECL.
-       * configure.in: Enhance finding krb libs.
-       * server-src/diskfile.c: Fix.
-       * server-src/dumper-krb4.c: New file.
-       * server-src/getconf.c: Define HOSTNAME_INSTANCE.
-
 2003-12-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * docs/HOWTO-FILE-DRIVER: New file.
        * changer-src/chg-disk.sh.in: New changer script.
        * changer-src/Makefile.am (libexec_SCRIPTS): Add chg-disk.
        * configure.in (AC_CONFIG_FILES): Add changer-src/chg-disk.sh.
-       * NEWS: new chag-disk changer script to use with the file: driver.
 
 2003-11-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * tape-src/tapeio.c: extern int optind.
 
 2003-11-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-       Patch by C.Scheeder <christoph.scheeder@scheeder.de
+       Patch by C.Scheeder <christoph.scheeder@scheeder.de>
 
        * changer-src/sense.c (SenseType): Add "DAT AutoChanger" and "C1537A".
 
        * server-src/amtape.c (taperscan_slot): Ditto.
        * server-src/taper.c (taperscan_slot): Ditto.
 
-2003-11-24  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/driver.c (handle_taper_result): Empty tapeq in TAPE_ERROR
-         and BOGUS case.
-
 2003-11-24  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/driver.c (handle_taper_result): Always call
        * server-src/diskfile.c (add_disk): Set device and todo.
        * server-src/find.c: Build disklist dynamicaly from log files.
        * server-src/find.h (find_dump): New prototype.
-       * NEWS: 'amadmin find' list disk removed from the disklist.
-       * NEWS: amrecover can recover a disk removed from the disklist file.
 
 2003-10-27  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
          tp->datestamp > 0.
        * server-src/amadmin.c (disklist_one): Don't print ':' on device line.
 
+2003-10-23  Todd Kover <kovert@omniscient.com>
+
+       * make amrecover link against readline rather than libamanda so
+         only amrecover would require the shared library (if it's found)
+
 2003-10-22  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Paul Bijnens <paul.bijnens@xplanation.com>
 
 
 2003-10-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * common-src/genversion.c (prundefvar): New macro to print an
+       * common-src/genversion.c (prundefvar): New function to print an
          undefined variable.
        * common-src/genversion.c: Print undefined variable.
        * server-src/amcheck.c: Improve message for no LPRCMD defined.
 
 2003-07-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * restore-src/amidxtaped.c: Don't clear re_label before checking
+       * restore-src/amidxtaped.c: Don't clea re_label before checking
          for the changer.
 
 2003-07-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * changer-src/chg-zd-mtx.sh.in (initial_poll_delay): New config
          variable to add a pause after a tape loading.
-       * News: New initial_poll_delay config in chg-zd-mtx.
 
 2003-07-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Fix by John E. Hein <jhein@timing.com>
 
        * changer-src/chg-chio.pl.in: Fix next/prev command.
 
-2003-07-06  Thomas Hepper <th@ant.han.de>
-       * changer-src/chg-scsi.c: Added debug Information to see which sg
-        version is used
-       * changer-src/scsi-linux.c: Added debug Information to see which sg
-       version is used.
-       Removed check if an data packet is larger than 4096 byte.
-
 2003-07-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        patch by Paul Bijnens <paul.bijnens@xplanation.com>
 
        * client-src/client_util.c (add_include): Count include with 2 /,
          Fix descriptor leak.
 
-2003-06-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * Amanda 2.4.4p1 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.4p1).
-
-
 2003-06-25  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amstatus.pl.in: Fix print spacing for idle dumpers.
 
+2003-06-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/holding.c: Fix compiler error.
+       * server-src/planner.c: Use snprintf.
+
 2003-06-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        patch by Paul Bijnens <paul.bijnens@xplanation.com>
 
 
        * changer-src/chg-zd-mtx.sh.in: Log the changer file used.
 
-2003-06-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/holding.c: Skip lost+found directories on holding disks.
-
 2003-06-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amverify.sh.in: Do not advance to next tape.
        * changer-src/scsi-hpux_new.c:Use pDev[DeviceFD].fd instead of DeviceFD.
        * changer-src/scsi-linux.c: Use pDev[ip].fd instead of DeviceFD.
 
+2003-06-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * client-src/noop.c: #include "util.h".
+
 2003-06-05  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amflush.c: Implement new -b and -s options.
          directory.
        * server-src/holding.h (mkholdingdir): Prototype.
        * server-src/driver.c: Use mkholdingdir;
-       * server-src/dumper.c: Call mkholdingdir before opening a file for
+       * server-src/chunker.c: Call mkholdingdir before opening a file for
          writing.
 
 2003-06-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        * server-src/tapefile.c (read_tapelist,parse_tapeline): Fix for
          previous patch.
 
+2003-05-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * common-src/versuff.c.in: Use @VERSION_SUFFIX@.
+
 2003-05-16  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * example/amanda.conf.in: Add more amrecover_changer doc.
 
 2003-04-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * configure.in (AC_CHECK_HEADERS): Remove linux/ftape-header-segment.h,
-         linux/ftape-vendors.h and linux/ftape.h.
+       * configure.in (AC_CHECK_HEADERS): Enleve linux/ftape-header-segment.h,
+         linux/ftape-vendors.h et linux/ftape.h.
 
 2003-04-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Darin Dugan <dddugan@iastate.edu>
 
        * common-src/error.c (output_error_message): Always prepend program
          name.
-       * server-src/dumper.c (process_dumpeof): 'missing size line' and
-         'missing end line' should be failed, not strange.
 
 2003-04-15  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
        * server-src/amverifyrun.sh.in: Run the amverify command.
 
-2003-04-01  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+2003-04-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Paul Bijnens <paul.bijnens@xplanation.com>
 
        * server-src/reporter.c: Get the filenumber correct.
        Patch by Paul Bijnens <paul.bijnens@xplanation.com>
 
        * server-src/reporter.c: Print a postscript label for each tape used.
-       * NEWS: Print a postscript label for each tape used.
 
 2003-03-18  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
 2003-03-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * recover-src/set_commands.c (set_tape): Recognize null:, rait:, 
+       * recover-src/set_commands.c (set_tape): Recognize null:, rait:,
          file: and tape: as driver, not host name.
 
 2003-03-14  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * changer-src/Makefile.am (libexec_SCRIPTS): Missing \.
 
-2003-03-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * NEWS: amrecover_changer works with chg-multi.
-
 2003-03-08  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * client-src/client_util.c (add_include): If include contain 2 '/' then
          use at asis, don't try to match it.
 
+2003-03-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/changer.h (changer_label): Return an int.
+       * server-src/changer.h (changer_label): First parameter is char *.
+
 2003-03-07  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * file tape-src/output-rait.c (rait_open): Call tapefd_set_master_fd();
        * file tape-src/tapeio.c (struct tape_info): Add master_fd field.
        * file tape-src/tapeio.c (tape_info_init): Set master_fd to -1;
-       * file tape-src/tapeio.c (tapefd_getinfo_host, tapefd_getinfo_disk, 
+       * file tape-src/tapeio.c (tapefd_getinfo_host, tapefd_getinfo_disk,
          tapefd_getinfo_level): Return info of master_fd.
        * file tape-src/tapeio.c (tapefd_set_master_fd): New function to set
          master_fd.
        * file tape-src/tapeio.h (tapefd_set_master_fd): Prototype.
-       * NEWS: rait: works with file:
 
 2003-03-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * tape-src/output-file.c (file_tapefd_can_fork): New function that 
+       * tape-src/output-file.c (file_tapefd_can_fork): New function that
          return 1 if the file: can be run under a forked process.
        * tape-src/output-file.h (file_tapefd_can_fork): Prototype.
-       * tape-src/output-null.c (null_tapefd_can_fork): New function that 
+       * tape-src/output-null.c (null_tapefd_can_fork): New function that
          return 1 if the null: can be run under a forked process.
        * tape-src/output-null.h (null_tapefd_can_fork): Prototype.
        * tape-src/output-rait.c (rait_close, rait_tapefd_ioctl): Fork only if
        * tapefd_can_fork() return 1.
-       * tape-src/output-rait.c (rait_tapefd_can_fork): New function that 
+       * tape-src/output-rait.c (rait_tapefd_can_fork): New function that
          return 1 if the rait: can be run under a forked process.
        * tape-src/output-rait.h (rait_tapefd_can_fork): Prototype.
-       * tape-src/output-tape.c (tape_tapefd_can_fork): New function that 
+       * tape-src/output-tape.c (tape_tapefd_can_fork): New function that
          return 1 if the tape: can be run under a forked process.
        * tape-src/output-tape.h (tape_tapefd_can_fork): Prototype.
        * tape-src/tapeio.c (struct virtualtape): Add xxx_tapefd_can_fork and
          initialize vtable[];
-       * tape-src/tapeio.c (tapefd_can_fork): New function to can the driver 
+       * tape-src/tapeio.c (tapefd_can_fork): New function to can the driver
          xxx_tapefd_can_fork function.
        * tape-src/tapeio.h (tapefd_can_fork): Prototype.
 
 2003-03-04  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * changer-src/chg-zd-mtx.sh.in: Default for driveslot is 0.
-       * NEWS: default driveslot for chg-zd-mtx is now 0.
 
 2003-03-04  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * amplot/amplot.awk: Add 'color' to command if bw is set.
        * amplot/amplot.g: Change line 6 to line 8.
        * man/amplot.8: Document -b option.
-       * NEWS: Document amplot -b option.
 
 2003-03-04  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
 2003-02-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Patch by Eric Doutreleau <Eric.Doutreleau@int-evry.fr>
-
+       
        * restore-src/amidxtaped.c: Use the device sent by the changer.
 
 2003-02-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        * restore-src/amidxtaped.c: Remove lock 'unlink(conf_logfile)' on
          all failure path.
 
-2003-02-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Patch by Martin Forssen <maf@appgate.com>
-
-       * server-src/changer.c (changer_label): Do not amfree(rest).
-
-2003-02-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2003-02-28  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * Amanda 2.4.4 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.4).
+       * server-src/changer.c: Sync with 2.4.4.
 
 2003-02-21  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * client-src/client_util.c: Print error except ENOENT for 
+       * client-src/client_util.c: Print error except ENOENT for
          exclude/include files.
 
 2003-02-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 2003-02-20  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * server-src/conffile.c (init_defaults): conf_printer.s must be set 
+       * server-src/conffile.c (init_defaults): conf_printer.s must be set
          with stralloc("").
 
 2003-02-12  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 2003-02-12  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * server-src/tapefile.c (read_tapelist): return 1 if can't open the 
+       * server-src/tapefile.c (read_tapelist): return 1 if can't open the
          tapelist file.
 
 2003-02-12  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amcheck.c: New -a option.
        * man/amcheck.8.in: Document it.
-       * NEWS: Document it.
 
 2003-02-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
 
        * man/amtapetype.8.in: Fix example.
 
-2003-01-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * Amanda 2.4.4b1 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.4b1).
-
 2003-01-31  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * common-src/amanda.h: #define S_ISDIR if not already defined.
 
 2003-01-23  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
-       * recover-src/extract_list.c (add_extract_item, delete_extract_item): 
+       * recover-src/extract_list.c (add_extract_item, delete_extract_item):
          Check also for level when comparing label.
 
-2003-01-17  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/dumper.c (update_dataptr): Loop if rc == 0.
-
 2003-01-17  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        Do not build chg-scsi-chio, it is buggy.
 2003-01-03  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        Add new maxpromoteday option in a dumptype.
-       * NEWS: Document it.
        * example/amanda.conf.in: Give an example
        * man/amanda.8.in: Document it.
        * server-src/amadmin.c: Print it in the disklist subcommand.
 
        * tape-src/output-tape.c: Add a ; after f = MT_UNLOAD
 
-2003-01-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * server-src/amcheck.c (handle_response): Print 'request timed out' or
-         'reply timed out'.
-       * server-src/dumper.c (sendbackup_response): Print 'request timeout' or
-         'reply timeout'.
-
-2003-01-02  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * common-src/protocol.h (proto_t): Add prevstate field.
-       * common-src/protocol.c: Keep prevstate up to date.
-       * server-src/planner.c (handle_result): Use prevstate to write
-         Request or Estimate timeout.
-
 2003-01-01  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        Undo patch of 2002-11-27. That doesn't work well for the planner.
 
        * client-src/sendsize.c: Ditto.
        * common-src/amfeatures.c: Ditto.
        * common-src/debug.c: Ditto.
-       * common-src/file.c: Ditto.
-       * common-src/security.c: Ditto.
        * recover-src/amrecover.c: Ditto.
        * recover-src/extract_list.c: Ditto.
        * recover-src/set_commands.c: Ditto.
        * recover-src/uparse.y: Ditto.
        * recover-src/uscan.l: Ditto.
-       * server-src/amcheck.c: Ditto.
        * server-src/amindexd.c: Ditto.
        * server-src/amlabel.c: Ditto.
-       * server-src/amlogroll.c: Ditto.
        * server-src/amtape.c: Ditto.
        * server-src/amtrmidx.c: Ditto.
        * server-src/amtrmlog.c: Ditto.
        * server-src/changer.c: Ditto.
        * server-src/conffile.c: Ditto.
-       * server-src/diskfile.c: Ditto.
        * server-src/driver.c: Ditto.
        * server-src/driverio.c: Ditto.
        * server-src/dumper.c: Ditto.
        * server-src/find.c: Ditto.
-       * server-src/getconf.c: Ditto.
        * server-src/holding.c: Ditto.
        * server-src/logfile.c: Ditto.
        * server-src/planner.c: Ditto.
        * server-src/driver.c (startaflush): New function to start a flush to
          tape.
 
+2002-12-27  Jean-Louis Martineau <martineau@iro.umontreal.ca>
+
+       * server-src/diskfile.c (parse_diskline): Allow skip in dumptype.
+
 2002-12-23  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amstatus.pl.in: Parse features from PORT-WRITE line.
        * recover-src/extract_list.c (extract_files_child): Set dumptype to
          IS_SAMBA_TAR if it's a SAMBA backup. Don't pass the G flag to tar
          if it's IS_SAMBA_TAR.
-       
+
 2002-12-18  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * amplot/amplot.awk: Parse line with features, parse ENDFLUSH line.
 
        * amplot/amplot.awk: Parse newer log lines.
 
-2002-12-12  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
-       * client-src/selfcheck.c: Typo.
-
-2002-12-11  Jean-Louis Martineau <martineau@iro.umontreal.ca>
-
+2002-12-11  Jean-Louis Martineau <martineau@iro.umontreal.ca> 
        * server-src/reporter.c (output_stats): Typo.
 
 2002-12-09  Jean-Louis Martineau <martineau@iro.umontreal.ca>
        * server-src/amadmin.c: Fix for newer days_diff.
        * server-src/planner.c: Fix for newer days_diff.
 
+2002-11-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * client-src/amandad.c: Fix compiler warning.
+       * common-src/Makefile.am (bsdsecurity): Link with file.o.
+       * common-src/bsd-security.c: Fix compiler warning.
+       * common-src/bsd-security.c (construct_datestamp, construct_timestamp):
+         Add function if TEST.
+       * server-src/chunker.c: Fix compiler warning.
+       * server-src/dumper.c: Fix compiler warning.
+
 2002-11-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * tape-src/tapetype.c: Cast time_t to long for printing.
 
 2002-11-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/planner.c (delay_dumps): Use ap_snprintf.
+       * server-src/planner.c (delay_dumps): Use snprintf.
 
 2002-11-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
 2002-11-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * docs/TAPE.CHANGERS: Sync with 2.5.0
-       * changer-src/chg-juke.sh.in: New changer from 2.5.0
-       * changer-src/chg-rait.sh.in: New changer from 2.5.0
-       * changer-src/chg-null.sh.in: New changer from 2.5.0
-       * changer-src/Makefile.am: Install them.
-       * configure.in (AC_CONFIG_FILES): Add chg-juke.sh.in, chg-rait.sh.in and
-         chg-null.sh.in
+       * docs/TAPE.CHANGERS: Sync with 2.4.3.
 
 2002-11-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
        * server-src/reporter.c: Fix for LPRCMD not defined.
 
+2002-11-14  Marc Mengel <mengel@fnal.gov>
+
+       New changer scripts for use with rait: code, run several other
+       changers in tandem and return a rait: tape device.  Makes fake
+       amanda.conf files under AMANDA_DEBUGDIR for each changer used,
+       then cleans up.
+
+       * changer-src/chg-rait.sh.in:   New file. Multi-changer script.
+       * changer-src/chg-null.sh.in:   New File. Null-device changer script.
+       * docs/TAPE.CHANGERS:  Descriptions of above.
+       * configure.in: added above files.
+       * changer-src/Makefile.am: Likewise.
+
 2002-11-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Patch by Orion Poplawski <orion@colorado-research.com>
 
        * changer-src/scsi-defs.h (B, B1): Check if already defined.
        * server-src/taper.c: Some cast to int.
        * tape-src/amdd.c (read_func, write_func): Complete prototype.
-       * tape-src/tapeio.h (tapefd_read, tapefd_write): return ssize_t, 
+       * tape-src/tapeio.h (tapefd_read, tapefd_write): return ssize_t,
          third argument is size_t.
        * tape-src/tapeio.c: Ditto.
-       * tape-src/output-file.h (file_tapefd_read, file_tapefd_write): return 
+       * tape-src/output-file.h (file_tapefd_read, file_tapefd_write): return
          ssize_t, third argument is size_t.
        * tape-src/output-file.c: Ditto.
-       * tape-src/output-null.h (null_tapefd_read, null_tapefd_write): return 
+       * tape-src/output-null.h (null_tapefd_read, null_tapefd_write): return
          ssize_t, third argument is size_t.
        * tape-src/output-null.c: Ditto.
        * tape-src/output-rait.h (rait_read, rait__write): return ssize_t,
-         third argument is size_t.
+          third argument is size_t.
        * tape-src/output-rait.c: Ditto.
-       * tape-src/output-tape.h (tape_tapefd_read, tape_tapefd_write): return 
+       * tape-src/output-tape.h (tape_tapefd_read, tape_tapefd_write): return
          ssize_t, third argument is size_t.
        * tape-src/output-tape.c: Ditto.
 
 
 2002-11-04  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-        * configure.in: Remove --disable-libtool.
-        * */Makefile.am: Remove WANT_LIBTOOL.
+       * configure.in: Remove --disable-libtool.
+       * */Makefile.am: Remove WANT_LIBTOOL.
 
 2002-11-04  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amtape.c: Ditto.
        * server-src/amtrmidx.c: Ditto.
        * server-src/amtrmlog.c: Ditto.
+       * server-src/chunker.c: Ditto.
        * server-src/diskfile.c: Ditto.
        * server-src/driver.c: Ditto.
        * server-src/dumper.c: Ditto.
        * server-src/planner.c: Ditto.
        * server-src/reporter.c: Ditto.
        * server-src/taper.c: Ditto.
-       * server-src/conffile.c: (config_name, config_dir): Add declaration.
+       * server-src/conffile.c (config_name, config_dir): Add declaration.
 
 2002-11-03  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
          is_local_fstype): remove Prototype.
 
 2002-10-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-        Patch by Paul Bijnens <paul.bijnens@xplanation.com>
+       Patch by Paul Bijnens <paul.bijnens@xplanation.com>
 
-        * tape-src/tapetype.c: Detects and warns the user if the tape drive
+       * tape-src/tapetype.c: Detects and warns the user if the tape drive
          has hardware compression enabled.
 
 2002-10-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * restore-src/amrestore.c: New '-f <fileno>' flag, Do a rewind and
          'fsf <fileno>' if -f is set.
        * man/amrestore.8: Document -f flag.
-
+       
 2002-10-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * common-src/amfeatures.h (fe_amindexd_fileno_in_OLSD,
+       * common-src/amfeatures.h (fe_amindexd_fileno_in_OLSD, 
          fe_amindexd_fileno_in_ORLD): New amfeatures.
        * common-src/amfeatures.c (am_init_feature_set): Set
          fe_amindexd_fileno_in_OLSD and fe_amindexd_fileno_in_ORLD.
          fe_amindexd_fileno_in_OLSD or fe_amindexd_fileno_in_ORLD are set.
 
 2002-10-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Patch by Doug Kingston <dpk@pobox.com>
+       patch by Doug Kingston <dpk@pobox.com>
 
        * configure.in (NEED_PATH_ENV, IGNORE_UID_CHECK, IGNORE_FSTAB,
          DONT_SUID_ROOT): Defined if on *-pc-cygwin.
 
        * recover-src/extract_list.c (READ_TIMEOUT): Increased to 240*60.
 
-2002-10-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * Amanda 2.4.3 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.3).
-
 2002-09-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client-src/getfsent.c (open_fstab): Check if MNTTAB is defined.
-
-2002-09-19  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * NEWS: Changes in release 2.4.3.
+        * client-src/getfsent.c (open_fstab): Check if MNTTAB is defined.
 
 2002-09-19  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
 2002-09-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/taper.c (read_file): Initialize file,
+       * server-src/taper.c (read_file): Initialize file, 
          stat(file.cont_filename) before opening it.
-         
+          
 2002-09-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amverify.sh.in: Don't check that the device is
          a character device, it could be a file: or rait:
 
-2002-09-06  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2002-09-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * common-src/amfeatures.c (am_set_default_feature_set):
          fe_rep_options_sendbackup_options is a default feature.
 
-2002-09-06  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2002-09-06  Jean-Louis Martineau <martineau@iro.umontreal.ca>
 
        * server-src/amstatus.pl.in: Sort a disk in datestamp order.
 
 
        * server-src/reporter.c: Fix compilation error if LPRCMD is not defined.
 
-2002-08-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * Amanda 2.4.3b4 released.
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.3b4).
-       * NEWS: Changes in release 2.4.3b4.
-
 2002-08-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Patch by Jason Brooks <jason0@mail.wrs.com>
 
        * docs/chg-scsi.notes: New document.
-       * changer-src/chg-scsi.c: Adding printout of "emubarcode" values
+       * changer-src/chg-scsi.c: Adding printout of "emubarcode" values 
          in the debug file.
-       * changer-src/scsi-changer-driver.c: Added dlt8000 and L500 to
+       * changer-src/scsi-changer-driver.c: Added dlt8000 and L500 to 
          ChangerIO[].
        * changer-src/sense.c: Added dlt8000 and L500 to SenseType[].
 
 2002-08-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * tape-src/output-null.c (null_tape_stat, null_tape_access): Use 
+       * tape-src/output-null.c (null_tape_stat, null_tape_access): Use
          "/dev/null" instead of filename.
 
 2002-08-22  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * changer-src/scsi-hpux.c: Add amanda copyright.
+       * changer-src/chg-mtx.sh.in: Sync with 2.4.3 branch.
+       * changer-src/chg-scsi-chio.c: Ditto.
+       * changer-src/chg-scsi.c: Ditto.
+       * changer-src/scsi-aix.c: Ditto.
+       * changer-src/scsi-bsd.c: Ditto.
+       * changer-src/scsi-cam.c: Ditto.
+       * changer-src/scsi-changer-driver.c: Ditto.
+       * changer-src/scsi-defs.h: Ditto.
+       * changer-src/scsi-hpux_new.c: Ditto.
+       * changer-src/scsi-irix.c: Ditto.
+       * changer-src/scsi-linux.c: Ditto.
+       * changer-src/scsi-solaris.c: Ditto.
+       * tape-src/tapeio.c: Ditto.
 
 2002-08-21  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * common-src/amanda.h: Fix bad #define.
 
 2002-07-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Patch by David Munro <D.Munro@surrey.ac.uk>
+       Patch by
+         David Munro <D.Munro@surrey.ac.uk>
 
        * common-src/sl.c (new_sl): Alloc (sl_t) instead of (sl_t *).
-         
+          
 2002-06-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Bug reported by
+       Bug reported by 
          Jonathan R. Johnson <Jonathan.Johnson@MinnetonkaSoftware.com>
 
        * server-src/reporter.c: Fix psfname filename.
          fe_rep_options_sendbackup_options.
        * common-src/amfeatures.c (am_init_feature_set): Add
          fe_rep_options_features.
-       * client-src/selfcheck.c: Write REP packet according to server features.
-       * client-src/sendbackup.c: Ditto.
+       * client-src/selfcheck.c: Write REP packet according to server features.        * client-src/sendbackup.c: Ditto.
        * client-src/sendsize.c: Ditto.
 
 2002-04-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * common-src/amfeatures.h: 
+       * common-src/amfeatures.h:
             Rename fe_g_options_maxdump  to fe_req_options_maxdumps
             Rename fe_g_options_hostname to fe_req_options_hostname
             Rename fe_g_options_features to fe_req_options_features
 
 2002-04-22  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amcheck.c (start_host): Check the todo bit before
+       * server-src/amcheck.c (start_host): Check the todo bit before 
          sending noop REQ.
 
 2002-04-21  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * client-src/sendbackup.c: Ditto.
        * client-src/sendsize.c: Ditto.
 
-2002-04-20  Thomas Hepper <th@ant.han.de>
-       * changer-src/scsi-aix.c: Fixed bug with the setting of the GSC driver
-         Added detection and setting of device type tape/robot
-       * changer-src/scsi-bsd.c: Added detection and setting of device 
-         type tape/robot
-       * changer-src/scsi-cam.c: Added detection and setting of device 
-         type tape/robot
-       * changer-src/scsi-hpux_new.c: Added detection and setting of device 
-         type tape/robot
-       * changer-src/scsi-linux.c: Added detection and setting of device 
-         type tape/robot
-       * changer-src/scsi-solaris.c: Added detection and setting of device 
-         type tape/robot
-       * changer-src/scsi-irix.c: Added detection and setting of device 
-         type tape/robot
-       * changer-src/scsi-changer-driver.c: Now there is an device handler
-         for an generic tape and an generic robot.
-         The result length from the read element status is now checked
-         and only fields which are in this area are used.. (Some librarys
-         retrun only 4 byte, expected are 52)
-       * changer-src/scsi-defs.h: Fixed the some defines in 
-         ElementStatusPage_T, 
-
 2002-04-19  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * client-src/client_util.c (parse_g_options) New function to parse
 
 2002-04-19  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/diskfile.c: Improve message for missing features.
+        * server-src/diskfile.c: Improve message for missing features.
 
 2002-04-19  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        Add many features.
-       * common-src/amfeatures.c (am_set_default_feature_set): New function
+       * common-src/amfeatures.c (am_set_default_feature_set): New function 
          to set the default features set.
        * common-src/amfeatures.h (am_set_default_feature_set): Prototype.
-       * common-src/amfeatures.h: Rename amanda_feature_auth_keyword to
+       * common-src/amfeatures.h: Rename amanda_feature_auth_keyword to 
          fe_options_auth.
        * client-src/client_util.c: Check features.
        * server-src/amcheck.c: Ditto.
        * server-src/diskfile.h (optionstr): Change prototype.
        * client-src/sendsize.c: Fix compiler warning.
 
+2002-04-18  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/amfeatures.c: Include "amfeatures.h"
+       * common-src/rsh-security.c: Don't assert on undefined variable.
+
 2002-04-17  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * common-src/amfeatures.c: Renamed from features.c
        * client-src/sendbackup.c: Ditto.
        * client-src/sendsize.c: Ditto.
        * server-src/amcheck.c: Ditto.
+       * server-src/chunker.h: Ditto.
        * server-src/diskfile.h: Ditto.
        * server-src/dumper.c: Ditto.
        * server-src/planner.c: Ditto.
        * client-src/sendbackup.c: Ditto.
        * client-src/sendsize.c: Ditto.
        * server-src/diskfile.c: Ditto.
+       * server-src/planner.c: Fix compiler warning.
 
 2002-04-13  John R. Jackson (jrj@purdue.edu)
 
        * server-src/diskfile.c: Fix memory leak.
 
+2002-04-13  John R. Jackson (jrj@purdue.edu)
+
+       * server-src/amcheck.c: Fix error parsing in packet.
+
 2002-04-13  John R. Jackson (jrj@purdue.edu)
 
        * common-src/features.c: New file.  Add support for feature sets so
          Improve parsing.
        * client-src/sendbackup.c: Ditto.
        * client-src/sendsize.c: Ditto.
+       * common-src/bsd-security.c: Minor message change.
        * common-src/error.c: Use strcasecmp.
        * common-src/protocol.c: Use dbprintf for PROTO_DEBUG and improve
-         messages.  Improve parsing.
-       * common-src/security.c: Improve parsing.
+         messages.
+       * restore-src/amidxtaped.c: Improve parsing.
        * server-src/amcheck.c: Ask for client features via "noop" before
          doing the real "selfcheck" service requests.  Improve parsing.
        * server-src/amflush.c: Minor coding format cleanup.
+       * restore-src/amindexd.c: Improve parsing.
+       * server-src/chunker.c: Deal with features string in commands.  Improve
+         parsing.
        * server-src/diskfile.c: Initialize the features hosttype field.
        * server-src/diskfile.h: Add the features hosttype field.
        * server-src/driver.c: Save the features from the schedule.  Clean
        * server-src/taper.c: Deal with features string in commands.  Improve
          parsing.
 
+2002-04-12  John R. Jackson (jrj@purdue.edu)
+
+       * server-src/driver.c: Fix crash when only processing a tape queue
+         (e.g. amflush).
+
+2002-04-11  John R. Jackson (jrj@purdue.edu)
+
+       * server-src/driver.c: Protect against crash when taper has died.
+
 2002-04-11  John R. Jackson (jrj@purdue.edu)
 
        * common-src/stream.c: Clean up an error message.
 
+2002-04-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * docs/DUMPER-API: Remove the section about USER and GROUP.
+
 2002-04-09  John R. Jackson (jrj@purdue.edu)
 
        * server-src/driver.c: Fix send of QUIT to taper when it is down.
 
+2002-04-07  John R. Jackson (jrj@purdue.edu)
+
+       * server-src/dumper.c: Change sendbackup response parsing to handle
+         2.4 changes.  Improve packet parse error processing.  Make packet
+         logging conditional on an #ifdef instead of commented out.
+
+2002-04-07  John R. Jackson (jrj@purdue.edu)
+
+       * client-src/amandad.c: Fix FORCE_USERID to run the service as the
+         client user if amandad was started as root.
+
+2002-04-07  John R. Jackson (jrj@purdue.edu)
+
+       * common-src/clock.c: Move definition of amanda_gettimeofday() macro
+         to the header file so it could be used other places.  Use new
+         amanda_timezone macro to avoid some #ifdef's.
+       * common-src/clock.h: Ditto.
+       * common-src/bsd-security.c: Fix compatibility problems with pre-2.5
+         servers trying to talk to 2.5 clients.  The HANDLE value was not
+         being properly handled, and the sequence number was being ignored.
+
 2002-04-07  John R. Jackson (jrj@purdue.edu)
 
        * server-src/reporter.c: Move column routines to conffile.c so amcheck
        * changer-src/scsi-defs.h: Fix compiler warning and bug it was hiding.
        * changer-src/scsi-solaris.c: Ditto.
 
+2002-03-31  John R. Jackson (jrj@purdue.edu)
+
+       * client-src/amandad.c: Fix arguments to pkt_cat.
+       * common-src/bsd-security.c: Ditto.
+
 2002-03-31  John R. Jackson (jrj@purdue.edu)
 
        * client-src/amandad.c: Add relative timestamps to a lot of debug
        * client-src/sendbackup.c: Ditto.
        * client-src/sendbackup.h: Ditto.
        * client-src/sendsize.c: Ditto.
-       * common-src/Makefile.am: Ditto.
        * common-src/amanda.h: Ditto.
+       * common-src/bsd-security.c: Ditto.
        * common-src/clock.c: Ditto.
        * common-src/clock.h: Ditto.
        * common-src/debug.c: Ditto.
        * common-src/dgram.c: Ditto.
        * common-src/error.c: Ditto.
+       * common-src/file.c: Ditto.
        * common-src/pipespawn.c: Ditto.
-       * common-src/security.c: Ditto.
        * common-src/stream.c: Ditto.
        * common-src/util.c: Ditto.
        * man/amanda.8.in: Ditto.
 
 2002-03-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client-src/client_util.c (fixup_relative): New function to prepend 
+       * client-src/client_util.c (fixup_relative): New function to prepend
          the dirname if relative.
-       * client-src/client_util.c (build_exclude, build_include): Use 
+       * client-src/client_util.c (build_exclude, build_include): Use
          fixup_relative.
        * client-src/client_util.c (parse_options): Do not prepend the dirname.
        * client-src/selfcheck.c (check_options): Don't generate ERROR for samba
 
        * client-src/sendbackup-gnutar.c: Fix use of no_record.
 
-2002-03-24  Thomas Hepper ( th@ant.han.de)
-       * changer-src/chg-scsi-chio.c: Fixed problems introduced by the agets change
-       * client-src/sendbackup-dump.c: Fixed compile problem on AIX, no_record
-         is no longeer defined, ist is now options->no_record.
-
 2002-03-24  John R. Jackson (jrj@purdue.edu)
 
        * client-src/amandad.c: Make sure argv[0] is valid before using it.
        * server-src/disk_history.c: Ditto.
        * server-src/driver.c: Ditto.
        * server-src/dumper.c: Ditto.
-       * server-src/list_dir.c: Ditto.
        * common-src/amanda.h: Always pass the source file and line number
          to the memory routines to make it easier to debug.
        * common-src/alloc.c: Ditto.
        * common-src/file.c: Ditto.
-       * common-src/dgram.c: Ditto.
-       * common-src/dgram.h: Ditto.
-
-2002-03-24  Thomas Hepper ( th@ant.han.de)
-       * changer-src/chg-scsi.c: Fixed problems introduced by the agets change
-       * changer-src/chg-scsi.c (MapBarCode): Fixed error in eof handling
-         eof was not correctly detected, now use the feof function.
-       * changer-src/scsi-aix.c (SCSI_OS_Version()): New function to print
-         the rcsid 
-       * changer-src/scsi-aix.c: same as above
-       * changer-src/scsi-cam.c: same as above
-       * changer-src/scsi-hpux_new.c: same as above
-       * changer-src/scsi-irix.c: same as above
-       * changer-src/scsi-linux.c: same as above
-       * changer-src/scsi-solaris.c: same as above
-       * changer-src/scsi-changer-driver.c (DLT448ElementStatus()): Fixed 
-         error messages. Fixed some errors with the barcode handling.
 
 2002-03-23  John R. Jackson (jrj@purdue.edu)
 
        * configure.in: Add -R$dir as well as -L$dir on Solaris when processing
          --with-libraries to support shared libraries of support products.
 
+2002-03-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/chunker.c: Get result from dumper.
+       * server-src/driver.c: Send dumper result to chunker.
+       * server-src/driverio.c (chunker_cmd): Send DONE and FAILED command.
+       * server-src/driverio.h (chunker_t): New down field.
+       * server-src/dumper.c: Cleanup.
+       * server-src/logfile.c (logtype_str): Add "PARTIAL".
+       * server-src/logfile.h (logtype_e): Add L_PARTIAL log.
+       * server-src/reporter.c: Handle PARTIAL log.
+       * server-src/server_util.c (cmdstr): Add "PARTIAL".
+       * server-src/server_util.h (cmd_t): Add PARTIAL command.
+       * server-src/taper.c (read_file): Result is PARTIAL if dumper
+         result is not DONE.
+
 2002-03-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/tapefile.c (write_tapelist): Write to a temp file and
 2002-03-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amstatus.pl.in: Fix.
-       * server-src/conffile.c(get-compress): Change message for bad
+       * server-src/conffile.c(get-compress): Change message for bad 
          compress argument.
 
 2002-03-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amstatus.pl.in: Fix.
+       * client-src/client_util.c (parse_options): Parse auth= option.
+       * client-src/client_util.h (option_t): Add auth field.
+       * client-src/sendbackup.c: Use auth instead of bsd-auth.
+       * client-src/sendsize.c: Init auth.
 
 2002-03-09  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * client-src/sendbackup-dump.c: use amdevice as argument to
          amname_to_fstype.
+       * client-src/sendsize.c: Use amdevice as argument to amname_to_dirname.
+       * server-src/dumper.c: clear device if it is set to NODEVICE.
 
 2002-03-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * Amanda 2.4.3b3 released
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.3b3)
-
-2002-03-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * ReleaseNotes: New file.
-       * NEWS: New item for 2.4.3b3.
+       * server-src/amindexd.c: Compilation fix.
 
 2002-03-07 John R. Jackson (jrj@purdue.edu)
 
 
 2002-03-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amstatus.pl.in: Write "wait to flush" only if waittaper
+        * server-src/amstatus.pl.in: Write "wait to flush" only if waittaper
          is requested.
 
 2002-03-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 2002-02-16  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * common-src/debug.c (debug_open); Don't try to renmae an already
+       * common-src/debug.c (debug_open); Don't try to renmae an already 
          renamed file.
 
 2002-02-15  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/conffile.c (dump_configuration): Print multiple
+       * server-src/conffile.c (dump_configuration): Print multiple 
          exclude and include.
 
 2002-02-15  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 2002-02-15  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client-src/client_util.c (build_include, build_exclude): Fix for
+       * client-src/client_util.c (build_include, build_exclude): Fix for 
          bad eof detection.
 
 2002-02-15  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
          the exclude file.
        * client-src/client_util.c (add_include): Add an include to the
          include file.
-       * client-src/client_util.c (build_exclude): Concat all excludes in
+       * client-src/client_util.c (build_exclude): Concat all excludes in 
          one file.
-       * client-src/client_util.c (build_include): Concat all includes in
+       * client-src/client_util.c (build_include): Concat all includes in 
          one file.
        * client-src/client_util.h (build_exclude, build_include): Prototype.
-       * client-src/selfcheck.c.diff (check_options): Call build_exclude
+       * client-src/selfcheck.c.diff (check_options): Call build_exclude 
          and build_include.
-       * client-src/sendsize.c.diff: Call gtar with one
+       * client-src/sendsize.c.diff: Call gtar with one 
          exclude file/include file.
-       * client-src/sendbackup-gnutar.c.diff: Call gtar with one
+       * client-src/sendbackup-gnutar.c.diff: Call gtar with one 
          exclude file/include file.
 
 2002-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * server-src/planner.c: Use new protocol if include is used.
        * client-src/client_util.h (option_t): Add include_file and include_list
        * client-src/client_util.c (parse_options): Parse include.
-       * client-src/selfcheck.c (check_options): Print ERROR if include are
+       * client-src/selfcheck.c (check_options): Print ERROR if include are 
          used for SAMBA or DUMP.
        * client-src/sendsize.c: Send include to gnutar.
        * client-src/sendbackup-gnutar.c: Send include to gnutar.
 
 2002-02-13  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client-src/client_util.c (parse_options): Check that files from 
+       * client-src/client_util.c (parse_options): Check that files from
          'exclude list' exist'.
-       * client-src/selfcheck.c (check_options): Give ERROR if multiple 
+       * client-src/selfcheck.c (check_options): Give ERROR if multiple
          exclude are used with samba or if exclude are used with DUMP.
 
 2002-02-13  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client_src/client_util.c (parse_options): Function to parse
-         the option string.
+       * client-src/sendbackup.h: Remove bad stuff introduced in previous
+         patch.
+       * client-src/sendbackup-gnutar.c: Ditto.
+
+2002-02-13  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * client_src/client_util.c (parse_options): Function to parse 
+         the option string. 
        * client_src/client_util.h (parse_options): Prototype.
        * client_src/client_util.h (option_t): Struct for options.
        * client_src/Makefile.am: Compile client_util.
 
 2002-02-12  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * common-src/pipespawn.c (pipespawnv): New funtion taking an
+       * common-src/pipespawn.c (pipespawnv): Typo, ap_snprintf -> snprintf.
+
+2002-02-12  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/pipespawn.c (pipespawnv): New funtion taking an 
          argv argument.
        * common-src/pipespawn.h (pipespawnv): Prototype.
 
 
        * changer-src/chg-zd-mtx.sh.in: Don't use '^' in expr match argument.
 
+2002-02-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/fileheader.c (build_header): Typo.
+
 2002-02-10 John R. Jackson (jrj@purdue.edu)
 
        * configure.in: Add new file-pad tapetype option to take the place
 
        * common-src/alloc.c: Fix type mismatch issues discovered by splint
          (www.splint.org).  Compliments of jens persson <jens@persson.cx>.
+       * common-src/bsd-security.c: Ditto.
        * common-src/debug.c: Ditto.
        * common-src/dgram.c: Ditto.
        * common-src/file.c: Ditto.
        * common-src/fileheader.c: Ditto.
        * common-src/fileheader.h: Ditto.
+       * common-src/genversion.c: Ditto.
        * common-src/getcwd.c: Ditto.
        * common-src/match.c: Ditto.
-       * common-src/security.c: Ditto.
        * common-src/stream.c: Ditto.
        * common-src/strstr.c: Ditto.
        * common-src/token.c: Ditto.
          argument list functions.
        * changer-src/scsi-changer-driver.c: Ditto.
        * common-src/debug.c: Ditto.
+       * common-src/dgram.c: Ditto.
        * common-src/error.c: Ditto.
+       * common-src/packet.c: Ditto.
+       * common-src/packet.h: Ditto.
+       * common-src/security.c: Ditto.
        * common-src/snprintf.c: Ditto.
        * common-src/token.c: Ditto.
        * common-src/token.h: Ditto.
 
 2002-02-03  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/holding.c (scan_holdingdir): Create the list in
+       * server-src/holding.c (scan_holdingdir): Create the list in 
          datestamp order.
 
 2002-02-02 John R. Jackson (jrj@purdue.edu)
          running OSF1 v5.1
 
 2002-02-01  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Reported by Roland E. Lipovits <rel@lipo.at0.net>
+        Reported by Roland E. Lipovits <rel@lipo.at0.net>
 
-       * server-src/amstatus.pl.in: Don't double-counts the failed
+       * server-src/amstatus.pl.in: Don't double-counts the failed 
          estimate partitions.
 
 2002-01-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * common-src/fileheader.c (build_header): Write the BLOCKSIZE= line
          after the dd if=... line.
-       * common-src/fileheader.c (parse_file_header): Ignore unknown line.
 
 2002-01-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amindexd.c: Clean up reporting of errors by gethostby*()
          functions.  Make sure they always report what they were trying to
          look up, and don't bother reporting errno (it would be h_errno).
-       * server-src/dumper.c: Ditto.
-       * server-src/planner.c: Ditto.
-
-2002-01-17  Thomas Hepper <th@ant.han.de>
-
-       * changer-src/scsi-changer-driver.c (DecodeSense): Check if it is
-         an normal or an extended result from request sense, and only
-         print the correct infos for the detected type.
-       * changer-src/scsi-changer-driver.c (RequestSense): Use the passed
-         pointer to store the result from request sense. Do not allocate
-         an own buffer. Fixed the bufer size which is passed to teh SCSI
-         function.
-       * changer-src/scsi-changer-driver.c (ChangerStatus): Use the macros
-         for setting the device to use for query, don't use fix values.
-       * changer-src/scsi-changer-driver.c (SCSI_Run): skip the sleep
-         if the status is ok, only sleep if we will loop.
-       * changer-src/scsi-changer-driver.c (DebugPrint): Print an timestamp
-         to see how many time is used between the prints and so see where
-         the time is gone.
 
 2002-01-13  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * common-src/fileheader.h (dumpfile_t): Add blocksize field.
        * common-src/fileheader.h (build_header): Change prototype.
-       * common-src/fileheader.c (fh_init): blocksize default to
+       * common-src/fileheader.c (fh_init): blocksize default to 
          DISK_BLOCK_BYTES.
        * common-src/fileheader.c (parse_file_header): Parse BLOCKSIZE= line.
-       * common-src/fileheader.c (build_header): Remove blocksize parameter,
+       * common-src/fileheader.c (build_header): Remove blocksize parameter, 
          write the BLOCKSIZE= line.
        * tape-src/tapeio.c: set file.blocksize, Change call to build_header.
        * restore-src/amrestore.c: Ditto.
        * server-src/dumper.c: Ditto.
        * server-src/taper.c: Ditto.
        * server-src/holding.c: Ditto.
+       * server-src/chunker.c: Ditto.
 
 2002-01-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
        * server-src/planner.c: Check for dp->todo.
 
-2002-01-10   Thomas Hepper <th@ant.han.de>
-
-        * changer-src/scsi-changer-driver.c: Fixed prototype for SCSI_ReadElementStatus
-        * changer-src/scsi-changer-driver.c (eject_tape): Fixed error in the rewind 
-        * changer-src/scsi-changer-driver.c (unload): Fixed error in the rewind logic
-        * changer-src/scsi-changer-driver.c (load): Fixed error in the rewind logic
-        * changer-src/scsi-changer-driver.c (GetElementStatus): Fixed error in the parameter list to SCSI_ReadElementStatus
-        * changer-src/scsi-changer-driver.c (SCSI_ReadElementStatus): Changed the logic, if the size for DescriptorSize
-         is 0 try to get the size the old way, if this parameter greate 0 take this value as the size for the data
-         buffer which is used to hold the result. May fix a problem with an HP changer
-       * changer-src/scsi-defs.h: Updated the structs for the different element types (Media Changer, Storage, Tape, Import)
-
-
 2002-01-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Patch by Harlan Stenn <Harlan.Stenn@pfcs.com>
 
 
        * changer-src/Makefile.am: Run `perl -c' on perl script.
        * client-src/Makefile.am: Ditto.
+       * dumper-src/Makefile.am: Ditto.
        * server-src/Makefile.am: Ditto.
 
 2002-01-06  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 2002-01-04  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * Amanda 2.4.3b2 released
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.3b2)
-       * NEWS: New feature of amanda-2.4.3b2
+       * common-src/event.c: Use ASSERTIONS not ASSERT.
 
 2002-01-01  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * changer-src/scsi-irix.c (SCSI_OpenDevice): Cast to int.
        * common-src/match.c (clean_regex): Cast to int.
 
+2002-01-01  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+       Reported by <ian.willis@sge.net>
+
+       * common-src/rsh-security.c: Fix for RSH_DEBUG.
+
 2001-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * config/ltconfig: Remove.
+       * config/ltconfig: Remove
        * config/ltmain.sh, config/libtool.m4i: Update from libtool 1.4.2.
        * config/config.guess: Update from
-         ftp://ftp.gnu.org/gnu/config/config.guess.
-       * config/config.sub: Update from
-         ftp://ftp.gnu.org/gnu/config/config.sub.
-       * config/depcomp, config/install-sh, config/missing,
-         config/mkinstalldirs: Update from automake 1.5.
+         ftp://ftp.gnu.org/gnu/config/config.guess
+       * config/config.sub: Update from 
+         ftp://ftp.gnu.org/gnu/config/config.sub
+       * config/depcomp, config/install-sh, config/missing, 
+         config/mkinstalldirs: Update from automake 1.5
        * config/Makefile.am (EXTRA_DIST): Remove ltconfig.
 
 2001-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * configure.in: Add missing [.
 
+2001-12-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+       Patch by Jason Thomas <jason@topic.com.au>
+            and Eric Siegerman <erics@telepres.com>
+
+       * common-src/bsd-security.c (check_user_amandahosts): improve message.
+
 2001-12-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/driver.c: Do not go in degraded mode in nodump mode.
        * server-src/driver.c (main): Don't check the value of RESERVE.
        * server-src/driver.c (find_diskspace): Remove as_pref variable.
        * server-src/driverio.c (getresult): cast cmd_t.
-       * server-src/dumper.c (update_dataptr): save_type is a filetype_t.
+       * server-src/chunker.c (databuf_flush): save_type is a filetype_t.
        * server-src/find.c (search_logfile): Remove host_undo_ch and
          disk_undo_ch variables.
        * server-src/holding.c (pick_datestamp): Remove result variable.
 
 2001-12-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * restore-src/amrestore.c: Fix compiler warning.
+       * client-src/selfcheck.c: Fix compiler warning.
        * changer-src/chg-scsi.c: Ditto.
-       * common-src/fileheader.c: Ditto.
        * changer-src/scsi-changer-driver.c: Ditto.
        * changer-src/scsi-defs.h: Ditto.
-       * client-src/selfcheck.c: Ditto.
+       * server-src/server_util.c: Ditto.
+       * common-src/fileheader.c: Ditto.
 
 2001-12-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * configure.in: Set MAX_TAPE_BLOCK_KB on linux.
+       * configure.in: Set MAX_TAPE_BLOCK_KB on linux
 
 2001-12-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Patch by Blaz Zupan <blaz@amis.net>
 
        * changer-src/chg-zd-mtx.sh.in: typo.
 
-2001-12-20 Thomas Hepper <th@ant.han.de>
-       * changer-src/scsi-changer-driver.c: Return error if the find_empty returns an error
-         In function LogSense try to reset the error counter. Fixed wrong pDev struct pointer in
-         TapeStatus. Must be INDEX_TAPECTL and not INDEX_TAPE at the start of the function
-
 2001-12-18  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client-src/selfcheck.c (check_access): New function (old check_file 
+       * client-src/selfcheck.c (check_access): New function (old check_file
          function).
-       * client-src/selfcheck.c (check_file): Check that the filename is a 
+       * client-src/selfcheck.c (check_file): Check that the filename is a
          file.
        * client-src/selfcheck.c (check_dir): Check that dirname is a directory.
 
 2001-12-18  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Patch by Henning Schmiedehausen <henning@forge.intermeta.de>
 
-       * common-src/file.c (safe_cd): Create the AMANDA_DBGDIR and 
+       * common-src/file.c (safe_cd): Create the AMANDA_DBGDIR and
          AMANDA_TMPDIR directory.
 
-2001-12-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * docs/Makefile.am (pkgdata_DATA): Include RAIT and VTAPE-API.
-
 2001-12-12  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amverify.sh.in: Check that @AMANDA_TMPDIR@ exist.
 
        * server-src/amstatus.pl.in: Fixup for estimate, write flush line.
 
-2001-12-09  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/reporter.c (output_summary): Set origsize and 
-         outsize correctly.
-
-2001-12-09  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/driver.c (start_some_dumps): Fixup length of dumporder.
-
 2001-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * recover-src/extract_list.c: You can change the tape device
 
 2001-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * restore-src/amrestore.c (restore): try to find the next chunk
+       * restore-src/amrestore.c (restore): try to find the next chunk 
          in the current directory.
 
 2001-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * example/amanda.conf.in: typo.
 
 2001-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       
+
        Patch by Roland E. Lipovits <rel@lipo.at0.net>
        * example/amanda.conf.in: typo.
 
 2001-12-04  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/dumper.c, server-src/taper.c: Replace TRY_AGAIN
-       by TRYAGAIN.
+       * server-src/dumper.c, server-src/taper.c, server-src/chunker.c:
+       Replace TRY_AGAIN by TRYAGAIN.
 
-2001-11-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2001-11-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+       Patch by Michael D. Beynon <beynon@ll.mit.edu>
 
-       * Amanda 2.4.3b1 released
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.3b1)
-       * NEWS: New feature of amanda-2.4.3
+       * server-src/driver.c (main): Take care of empty tapeq.
 
 2001-11-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
 2001-11-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/planner.c: Add host, disk, datestamp and level on
+       * server-src/planner.c: Add host, disk, datestamp and level on 
        FLUSH line. Add datestamp on DUMP line.
        * server-src/driver.c (read_flush): Read new format of FLUSH line.
        * server-src/driver.c (read_schedule): Read new format of DUMP line.
        * server-src/amdump.sh.in: Write a datestamp on stderr.
        * server-src/amstatus.pl.in: Works with autoflush.
 
-2001-11-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
+2001-11-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA> 
        * server-src/conffile.c (autoflush): New configuration options.
        * server-src/conffile.h (autoflush): New configuration options.
        * man/amanda.8.in: Document it.
 
        * recover-src/amrecover.h (cd_glob, cd_regex, cd_dir): New prototypes.
        * recover-src/set_commands.c (cd_glob, cd_regex, cd_dir): New functions.
-       * recover-src/uparse.y: Add new token CDX, call cd_glob instead
+       * recover-src/uparse.y: Add new token CDX, call cd_glob instead 
        of set_directory for cd command, call cd_regex for cdx command.
        * recover-src/uscan.l: On cdx string return CDX token.
        * recover-src/help.c: Document it.
        * man/amrecover.8.in: Document it.
 
-2001-11-03  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/taper.c: Backport from 2.5.0 the change to use only
-       one cmd_t type for all program.
-       * server-src/server_util.h: Likewise.
-       * server-src/server_util.c: Likewise.
-       * server-src/dumper.c.orig: Likewise.
-       * server-src/dumper.c: Likewise.
-       * server-src/driverio.h: Likewise.
-       * server-src/driverio.c: Likewise.
-       * server-src/driver.c: Likewise.
-       * server-src/amflush.c: Likewise.
-
-2001-11-03  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/reporter.c: Backport from 2.5.0 the change to allow
-       the "[host [disk]*]*" arguments on command.
-       * server-src/planner.c: Likewise.
-       * server-src/logfile.h: Likewise.
-       * server-src/logfile.c: Likewise.
-       * server-src/find.h: Likewise.
-       * server-src/find.c: Likewise.
-       * server-src/diskfile.h: Likewise.
-       * server-src/diskfile.c: Likewise.
-       * server-src/amtrmidx.c: Likewise.
-       * server-src/amindexd.c: Likewise.
-       * server-src/amflush.c: Likewise.
-       * server-src/amdump.sh.in: Likewise.
-       * server-src/amcheck.c: Likewise.
-       * server-src/amadmin.c: Likewise.
-       * restore-src/amrestore.c: Likewise.
-       * man/amrestore.8: Likewise.
-       * man/amflush.8.in: Likewise.
-       * man/amdump.8.in: Likewise.
-       * man/amcheck.8.in: Likewise.
-       * man/amanda.8.in: Likewise.
-       * man/amadmin.8.in: Likewise.
-       * common-src/match.c: Likewise.
-       * common-src/amanda.h: Likewise.
-
-2001-10-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * man/Makefile.am: add amdd.8 and ammt.8 to EXTRA_DIST.
-
 2001-09-26 John R. Jackson (jrj@purdue.edu)
 
        * server-src/reporter.c: Fix problem when column sizes are negative.
        * server-src/planner.c: Make sure we do not attempt to bump beyond
          level 9.
 
-2001-09-15 Thomas Hepper (th@ant.han.de)
+2001-09-16 Thomas Hepper (th@ant.han.de)
        * changer-src/chg-scsi.c: Added new config option autoinv, 
        if not set no auto inventory will be done if the label db is out of 
        sync. Reworked MapBarCode, now the parameters are passed as a struct 
        * tape-src/Makefile.am: Add chown/chgrp rules for ammt/amdd install
          so they end up like all the other Amanda programs.
 
-2001-08-16 John R. Jackson (jrj@purdue.edu)
-
-       * docs/Makefile.am: Fix PORTS.USAGE -> PORT.USAGE typo.
-
-2001-08-16 John R. Jackson (jrj@purdue.edu)
-
-       * configure.in: Change release name to "2.4.2p2-tapeio".  Add missing
-         CAM header checks from the 2.5 branch.
-
 2001-08-15 Thomas Hepper (th@ant.han.de)
        * changer-src/chg-scsi.c. Removed version 1 DB support from mapBarCode. Changed the way parameter
        are given to MapBarCode and returned from there. No a struct is passed where all infos
 
        * docs/PORT.USAGE: New document about how Amanda ports are used.
 
+2001-08-14 John R. Jackson (jrj@purdue.edu)
+
+       * client-src/sendsize.c: Fix patch merge goof (ap_snprintf -> snprintf).
+
 2001-08-14 John R. Jackson (jrj@purdue.edu)
 
        * common-src/stream.c: Add stream_client_privileged() function to
        Added global variables which are set by the tape_rdlabel function
        in eject/unload.
        Reworked the way how the updates of the labelfile are done.
-       * docs/TAPE.CHANGERS: Added note about solaris 8 and the sgen driver.
-
-2001-08-09 John R. Jackson (jrj@purdue.edu)
-
-       * tape-src/output-tape.c: Missed a reference to TAPE_BLOCK_BYTES
-         while doing the tapetype "blocksize" changes.
 
 2001-08-01 John R. Jackson (jrj@purdue.edu)
 
 
        * server-src/amcheck.c: Unlink the temp files as soon as they are
          created so they always go away when amcheck terminates.  Use
-         pipespawn() instead of system() to call the MAILER program.
+         pipespawn() instead of system() to call the MAILER program.  Call
+         dbopen()/dbclose() in main() to write to a debug file instead of
+         stderr.
 
 2001-08-01 John R. Jackson (jrj@purdue.edu)
 
        * server-src/conffile.c: Add tapetype "blocksize" keyword.  Use
          DISK_BLOCK_KB where appropriate instead of TAPE_BLOCK_SIZE.  Disallow
          negative tape length and tapemark size.
-       * client-src/sendbackup.c: Use new STREAM_BUFSIZE constant.  Use -1
-         for new default buffer size flag.
        * common-src/alloc.c: Add new amtable_free() function.  Adjust args
          to amtable_alloc() to be consistent with amtable_free().
        * common-src/amanda.h: Add new am_round() and am_floor() macros.
          Define new DISK_BLOCK_KB, DISK_BLOCK_BYTES, MAX_TAPE_BLOCK_KB,
          MAX_TAPE_BLOCK_BYTES constants.  Remove TAPE_BLOCK_SIZE and
          TAPE_BLOCK_BYTES.
+       * common-src/bsd-security.c: TAPE_BLOCK_BYTES -> NETWORK_BLOCK_BYTES.
+         Use -1 instead of DEFAULT_SIZE.
+       * common-src/rsh-security.c: Ditto.
        * common-src/fileheader.c: Change write_header() to build_header().
          Add blocksize arg.  Get rid of unused fill_buffer() function.
        * common-src/fileheader.h: Ditto.
        * restore-src/amrestore.c: Add new "-b blocksize" arg.  Document how
          the header is handled.  Deal with arbritrary tape record sizes.
        * server-src/amlabel.c: Use the tapetype blocksize.
+       * server-src/chunker.c: Use DISK_BLOCK_BYTES and DISK_BLOCK_KB as
+         appropropriate instead of older constants.  Rewrite disk I/O buffer
+         management.  Never pad output stream (e.g. to holding disk).  Use
+         -1 for default stream buffer size.
        * server-src/driver.c: Use DISK_BLOCK_KB where appropriate instead of
          TAPE_BLOCK_SIZE.
+       * server-src/driverio.c: Set chunker argv[0] to name based on which
+         dumper it is working with.
        * server-src/dumper.c: Use DISK_BLOCK_BYTES and DISK_BLOCK_KB as
          appropropriate instead of older constants.  Rewrite disk I/O buffer
          management.  Never pad output stream (e.g. to holding disk).  Use
        * tape-src/tapetype.c: Add "-b blocksize" arg.  Fix some end case
          aborts.
 
-2001-07-31 Ben Lewis (bhlewis@purdue.edu) via John R. Jackson (jrj@purdue.edu)
-
-       * configure.in: Add missing CAM header checks from the 2.5 branch.
-
-2001-07-30 John R. Jackson (jrj@purdue.edu)
-
-       * configure.in: Add CAM SCSI support section from the 2.5 branch.
-
 2001-07-30 Ben Lewis (bhlewis@purdue.edu) via John R. Jackson (jrj@purdue.edu)
 
        * recover-src/amrecover.c: Improve the "Unexpected server end of file"
        * docs/TAPE.CHANGER: Changes from Ben Lewis (bhlewis@purdue.edu) to
          document the new (but optional) searchable features.
 
-2001-07-20 John R. Jackson <jrj@purdue.edu>
+2001-07-19 John R. Jackson <jrj@purdue.edu>
 
-       * common-src/security.c: Use NUM_STR_SIZE instead of hard coded
-         constant.
-       * common-src/versuff.c.in: Ditto.
+       * common-src/error.c: Fix function prototype error.
 
 2001-07-19 John R. Jackson <jrj@purdue.edu>
 
 
 2001-07-10 John R. Jackson <jrj@purdue.edu>
 
-       * server-src/Makefile.am: Backport development branch chg-scsi code
-         to 2.4.2.
-       * changer-src/chg-scsi.c: Ditto.
-       * changer-src/libscsi.h: Ditto.
-       * changer-src/scsi-aix.c: Ditto.
-       * changer-src/scsi-bsd.c: Ditto.
-       * changer-src/scsi-cam.c: Ditto.
-       * changer-src/scsi-changer-driver.c: Ditto.
-       * changer-src/scsi-defs.h: Ditto.
-       * changer-src/scsi-hpux.c: Ditto.
-       * changer-src/scsi-hpux_new.c: Ditto.
-       * changer-src/scsi-irix.c: Ditto.
-       * changer-src/scsi-linux.c: Ditto.
+       * changer-src/scsi-aix.c: Convert Tape_Eject to Tape_Ioctl.
        * changer-src/scsi-solaris.c: Ditto.
-       * changer-src/sense.c: Ditto.
 
 2001-07-10 John R. Jackson <jrj@purdue.edu>
 
          redundant "OISD /" exchange.  Change "Trying" to "Trying host" to
          distinguish this from disk attempts.
 
+2001-06-19 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c: Made clean_slot a global var. Removed
+       the label db update stuff from the COM_SLOT part (moved to unload
+       in scsi-changer-driver.c)
+       * changer-src/scsi-changer-driver.c: Do an unload if the tape is
+       loaded in the Inventory function. Added an marker to avoid recursion
+       in Inventroy function. Added label db check in unload function and
+       call Inventroy if it indicates an out of sync db
+       
 2001-06-18 John R. Jackson <jrj@purdue.edu>
 
        * recover-src/extract_list.c: Do not pass a 'b' (blocking) factor
        * changer-src/chg-manual.sh.in: Add yet another online regex.  Found
          by George Herson <gherson@snet.net>.
 
+2001-06-12 Thomas Hepper <th@ant.han.de>
+       * changer-src/scsi-changer-driver.c (Inventory): Call Tape_Ready and let this function
+       decide how to get the tape drive status.
+       * changer-src/scsi-changer-driver.c (Tape_Ready): Now this function looks how to get
+       the tape drive status.
+       * changer-src/scsi-linux.c: changed some dbprintf to DebugPrint
+       
+2001-06-10 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c: If get_current_slot gets an error from the fscanf function
+       return also an error (-1) to the calling fucntion. (Fixes an error if the slot file
+       is created with an touch)
+       * changer-src/scsi-changer-driver.c: Fixed some NULL pointer errors in PrintConf
+       Fixed an error in the unload function if the destination slot for the unload is not empty.
+       (cut and paste error !!)
+       
+2001-06-07 Thomas Hepper <th@ant.han.de>
+       * changer-src/scsi-changer-driver.c: Change the type of TapeStatus from void to int.
+       In PrintConf changed the loop variable for scan of pDev from 3 to CHG_MAXDEV.
+       In PrintConf check if pDev[count].inquiry is a NULL pointer, and if yes skip.
+       * changer-src/scsi-irix.c: Changed a lot, now it should work.
+       * client-src/sendbackup-dump.c: Removed a { in the vxfsdump part. 
+       * tape-src/output-tape.c: Fixed the tape status checks, the structure elelemt
+       is called buf.mt_dposn not buf.mt.dposn.
+       
+2001-06-04 Thomas Hepper <th@ant.han.de>
+       * changer-src/scsi-changer-driver.c: Renamed Tape_Eject to Tape_Ioctl
+       incl. change of passwd parameter.
+
+2001-06-04 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c: include dmalloc.h for debugging of mem problems
+       * changer-src/scsi-cam.c: Replaced Tape_Eject with a more generic 
+       function to send different ioctls (Tape_Ioctl)
+       * changer-src/scsi-bsd.c: see above
+       * changer-src/scsi-hpux_new.c: see above
+       * changer-src/scsi-irix.c: If the device can be opened in SCSI_OpenDevice
+       set pDev[ip].avail to 1.
+       * changer-src/scsi-linux.c: include dmalloc.h for debugging of mem problems.
+       Fixed an invalid free in SCSI_OpenDevice. Replaced Tape_Eject with Tape_Ioctl.  
+       * changer-src/scsi-changer-driver.c: include dmalloc.h for debugging of mem problems
+       Eject the tape in the inventory function before the scan to get all
+       barcode labels. Check in GenericEject if the device is able to receive
+       SCSI commands, if not use the ioctl interface to eject the tape.
+       Same for the GenericRewind function.
+       Added the LogSense in the GenericEject function.
+       * changer-src/scsi-defs.h: Added define for Tape_Ioctl commands, IOCTL_EJECT.
+       
 2001-06-01 John R. Jackson <jrj@purdue.edu>
 
        * server-src/amindexd.c (build_disk_table): Make sure a holding disk
          image is used rather than a copy also on tape, if both exist.
 
+2001-06-01 Thomas Hepper <th@ant.han.de>
+       * changer-src/scsi-changer-driver.c: Added an range check in the load
+       function and abort if the requested slot is out of range.
+       Fixed in incorrect pointer in the eject function if the ioctl
+       interface is used
+
 2001-05-29 John R. Jackson <jrj@purdue.edu>
 
        * server-src/reporter.c: Fix PostScript output to only show what went
          on the tape, not what the total amount dumped.  Compliments of
          Joshua Baker-LePain <jlb17@duke.edu>.
 
+2001-05-28 Thomas Hepper <th@ant.han.de>
+       * changer-scsi/chg-scsi.c: Made the array for pDev configurable, #define CHG_MAXDEV
+       * changer-scsi/scsi-defs.h: Added the define for CHG_MAXDEV
+       * changer-src/scsi-cam.c: Set the flag pDev[x].avail to 1 if the device can be openend.
+       Added debug message if the open fails. Implemented the function Tape_Status (not tested)
+       * changer-src/scsi-changer-driver.c: Added the function DLT448ElementStatus, was lost
+       during merge from 2.4.2. The difference to GenericElementStatus is that the DecodeModeSense
+       needs an offset of 12, not 0 as in GenericElementStatus.
+       Added an unload/GenericResetStatus in the Inventory function if an bar code reader is 
+       available. This is to get the label from the loaded tape.
+       The function TapeStatus sets now the status regardless of the status of the tape.
+       If the device is capable for sending SCSI commands use the SCSI interface to get
+       the status of the tape.
+       * docs/TAPE.CHANGERS: Added some notes about the debuglevel keyword and a short
+       description on how to use the sgen interface on solaris 2.8
+       
 2001-05-18 John R. Jackson <jrj@purdue.edu>
 
        * client-src/patch-system.sh.in: Missed a reference to kamanda in the
          inetd.  Compliments of Tom Schutter <t.schutter@att.net>.  Add
          the TCP port for amandad for future use.
 
-2001-05-15 John R. Jackson <jrj@purdue.edu>
-
-       * restore-src/amidxtaped.c: Call tape_stat() instead of stat() to
-         decide if an image is a file or a tape.
-
 2001-05-14 John R. Jackson <jrj@purdue.edu>
 
        * client-src/amandad.c: Fix hang when the incoming packet size is
-         larger than the pipe buffer.  Also fix a buffer overflow bug.
-
-2001-05-11 John R. Jackson <jrj@purdue.edu>
-
-       * changer-src/chg-scsi.c: Add support for "-slot advance".
+         larger than the pipe buffer.  Also, report back when too much
+         data for a packet is returned by the service (this is not properly
+         diagnosed back to, e.g., amcheck, but that's for another day).
+       * common-src/bsd-security.c: Fix minor comment error.
 
 2001-05-11 John R. Jackson <jrj@purdue.edu>
 
          explicitly that all ports in the requested range were busy, or
          that a specific port failed bind() for an unexpected reason.
 
-2001-05-11 John R. Jackson <jrj@purdue.edu>
-
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.2p2)
-
-2001-05-10 John R. Jackson <jrj@purdue.edu>
-
-       * changer-src/scsi-changer-driver.c: Fix routine name in diagnostic
-         messages for DLT4000Eject.
-
 2001-05-07 John R. Jackson <jrj@purdue.edu>
 
        * client-src/sendbackup-dump.c: Do not use full path to sed.  Found by
          Roland E. Lipovits (rel@lipo.at0.net).
 
+2001-05-07 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c : Fixed NULL pointer in debug print of the config.
+       * changer-src/scsi-canger-driver.c : Try to get and set the status of the tape drive in
+       GenericElementStatus if there is an error condition. Move from tape to tape to get the
+       tape loaded if it is only ejected.
+       * changer-src/scsi-defs.h : New define for the Tape_Status fucntion, TAPE_NOT_LOADED
+       * changer-src/scsi-linux.c : Added return type for tape not loaded
+       * changer-src/scsi-solaris.c : In SCSI_ExecuteCommand force the direction to write if the
+       databuffersize is 0, if the direction is input the ioctl returns with errno 22, invalid argument.
+       The function Tape_Status will now return either tape loaded or not.
+       * example/chg-scsi-solaris.conf.in : Added pointer to doc/TAPE.CHANGERS on how to configure
+       the sgen driver.
+       * doc/TAPE.CHANGERS : Updated the description of the chg-scsi.conf options, short description on
+       how to confgure the sgen driver on solaris 2.8
+       
 2001-05-04 John R. Jackson <jrj@purdue.edu>
 
-       * config/depcomp: Fix problem with argument processing and update to
+       * config/depcomp: Fix problem with argument processing and update to
          latest version.
 
+2001-05-01 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c : Added patch for the slot advance command from John R. Jackson
+       * changer-src/scsi-changer-driver.c : Renamed EXB120BarCode to EXB_BarCode. The currently
+       known Exabyte libs handles the reader in the same way.
+       
+2001-04-28 Thomas Hepper <th@ant.han.de>
+       * changer-scsi/chg-scsi.c : Added missing break in MapBarCode
+       Changed the way an tape label is read, use tape_open to open the
+       device, not own open.
+       * changer-src/scsi-changer-driver.c : Changed the way an tape label 
+       is read, use tape_open to open the device, not own open.
+       * changer-src/scsi-linux.c : Fixed error on reopen of non SCSI devices
+       (/dev/nst0 for example)
+       
+2001-04-26 Thomas Hepper <th@ant.han.de>
+
+       * changer-src/scsi-aix.c : Added more different ret values depending on the SCSI
+       error condition. 
+       * changer-src/scsi-changer-driver.c: Split GenericElementStatus in GetElementStatus which
+       reads the element Status, and GenericElementStatus which handles the errors.
+       Removed DLT448ElementStatus. Rework the handling of some SCSI error conditions...
+       * changer-src/scsi-defs.h: Added more defs for the debug SECTION types.
+       * changer-src/scsi-linux.c: Fixed an bug in the non SCSI device handling in SCSI_OpenDevice
+       * changer-src/sense.c: Added EXB-210 defs, added defs for READ_ELEMENT_STATUS error conditions.
+       
 2001-04-25 John R. Jackson <jrj@purdue.edu>
 
        * changer-src/chg-rth.pl.in: Add exec_prefix back since it is usually
        * client-src/sendbackup-gnutar.c: Ditto.
        * client-src/sendsize.c: Ditto.
 
-2001-04-21 John R. Jackson <jrj@purdue.edu>
-
-       * tape-src/output-tape.c: Fix IRIX field reference (patch from Marc
-         W. Mengel <mengel@fnal.gov>).
+2001-04-15 Thomas Hepper <th@ant.han.de>
+       * Makefile.am: Added contrib/gsc files to EXTRA_DIST
+       
+2001-04-15 Thomas Hepper <th@ant.han.de>
+       * changer-src/scsi-aix.c: Rework of the SCSI interface, support
+       to talk to an device handled by the gsc driver (not tested yet)
+       * changer-src/scsi-bsd.c (SCSI_ExecuteCommand): Fix error in
+       device handling, Changed the return codes in case of an error
+       * changer-src/scsi-cam.c (SCSI_ExecuteCommand): Fix error in 
+       device handling, Changed the return codes in case of an error
+       * changer-src/scsi-changer-driver.c: Changed the way 
+       SCSI_ExecuteCommand passes error conditions back, error handling
+       should now be done by the calling function, SCSI_Run for example.
+       * changer-src/scsi-changer-driver.c (CheckMove): If the 
+       DeviceCapabilitiesPage is not set do not return an error, print
+       an warning to the debug file.
+       * changer-src/scsi-defs.h: New define for AIX_USE_GSC
+       New defines for the return codes of SCSI_ExecuteCommand
+       * changer-src/scsi-hpux_new.c: Fix error in device handling.
+       Changed the return codes in case of an error
+       * changer-src/scsi-irix.c: Fix error in device handling.
+       Changed the return codes in case of an error
+       * changer-src/scsi-solaris.c: Fix error in device handling.
+       Changed the return codes in case of an error
+       
+2001-04-15 Thomas Hepper <th@ant.han.de>
+       *contrib/gsc: Generic SCSI interface for AIX, used by chg-scsi
 
 2001-04-13 John R. Jackson <jrj@purdue.edu>
 
        * example/amanda.conf.in: Fix multiple holding disks comment.
-       * example/amanda.conf.chg-scsi.in: Ditto, plus bring this file into
-         sync with the base version.
 
-2001-04-12  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2001-04-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * client-src/getfsent.h (search_fstab): New prototype.
        * client-src/getfsent.c (search_fstab): New arg check_dev, skip
        * client-src/getfsent.c (open_fstab for linux): Open MOUNTED.
        * client-src/getfsent.c (close_fstab for linux): close MOUNTED.
        * client-src/getfsent.c (get_fstab_nextentry for linux): parse MOUNTED.
-       * client-src/getfsent.c (amname_to_devname, amname_to_dirname,
-       amname_to_fstype): Call search_fstab sequentialy with 1 and 0
+       * client-src/getfsent.c (amname_to_devname, amname_to_dirname, 
+       amname_to_fstype): Call search_fstab sequentialy with 1 and 0 
        for check_dev.
 
 2001-04-10 John R. Jackson <jrj@purdue.edu>
        * docs/INSTALL: Update location to GNUPLOT per Lars Hecking
          <lhecking@nmrc.ie>.
 
+2001-04-09 Thomas Hepper <th@ant.han.de>
+       * changer-src/scsi-changer-driver.c: More rework on the debug output.
+       changed definition SENSE_NO_TAPE to SENSE_TAPE_NOT_ONLINE
+       In function GenericRewind do an check before the rewind to see
+       if the tape is loaded.
+       * changer-src/scsi-defs.h: New #define for the debug, SECTION_TAPE
+       * changer-src/sense.c: New definition for SENSE_RETRY, ASC=4, ASCQ=1
+       
+2001-04-08  Alexandre Oliva  <aoliva@redhat.com>
+
+       * client-src/getfsent.c (search_fstab): Don't skip entry just
+       because device stats failed.
+
 2001-04-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * config/config.guess: Upgrade from ftp://ftp.gnu.org/pub/gnu/config
 
        * Makefile.am: Remove *.test.c from the distribution.
 
-2001-04-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Upgrade to the 2.5.0 code.
-
-       * changer-src/chg-zd-mtx.sh.in: Added barcode reader support,
-       >9 tape slot support, variable for 'offline' or 'ONLINE'
-       return value of tape device, and multi-config support.  Moved
-       all user settable variables to 'changerfile'.conf in the
-       amanda config directory.  Added commented out example of .conf
-       file into script.
-       * NEWS: updated chg-zd-mtx.sh.in changer.
-
 2001-04-02 John R. Jackson <jrj@purdue.edu>
 
-       * NEWS: Initial notes for 2.4.2p2.
+       * NEWS: Update some of the 2.4.2 items.
 
 2001-03-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amcleanupdisk.c: Change construct_datestamp call to pass
          indication that it should get the current time.
        * server-src/amflush.c: Ditto.
+       * server-src/chunker.c: Ditto.
        * server-src/driver.c: Ditto.
        * server-src/dumper.c: Ditto.
        * server-src/planner.c: Ditto.
        * client-src/sendsize.c: Send smbclient via pipe instead of command
          line arg.  Various minor cleanups.  Clean up listed incremental file
          handling.
-       * common-src/pipespawn.c: Support optional password pipe.  Various
-         minor cleanups.
-       * common-src/pipespawn.h: Support optional password pipe.  Various
-         minor cleanups.
-       * common-src/util.c: Backport fullread() and fullwrite() from main
-         branch.
-       * common-src/util.h: Backport fullread() and fullwrite() from main
-         branch.
        * docs/SAMBA: Update and cleanup.
+       * common-src/pipespawn.c: Import from 2.4.2 branch.
+       * common-src/pipespawn.h: Import from 2.4.2 branch.
+       * common-src/Makefile.am: Add pipespawn.[ch] references.
 
 2001-03-13 John R. Jackson <jrj@purdue.edu>
 
        * recover-src/extract_list.c (extract_files_child): Fix xfsrestore
          argument list processing.
 
+2001-03-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/dumper.c (read_datafd): set errstr and return on
+       databuf_write error.
+
+2001-03-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/dumper.c (read_indexfd): Ignore error while writing
+       to the index file. Log an L_INFO message.
+
 2001-03-09 John R. Jackson <jrj@purdue.edu>
 
        * server-src/taper.c: Initialize tape_fd to -1 and test in a couple
 2001-03-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Reported by Eric Schnoebelen <eric@cirr.com>
 
-       * server-src/changer.c (): Fix fd leak.
+       * server-src/changer.c (changer_command): Fix fd leak.
+
+2001-03-05  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/server_util.c (cmdstr, getcmd, putresult): New.
+       * server-src/server_util.h (cmdstr, getcmd, putresult): Prototype.
+       * server-src/server_util.h (cmd_t): New.
+       * server-src/driverio.c (cmdstr): Remove.
+       * server-src/driverio.c: Use new cmdstr and cmd_t.
+       * server-src/driverio.h: (tok_t): Remove.
+       * server-src/amflush.c: Use new cmd_t.
+       * server-src/driver.c: Use new cmd_t.
+       * server-src/chunker.c (cmd_t, getcmd, putresult): Remove.
+       * server-src/chunker.c: Use new cmd_t, getcmd and putresult.
+       * server-src/dumper.c (cmd_t, getcmd, putresult): Remove.
+       * server-src/dumper.c: Use new cmd_t, getcmd and putresult.
+       * server-src/taper.c (cmd_t, getcmd, putresult): Remove.
+       * server-src/taper.c: Use new cmd_t, getcmd and putresult.
+
+2001-03-05 John R. Jackson <jrj@purdue.edu>
+
+       * common-src/util.c: The fullread() and fullwrite() functions should
+         call read() and write(), not tapefd_read() and tapefd_write().
 
 2001-02-28  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amadmin.c (info_one): typo.
        * server-src/planner.c (setup_estimate): Don't re-ask for level 0
        if last_level is 0 and FORCE_NO_BUMP is set.
 
 
 2001-02-27 John R. Jackson <jrj@purdue.edu>
 
-       * configure.in: Copy ssize_t type check code from main branch.
+       * configure.in: Add some commentary about why pushdef/popdef are
+         needed around AC_CHECK_TYPE.
 
-2001-02-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+       Patch by Alex Pilosov <alex@pilosoft.com>
+
+       * changer-src/scsi-cam.c: Clean up some SCSI CAM code,
+       and permit use of both bus:target:lun(btl) and a full
+       device name (/dev/ch0) as changerdev.
+       
+2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+       Patch by Joe Rhett <jrhett@isite.net>
+       and Jason Hollinden <jhollind@sammg.com>
 
-       * docs/SYSTEM.NOTES: change cs.umd.edu by amanda.org.
+       * changer-src/chg-zd-mtx.sh.in:  Added barcode reader support,
+       >9 tape slot support, variable for 'offline' or 'ONLINE'
+       return value of tape device, and multi-config support.  Moved
+       all user settable variables to 'changerfile'.conf in the
+       amanda config directory.  Added commented out example of .conf
+       file into script.
 
 2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
 2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * changer-src/scsi-changer-driver.c (GenericRewind): init ret to 0
-       to remove compiler warning.
+       * restore-src/amrestore.c (main): init r to 0.
+
+2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * changer-src/scsi-defs.h (PrintConf): Add prototype.
+       * changer-src/scsi-changer-driver.c (SCSI_Run): Add prototype.
+       * changer-src/scsi-linux.c (ScanBus): remove btl variable, return 0.
 
 2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/planner.c (setup_estimate): ask for level 0 for
-       a new disk if force-bump is set,
-       log force-bump and force-nobump command.
+       * man/Makefile.am (EXTRA_DIST): add amdd.8 and ammt.8.
 
-2001-02-21 Thomas Hepper <thqant.han.de>
-       * changer-src/scsi-changer-driver.c: Do an Test Unit Ready
-         before sending SCSI commands in GenericRewind
-       * changer-src/chg-scsi.c: Fixed an type in the debug print
-         of the config file
+2001-02-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
+        * server-src/planner.c (setup_estimate): ask for level 0 for 
+        a new disk if force-bump is set, 
+        log force-bump and force-nobump command.
+
+2001-02-17 Thomas Hepper <th@ant.han.de>
+
+       * changer-scsi/chg-scsi.c: New Option -genconf to create an example config file
+        based on the information found on the system, works for Linux and BSD with cam
+        support. New config option debuglevel
+       * changer-src/scsi-changer-deriver.c: Reworked the debug output, it is now possible
+        to control the amount of information by the config option debuglevel in the config
+        file (docs follow), not complete yet.
+       * changer-src/scsi-changer-driver.c: New function PrintConf to create an example
+         config file.
+         New function DebugPrint to print debug information based on the variable debuglevel.
+         Replaced a lot of dbprintf with new Function DebugPrint
+       * changer-src/scsi-aix.c: changed parameter for ScanBus
+       * changer-src/scsi-irix.c: changed parameter for ScanBus
+       * changer-src/scsi-solaris.c: changed parameter for ScanBus
+       * changer-src/scsi-bsd.c: changed parameter for ScanBus
+       * changer-src/scsi-cam.c: Implemented function ScanBus
+       * changer-src/scsi-linux.c: Implemented function ScanBus
+       
 2001-02-09 John R. Jackson <jrj@purdue.edu>
 
        * server-src/diskfile.c: Fix core dump in test program.
          allows the status file to be moved to the main directory.
        * man/amanda.8.in: Document these changes.
 
-2001-02-05 John R. Jackson <jrj@purdue.edu>
+2001-02-08 Thomas Hepper <th@ant.han.de>
+
+       * changer-src/scsi-aix.c: Added dummy ScanBus function
+       * changer-src/scsi-bsd.c: Added dummy ScanBus function
+       * changer-src/scsi-cam.c: Added dummy ScanBus function
+       * changer-src/scsi-hpux_new.c: Added dummy ScanBus function
+       * changer-src/scsi-irix.c: Added dummy ScanBus function
+       * changer-src/scsi-defs.h: Added prototype for ScanBus function
+
+2001-02-04 John R. Jackson <jrj@purdue.edu>
 
        * man/amanda.8.in: Fix mailto to space separated, not comma.
 
          other Makefile.am files.
        * tape-src/Makefile.am: Add CLEANFILES rule to remove *.test.c.
 
+2001-02-03 John R. Jackson <jrj@purdue.edu>
+
+       * server-src/diskfile.c: Fix test program compilation error and bug
+         when just a config name was given on the command line.
+
 2001-02-02 John R. Jackson <jrj@purdue.edu>
 
        * server-src/reporter.c: Fix problem with enum being unsigned on
          some systems.
 
+2001-01-29 John R. Jackson <jrj@purdue.edu>
+
+       * tape-src/tapeio.c (tape_fsf): Go back to using snprintf as this
+         is now "the way".
+
 2001-01-29 John R. Jackson <jrj@purdue.edu>
 
        * tape-src/output-tape.c (tape_tapefd_status): Convert flag values
        * server-src/Makefile.am: Ditto.
        * tape-src/Makefile.am: Ditto.
 
-2001-01-24 John R. Jackson <jrj@purdue.edu>
-
-       * docs/VTAPE-API: Added.
-
 2001-01-23 John R. Jackson <jrj@purdue.edu>
 
        * configure.in: Add tapeio switch from Marc Mengel <mengel@fnal.gov>,
        * tape-src/tests/testdist: Ditto.
        * tape-src/tests/torture: Ditto.
 
+2001-01-24 John R. Jackson <jrj@purdue.edu>
+
+       * client-src/amandad.c: Improve packet logging.
+
+2001-01-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/driver.c (start_some_dumps): typo.
+
 2001-01-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/driverio.h (sched_t): new field no_space.
        * client-src/getfsent.c: Add some support for Redhat 7 /etc/fstab
          changes that indirectly reference the device for a file system.
 
-2001-01-20  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2001-01-22  Marc W. Mengel <mengel@fnal.gov>
 
-       * configure.in: AM_INIT_AUTOMAKE(amanda, 2.4.2p1)
+       * recover-src/extract_list.c: Added -U to tar recover options
+       to reduce errors recovering shared libs and/or binaries on
+       active filesystems.
 
 2001-01-20  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * NEWS: 2.4.2p1 is a bug fix release.
+       * docs/INSTALL: Notes about tar-1.13.19
 
-2001-01-20  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2001-01-17  Thomas Hepper <th@ant.han.de>
+
+       * changer-src/chg-scsi.c: Moved definitions for config_t and
+       changer_t into scsi-defs.h
+       * changer-src/chg-scsi.c: New config option havebarcode
+       * changer-src/scsi-changer-driver.c: Changed GenericBarCode do handle
+       the option havebarcode. Replaced NoBarCode with GenericBarCode.
+       Fixed compile warnings from -Wshadow
+       * changer-src/scsi-linux.c: New function ScanBus to scan the SCSI Bus.
+       not used yet.
+       * changer-src/scsi-solaris.c: Changed the return value to
+       Command.uscsi_status in SCSI_ExecuteCommand if the return from the
+       ioctl is not 0;
+       
+2001-01-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * docs/INSTALL: Notes about tar-1.13.19
+       * man/amanda.8.in: New section "HOST & DISK EXPRESSION" and 
+         "DATESTAMP EXPRESSION".
+       * man/amadmin.8.in: Document new usage.
+       * man/amflush.8.in: Document new usage.
+       * man/amcheck.8.in: Document new usage.
+       * man/amdump.8.in: Document new usage.
+       * man/amrestore.8: Document new usage.
+       * server-src/amadmin.c: Fix usage.
+       * server-src/amflush.c: Fix usage.
+       * server-src/amcheck.c: Fix usage.
+
+2001-01-08  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/diskfile.c (match_disklist): Return if no args.
+
+2001-01-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/diskfile.c (match_disklist): Fix.
+
+2001-01-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/diskfile.c (match_disklist): Updated for
+         [host [disk]*]* syntax.
 
-2001-01-07  Thomas Hepper <th@ant.han.de>
+2001-01-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * changer-src/chg-scsi.c: Moved defs. for config_t and changer_t
-       into scsi-defs.h
-       New option havebarcode to force the reading of the barcode labels
-       * changer/src/scsi-changer-driver.c: GenericBarCode now returns
-       true/false depending on the setting of havebarcode.
-       Removed EXB230DElementStatus, the exsisting Exabyte function works.
-       Fixed more warnings from -Wshadow
+       * common-src/match.c (match_datestamp): New function.
+       * common-src/amanda.h (match_datestamp): Prototype.
+       * server-src/amflush.c: Use match_datestamp.
+       * restore-src/amrestore.c: Use match_datestamp.
+
+2001-01-06  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/match.c (match_word): Support for leading ^ and
+         trailing $.
 
 2001-01-04 John R. Jackson <jrj@purdue.edu>
 
          any fatal error message to it and close the file so it has a good
          trace of what happened and when.
 
+2001-01-04  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * taper-src/am-dd.c: include "tapeio.h", fix debug warning.
+       * taper-src/am-mt.c: include "tapeio.h", fix debug warning.
+       * taper-src/output-rait.c: include "tapeio.h", new define for
+          rait_debug
+       * taper-src/tapeio.c(many): Remove unused tfd variable.
+       * taper-src/tapeio.h (tape_unload,tape_status): Prototype.
+
 2001-01-04 John R. Jackson <jrj@purdue.edu>
 
        * client-src/killpgrp.c: Calls to error() do not need a newline.
 
        * server-src/driver.c (continue_dumps): Don't reduce est_size if
          it is already larger than holding space allocated.
-       * server-src/dumper.c: Better handling of ENOSPC from open() and
+       * server-src/dumper.c: Remove all code for FILE_DUMP command.
+       * server-src/chunker.c: Better handling of ENOSPC from
          write_tapeheader().
 
 2001-01-04 John R. Jackson <jrj@purdue.edu>
        * server-src/amstatus.pl.in: Better support for TRY-AGAIN and
          ABORT-FINISHED result.
 
+2001-01-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amflush.c: Use getopt to parse argument.
+       * server-src/amflush.c: New [-D date]* argument.
+       * man/amflush.8.in: Document it.
+
 2001-01-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        Patch by Andreas F Mueller <afm@othello.ch>
 
        * server-src/amadmin.c (force_no_bump_one): Fix message.
 
+2001-01-01  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * tape-src/am-dd.c: include "amanda.h"
+       * tape-src/am-mt.c: include "amanda.h"
+       * tape-src/am-mt.c (main): res is int.
+       * tape-src/output-rait.c: include "amanda.h", do not define stderr.
+       * tape-src/tapeio.c (xxx_tapefd_read, plain_tapefd_read): second
+         argument should be "char *"
+       * tape-src/tapeio.c (xxx_tapefd_write, plain_tapefd_write): second
+         argument should be "const char *"
+
+2000-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/find.c (find_match): Use todo bit.
+       * server-src/find.c (find_dump): No arguments.
+       * server-src/find.h (find_dump): Change prototype.
+       * server-src/amadmin.c (find): New [host disk]* pair arguments.
+       * server-src/amindexd.c: Change call to find_dump().
+       * server-src/amtrmidx.c: Change call to find_dump().
+
+2000-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * configure.in: Don't check krb5 include if krb5 is not selected.
+
+2000-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * tape-src/Makefile.am (noinst_HEADERS): Add output-rait.h
+
+2000-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amadmin.c (diskloop): typo.
+
+2000-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amadmin.c (diskloop): New [host disk]* pair arguments.
+       * server-src/amadmin.c (diskloop, reuse, noreuse): use get_pname()
+       instead of argv[0].
+
+2000-12-31  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amflush.c (main):log DISK after checking if logfile exist.
+
+2000-12-30 John R. Jackson <jrj@purdue.edu>
+
+       * common-src/bsd-security.c: Improve the .rhosts/.amandahosts messages
+         when things go wrong.  Add support for "bsdsecurity" test program
+         in common-src.
+       * common-src/Makefile.am: Ditto.
+       * common-src/amanda.h: Ditto.
+       * restore-src/amidxtaped.c: Ditto.
+       * server-src/amindexd.c: Ditto.
+
+2000-12-30 John R. Jackson <jrj@purdue.edu>
+
+       * ChangeLog: Bring Jean-Louis into the right month :-).
+       * changer-src/scsi-changer-driver.c: Untested changes to at least
+         get the code to compile on Solaris and to remove some warnings.
+       * changer-src/scsi-defs.h: Ditto.
+       * changer-src/scsi-solaris.c: Ditto.
+
+2000-12-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/diskfile.c (add_disk): New function.
+       * server-src/diskfile.h (add_disk): Prototype.
+       * server-src/logfile.h (logtype_e): add L_DISK.
+       * server-src/logfile.c (logtype_str): add "DISK".
+       * server-src/amflush.c (main): log DISK.
+       * server-src/planner.c (main): log DISK.
+       * server-src/reporter.c: use DISK if available.
+
+2000-12-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amcheck.c: New [host disk]* pair arguments.
+       * server-src/amflush.c: Ditto.
+       * server-src/planner.c: Ditto.
+       * server-src/amdump.sh.in: Ditto.
+       * server-src/amrestore.c: Use new host/disk matcher.
+       * man/amcheck.8.in: Document new [host disk]* pair arguments.
+       * man/amflush.8.in: Ditto.
+       * man/amdump.8.in: Ditto.
+
+2000-12-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/diskfile.c (match_disklist): new function.
+       * server-src/diskfile.h (struct disk_s): new field todo.
+       * server-src/diskfile.h (match_disklist): prototype.
+
+2000-12-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/match.c (match_word, match_host, match_disk): 
+       new functions.
+       * common-src/amanda.h (match_host, match_disk): prototype.
+
 2000-12-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/planner.c (analyze_estimate): pick incremental level
-       if no estimate of level 0.
+        if no estimate of level 0.
+
+2000-12-28 Marc W. Mengel <mengel@fnal.gov>
+       * changer-src/chg-juke.sh.in: New File
+       * changer-src/Makefile.am: Added support for chg-juke.
+       * docs/TAPE.CHANGERS: Likewise.
+       * configure.in: Likewise.
 
 2000-12-24 John R. Jackson <jrj@purdue.edu>
 
         * man/amcheck.8.in: Add mention of tapelist directory and do
          some other directory writable cleanup.
 
-2000-12-13 John R. Jackson <jrj@purdue.edu>
-
-       * docs/Makefile.am: Removing entries for missing RAIT/VTAPE-API files.
-
-2000-12-13 John R. Jackson <jrj@purdue.edu>
-
-       * tape-src/tapeio.c: De-commit the RAIT feature from 2.4.2.  It will
-         be in 2.5 and 2.4.2-multitape.
-       * tape-src/tapeio.h: Ditto.
-       * tape-src/Makefile.am: Ditto.
-
 2000-12-12 John R. Jackson <jrj@purdue.edu>
 
        * client-src/sendbackup-gnutar.c: Fix regex pattern to accept blanks
          or tabs.
 
-2000-12-12 John R. Jackson  <jrj@purdue.edu> and Marc Mengel <mengel@fnal.gov>
+2000-12-12 John R. Jackson <jrj@purdue.edu>
 
        * Makefile.am: Work around problem with automake 1.4 not including
          pkgdata_DATA.
-       * docs/RAIT: New file.
-       * docs/VTAPE-API: New file.
        * docs/Makefile.am: Include RAIT and VTAPE-API in distribution.
          Work around problem with automake 1.4 not including pkgdata_DATA.
-       * tape-src/output-rait.h: New File providing RAIT virtual tape type.
-       * tape-src/output-rait.c: New File providing RAIT virtual tape type.
-       * tape-src/Makefile.am: Add output-rait.c.
+       * tape-src/rait.h: Renamed to rait.h.
+       * tape-src/rait.c: Renamed to rait.c.
+       * tape-src/output-rait.h: Renamed from rait.h.
+       * tape-src/output-rait.c: Renamed from rait.c.
+       * tape-src/Makefile.am: Reflect the new rait.[ch] names.
+       * tape-src/tapeio.c: Use output-rait.h name.  Minor typo changes.
+
+2000-12-08 Marc Mengel <mengel@fnal.gov>
+
+       * docs/RAIT: New file.
+       * docs/VTAPE-API: New file.
+       * tape-src/rait.c: New File providing RAIT virtual tape type.
        * tape-src/tapeio.c: Major Surgery.
          (vtable): New static table of virtual tape types.
          (fdtable): New static table mapping file descriptors.
          (plain_tapefd_status): Likewise.
          (plain_tapefd_weof): Likewise.
 
-2000-12-07 Thomas Hepper <th@ant.han.de>
-
-       changer-src/scsi-changer-driver.c: Added Exabyte 230D Sense Handler
-       (patch from Gary Algier gaa@ulticom.com)
-       Fixed some compile warnings (-Wshadow)
-       changer-src/scsi-solaris.c: Changed the return Value from 
-       SCSI_ExecuteCommand to the value of Command.uscsi_status if
-       the return value of the ioctl is > 0
-
 2000-12-04 John R. Jackson  <jrj@purdue.edu>
 
-       server-src/amdump.sh.in: Temporary fix for $LOGNAME vs whoami problem.
-
-2000-12-04 John R. Jackson  <jrj@purdue.edu>
-
-       * common-src/security.c: Make the "./security" test code available
-         for normal operation by #define so it can be seen in, e.g., the
-         */amandad*debug file.
+       * server-src/amdump.sh.in: Temporary fix for $LOGNAME vs whoami
+         problem.
 
 2000-12-04 John R. Jackson  <jrj@purdue.edu>
 
        * man/amrestore.8: Document the new option, the compression level,
          and clean up some nroff issues.
 
-2000-11-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2000-11-30 Marc Mengel <mengel@fnal.gov>
+
+       * changer-src/chg-chio.pl.in: Use am-mt and am-dd versus mt and dd.
+       * changer-src/chg-chs.sh.in: Likewise.
+       * changer-src/chg-manual.sh.in: Likewise.
+       * changer-src/chg-mtx.sh.in: Likewise.
+       * changer-src/chg-multi.sh.in: Likewise.
+       * changer-src/chg-rth.pl.in: Likewise.
+       * changer-src/chg-zd-mtx.sh.in:  Likewise.
+       * tape-src/am-dd.c: New file. Replacement for dd.
+       * tape-src/am-mt.c: New file. replacement for mt.
+       * tape-src/Makefile.am: Add build for am-mt and am-dd.
+       * tape-src/tapeio.c (tape_unload, tapefd_unload, tape_status, 
+         tapefd_status): New functions.
+          (tape_rewind, tape_fsf, tape_rdlabel): Change error message 
+               for tape being offline so it matches online/offline regex 
+               in changer scripts.
+         (tape_open): Ifdef-out mode flag clearing, so you can pass 
+               O_TRUNC, etc.  in for am-dd.
+
+2000-11-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/util.c: #include "../tape-src/tapeio.h"
+       * tape-src/tapeio.c(tapefd_write): second arg is const.
+       * tape-src/tapeio.h(tapefd_write): Likewise.
+       * common-src/event.c(event_loop): declare entry if ASSERT is defined.
+       * changer-src/chg-scsi.c: Fix compiler warning.
+       * changer-src/scsi-aix.c: Likewise.
+       * changer-src/scsi-bsd.c: Likewise.
+       * changer-src/scsi-cam.c: Likewise.
+       * changer-src/scsi-changer-driver.c: Likewise.
+       * changer-src/scsi-defs.h: Likewise.
+       * changer-src/scsi-hpux.c: Likewise.
+       * changer-src/scsi-hpux_new.c: Likewise.
+       * changer-src/scsi-irix.c: Likewise.
+       * changer-src/scsi-linux.c: Likewise.
+       * changer-src/scsi-solaris.c: Likewise.
+       * changer-src/sense.c: Likewise.
 
-       * Amanda 2.4.2 released
-       
 2000-11-22 John R. Jackson  <jrj@purdue.edu>
 
        * contrib/dbbackup.ksh: Deal with adm being a symlink.
        * server-src/amverify.sh.in: use common form for getting the first
        line of a file/pipe.  Sed is more portable than head.
 
-2000-11-01 John R. Jackson  <jrj@purdue.edu>
-
-       * common-src/security.c (bsd_security_ok): Same fix for amwait_t !=
-       int as applied a while back to changer.c.  Compliments of John E.
-       Hein <jhein@timing.com>.
-
 2000-10-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * client-src/selfcheck.c (check_disk): Write an appropriate
 
 2000-10-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/driver.c (continue_dumps): set estimate to more than
+       * server-src/driver.c (handle_chunker_result): The dumpsize is
+       the third argument, not the fourth.
+
+2000-10-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/driver.c (handle_chunker_result): don't check
+       pending_aborts, call event_release() ob ABORT-FINISHED.
+
+2000-10-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/chunker.c (databuf_flush): workaround to prevent a
+       hang on a ABORT command.
+
+2000-10-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/driver.c (continue_dumps): set estimate to more than 
        what is already use instead of setting no_hold=1 when a disk
        don't fit on holding disk.
 
+2000-10-29  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/chunker.c: chunker was broken after RQ-MORE-DISK.
+
 2000-10-28  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amstatus.pl.in: add '&' when calling &usage()
+       * server-src/amstatus.pl.in: add '&' when calling &usage() 
        or &dump_size().
 
 2000-10-28  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 2000-10-28  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        reported by The Hermit Hacker <scrappy@hub.org>
 
-       * changer-src/chg-chio.pl.in: remove comma after LOG,
+       * changer-src/chg-chio.pl.in: remove comma after LOG, 
        typo: r should be 0.
 
 2000-10-25  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * docs/INDEXING: doc updated.
 
-2000-10-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * changer-src/scsi-defs.h: prototype SCSI_Inquiry, PrintInquiry, 
-       DecodeSCSI, ChangerReplay, BarCode and MapBarCode.
-       * changer-src/scsi-linux.c: fix compiler warning.
-       * changer-src/scsi-changer-driver.c: fix compiler warning.
-
-2000-10-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * changer-src/chg-scsi.c: remove rcsid.
-       * changer-src/scsi-aix.c: remove rcsid, add amanda Copyright.
-       * changer-src/scsi-bsd.c: remove rcsid, add amanda Copyright.
-       * changer-src/scsi-changer-driver.c: remove rcsid, add amanda Copyright.
-       * changer-src/scsi-defs.h: add amanda Copyright.
-       * changer-src/scsi-hpux.c: remove rcsid.
-       * changer-src/scsi-hpux_new.c: remove rcsid, add amanda Copyright.
-       * changer-src/scsi-irix.c: remove rcsid, add amanda Copyright.
-       * changer-src/scsi-linux.c: remove rcsid, add amanda Copyright.
-       * changer-src/scsi-solaris.c: remove rcsid, add amanda Copyright.
-
 2000-10-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * AUTHORS: add Thomas Hepper.
 
-2000-10-14  Thomas Hepper <th@ant.han.de>
+2000-10-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * changer-src/scsi-changer-driver.c: Added support for the TreeFrog
-       library (barcode support), fixed some signal 11 problems in the
-       output of chg-scsi -status
-       Removed unused variables
-       * changer-src/chg-scsi.c: same
-       * changer-src/scsi-defs.h: same
+       * server-src/driverio.c (chunker_cmd): send ABORT command.
 
 2000-10-13  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
 2000-10-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * NEWS: A new `ctimeout' keyword in amanda.conf to replace
+       * NEWS: A new `ctimeout' keyword in amanda.conf to replace 
        the CHECK_TIMEOUT constant in amcheck.c.
 
 2000-10-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amlabel.c: Don't set tape_ok to 0 if
+       * server-src/amlabel.c: Don't set tape_ok to 0 if 
        tape_wrlabel is successful.
 
 2000-10-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/taper.c: amfree(strclosing).
 
+2000-10-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/driver.c: typo.
+
 2000-10-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * configure.in: --with-samba-user is deprecated.
        * client-src/sendsize.c (getsize_smbtar): ditto.
        * client-src/sendbackup-gnutar.c (start_backup): ditto.
        * recover-src/extract_list.c (extract_files_child): ditto.
-       
-2000-10-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/dumper.c (write_tapeheader): set errno = ENOSPC
-       and return -1 if is not fully written.
 
 2000-10-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/taper.c: give better message when failing
+       * server-src/taper.c: give better message when failing 
        to open a chunk.
 
 2000-10-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * server-src/diskfile.c (headqueue_disk): new function to
        insert at the head of the queue.
        * server-src/diskfile.h (headqueue_disk): prototype.
-       * server-src/driver.c (handle_taper_result,dump_to_tape):
-       insert with headqueue_disk() after a TRY-AGAIN.
-
-2000-10-10  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/dumper.c (do_dump): wait for index compress
-       process to terminate before renaming the index file.
+       * server-src/driver.c (taper_queuedisk): insert with
+       headqueue_disk() if disk already attempted.
 
 2000-10-09  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
        * man/amanda.8.in: add all pages in the SEE ALSO section.
 
-2000-09-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * client-src/sendbackup.c: set estr=NULL if the exclude
-       file doesn't exist.
-
-2000-09-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * client-src/sendbackup-gnutar.c: use exclude string estr 
-       instead of "estr".
-
 2000-09-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * man/amreport.8.in: amreport does not rotate the log.
        -config is no longer needed for ccompatibility with other program.
        * man/amoverview.8.in: -config is no longer needed.
 
-2000-09-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/amadmin.c (usage): show disklist command.
-
 2000-09-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * example/amanda.conf.in: chunk should not be larger than
 
 2000-09-24  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * client-src/sendsize.c (getsize_smbtar): remove unused debug_level 
+       * client-src/sendsize.c (getsize_smbtar): remove unused debug_level
        variable.
        * server-src/amlabel.c (main): init errstr to NULL, 
        fix compiler warning.
 
        * server-src/reporter.c (output_tapeinfo): test reversed for run_tapes.
 
-2000-08-01  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
-
-       * client-src/sendbackup-gnutar.c (start_backup) <taropt>:
-       NULL-terminate it correctly.
-
+2000-07-31 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c: Rework of the device handling.
+       Every device is opend for an operation and than closed.
+       This will hopefully fix the problems with openening the tape device
+       and the SCSI control device for the tape
+       new option emubarcode (see docs/TAPE.CHANGERS)
+       * changer-src/scsi-cam.c: Changed to work with the new device handling.
+       * changer-src/scsi-hpux_new.c: Changed to work with the new device handling.
+       * changer-src/scsi-irix.c: Changed to work with the new device handling. (Not tested)
+       * changer-src/scsi-solaris.c: Changed to work with the new device handling. (Not tested)
+       * changer-src/scsi-linux.c: Changed to work with the new device handling.
+       * changer-src/scsi-changer-driver.c: Changed to work with the new device handling
+       * changer-src/scsi-defs.h: Changed to work with the new device handling
 2000-07-18 John R. Jackson  <jrj@purdue.edu>
 
        * changer-src/chg-chio.pl.in (do_time): fix chg-chio.pl timestamp
        memory areas on an error condition.  Found by Patrik Andersin
        <cat@iki.fi>.
 
-2000-07-17  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * client-src/sendsize.c (getsize_dump,getsize_gnutar): set 
-       dumppid to the return value of pipespawn.
-
-2000-06-27  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * client-src/sendbackup.c (parse_options): set efile.
-
-2000-06-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+2000-07-17 Thomas Hepper <th@ant.han.de>
+       * docs/TAPE.CHANGERS: Added some notes for the cam driver
+       * changer-src/scsi-cam.c: New syntax for telling scsi ids
+       (bus:target:lun)
+       SCSI_ExecuteCommand now returns the correct sense buffer.
+
+2000-07-17 Thomas Hepper <th@ant.han.de>
+       * configure.in: Added check for BSD SCSI CAM Support
+       * changer-src/scsi-cam.c: New, functions for SCSI CAM Support
+       ( at the moment for FreeBSD 4.0)
+       * changer-src/Makefile.am: added scsi-cam.s to the list of sources
+       * changer-src/chg-scsi.c: The structs for the OpenFiles_T is now
+       allocated in chg-scsi and passed to OpenDevice.
+       * changer-src/scsi-changer-driver.c: New Parameter for OpenDevice
+       (OpenFiles_T)
+
+2000-07-10 Marc Mengel <mengel@fnal.gov>
+       * tape-src/tapeio.c -- add tape_{stat,access}, allow "plain:" prefix
+               on tape device names
+       * tape-src/tapeio.h -- add tape_{stat,access} prototypes
+       * common-src/util.c -- call tape_{read,write}() in full{read,write}()
+       * restore-src/amidxtaped.c -- use tape_stat() on tapename
+       * restore-src/amrestore.c -- use tape_stat() on tapename
+       * server-src/amcheck.c -- use tape_access() on tapename
+       * client-src/Makefile.am -- now needs libamtape.a twice
+       * server-src/Makefile.am -- now needs libamtape.a twice
+       * recover-src/Makefile.am -- now needs libamtape.a twice
+       * Makefile.am -- tape-src before client-src
+
+2000-07-05 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi.c: fixed an core dump if tapeident was set
+       * changer-src/scsi-changer-driver.c (OpenFile):
+        if the ident ist set in the config set this in the internal device 
+        struct too.
+       * changer-src/scsi-changer-driver.c (GenerciSenseHandler):
+        changed the type for the info text from char * to char ** which
+        is passwd to Sense2Action
+       * changer-src/scsi-changer-driver.c (ChangerStatus):
+        fixed the bug which causes an core dump for chg-scsi -status robot
+        if an bar code reader is detected. Fixed also the bug that the
+        mapping Label -> Barcode was not displayed.
+       * changer-src/scsi-defs.h: Changed the prototype for Sense2Action
+       * changer-src/sense.c: Added the defs for the Spectra TreeFrog lib
+       * changer-src/sense.c (Sense2Action); Fixed the handling if no match
+        was found (fall back to the generic description)
+
+2000-06-26 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/list_dir.c (add_dir_list_item): add at head of list.
 
+2000-06-24 Thomas Hepper <th@ant.han.de>
+       * changer-src/chg-scsi-chio.c: Merged changes from 2.4.2 
+       * changer-src/chg-scsi.c: Merged changes from 2.4.2
+       * changer-src/sense.c: New file. Contains an table and function for the 
+          mapping of sense/ASC/ASCQ conditions from the SCSI sense.
+       * changer-src/scsi-changer-driver.c: Merged changes from 2.4.2
+         Changed handling for the sense keys. Now there is only one function
+          to decide what to do with an sense/ASC/ASCQ conditon (abort,retry ..)
+       * changer-src/Makefile.am: Added sense.c to the source list.
+       * changer-src/scsi-solaris.c: Merged changes from 2.4.2 
+       * changer-src/scsi-linux.c: Merged changes from 2.4.2 
+       * changer-src/scsi-irix.c: Merged changes from 2.4.2 
+       * changer-src/scsi-hpux_new.c: Merged changes from 2.4.2 
+       * changer-src/scsi-defs.h: Merged changes from 2.4.2 
+       
 2000-06-12  Jeroen Ruigrok van der Werven  <asmodai@wxs.nl>
 
        * server-src/amlabel.c (main): Do not amfree(config_name).
 
-2000-06-03 Thomas Hepper <th@ant.han.de>
-
-       * changer-src/scsi-defs.h: Add missing defines which are used by the
-       sense handler
-       * changer-src/scsi-solaris.c: Added patch to limit the recursion
-       in Scsi_ExecuteCommand.
-
 2000-06-02 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/holding.c (pick_datestamp): convert ch to upper.
 
+2000-05-29 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/driver.c (handle_dumper_result, handle_chunker_result):
+         delay call to dumper_result().
+
 2000-05-28  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * client-src/sendbackup-gnutar.c: Ignore `socket ignored' GNU tar
        messages.
 
-2000-05-27 Ian Turner <vectro@pipeline.com>
-       * client-src/sendbackup.c (pipespawn): Moved to...
-       * common-src/pipespawn.c: ... new file.  Redirect all std
-       streams.  Support skipping arguments.
-       * common-src/pipespawn.h (pipespawn, skip_argument): Declare.
-       * common-src/Makefile.am (noinst_HEADERS): Added pipespawn.h.
-       (libamanda_la_SOURCES): Added pipespawn.c.
-       * client-src/sendbackup-dump.c, client-src/sendbackup-gnutar.c:
-       Adjust.
+2000-05-27 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * chunker.c: allow chunk to be written on different holding disk.
+       * server-src/driver.c: allow chunk to be written on different
+         holding disk.
+       * server-src/conffile.c: make sure that disksize and chunksize
+         are multiple of TAPE_BLOCK_SIZE.
+       * server-src/conffile.h: disksize and chunksize are long.
+       * server-src/diskfile.c (find_disk): new function to see if a
+         given disk is contained in a list structure.
+       * server-src/diskfile.h (find_disk): prototype.
+       * server-src/driverio.h (RQ_MORE_DISK): Added message.
+       * server-src/driverio.h (free_assignedhd): prototype.
+       * server-src/driverio.h (assignedhd_t): new data structure.
+       * server-src/driverio.c (cmdstr): added comamnd RQ-MORE-DISK.
+       * server-src/driverio.c (free_assignedhd): new function to free an
+         array of assignedhd_t.
+       
+2000-05-03 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/driver.c (chunker_program): new variable.
 
 2000-04-20 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amstatus.pl.in: typo
+       * server-src/amstatus.pl.in: handle chunker line.
 
 2000-04-20  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * recover-src/Makefile.am (LDADD): Removed libamtape.
        Reported by Paul Yeatman <pyeatman@ucsd.edu>
 
+2000-04-17 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/chunker.c: new file for the chunker program.
+       * server-src/Makefile.am: compile it.
+       * server-src/driver.c: many modification.
+       * server-src/driverio.c: many modification.
+       * server-src/driverio.c (startup_chunk_process, chunker_cmd):
+       new functions.
+       * server-src/driverio.h: prototype them.
+       * server-src/driverio.h (struct chunker_s): new structure.
+       * server-src/logfile.c: handle chunker log.
+       * server-src/logfile.h: ditto.
+       * server-src/reporter.c: ditto.
+       * server-src/taper.c: size reduced by TAPE_BLOCK_SIZE.
+
 2000-04-16 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/taper.c: don't crash if the tapelist file
        should have been `InfoFile'.
 
 2000-04-09  Davide Marchignoli  <marchign@di.unipi.it>
-
+  
        * server-src/conffile.h (confparm_t): Added CTIMEOUT.
        * server-src/conffile.c: Added ctimeout support.  Default to 30.
        * example/amanda.conf.in: Likewise.
 2000-04-09  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * server-src/amlabel.c (main): Check label *after* writing end mark.
-       
+
 2000-03-06 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amlabel.c: don't crash if the tapelist file
+       * server-src/amlabel.c: don't crash if the tapelist file 
        doesn't exist.
 
 2000-02-12 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amstatus.pl.in: "0 dumpers busy" should be "0 dumper busy".
 
-2000-02-08 Thomas Hepper <th@ant.han.de>
-
-       * changer-src/scsi-linux.c (SCSI_ExecuteCommand) : Direction for the 
-       memcpy for the sense result was wrong, so every time the sense result
-       was 0x0.....
-
-       * changer-src/scsi-changer-driver.c (GenericElementStatus) : Added
-       flag to signal if it is either a tape drive or a library. 
-
 2000-01-31 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amadmin.c (force_one, force_bump_one): FORCE_FULL
        and FORCE_BUMP are mutually exclusive.
 
-2000-01-30  Thomas Hepper <th@ant.han.de>
+2000-01-31 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * changer-src/chg-scsi.c : Exit it tapedev in amanda.conf is not a 
-       number. 
+       * server-src/driver.c (main): use the holding disk even if the
+       datestamped directory already exist.
 
 2000-01-21  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * recover-src/amrecover.c (tape_device_name): Default to
        server-determined default.
 
-2000-01-17  Thomas Hepper <th@ant.han.de>
-       * changer-src/scsi-changer-driver.c : Typo in CheckMove fixed .
-
-2000-01-17  Thomas Hepper <th@ant.han.de>
-
-       * configure.in: check for scsi/sg.h on linux, and if true
-       enable sg support
-
-       * changer-src/chg-scsi.c : New option -trace for debuging...
-       new option changer_ident to set the internal driver for the changer
-
-       * hanger-src/scsi-hpux_new.c: New function Tape_Status.
-       returns the status of the tape. (loaded/empty etc)
-       * changer-src/scsi-aix.c : Dummy function for Tape_Status
-       * changer-src/scsi-bsd.c : Dummy function for Tape_Status
-       * changer-src/scsi-irix.c : Dummy function for Tape_Status
-       * changer-src/scsi-solaris.c : Dummy function for Tape_Status
-       * changer-src/scsi-linux.c : Added better support for the sg driver.
-       * changer-src/scsi-changer-driver.c : New driver for ADIC SDX and DLT448
-       librarys
-       new function SDXMove for SDX library
-       new function CheckMove to check if a move is legal based on the infs
-       we get from the Mode Sense command
-       * changer-src/scsi-defs.h : Added types returned by Tape_Status
-
-2000-01-16  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
-
-       * server-src/driver.c (handle_dumper_result): When failed, set
-       dp->inprogress to 0, not 1.
-
 2000-01-13  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * configure.in: Recognize alpha*-*-linux-* and sparc*-*-linux-*.
 2000-01-06  David Wolfskill  <dhw@whistle.com>
 
        * docs/TAPETYPES: Typo.
-
+       
 2000-01-06  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * docs/TAPETYPES: Removed all tapetype entries.  Pointed to
 
        * client-src/sendbackup-gnutar.c (re_table): Update for Samba 2.0.6.
 
+1999-11-25 John R. Jackson  <jrj@purdue.edu>
+
+       * server-src/amflush.c (main): conf_logdir should not be free'd
+         (found by Espen H Wiborg <espenhw@infotek.no>).
+
 1999-11-10 John R. Jackson  <jrj@purdue.edu>
 
        * recover-src/extract_list.c: report the tape server host in the
        * server-src/amcheck.c (start_server_check): test tapedev for
          "/dev/null" and issue warning that dumps will be thrown away.
 
+1999-11-02  David M. Olsen  <David.M.Olsen@boeing.com>
+
+       * server-src/amadmin.c (main): Second occurrence of CNF_TAPELIST
+       should have been CNF_INFOFILE; fixed.
+
 1999-11-02  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * common-src/amflock.c (struct flock): Do not assume the fields are
        * contrib/set_prod_link.pl: Create the links for a configuration
        with --with-suffix.
 
-1999-11-02  Nicolas Mayencourt  <Nicolas.Mayencourt@cui.unige.ch>
+1999-11-02  David M. Olsen  <David.M.Olsen@boeing.com>
 
-       * server-src/amtoc.pl.in: Correct a bug for total report.
+       * common-src/rsh-security.c (net_writev): The result of a cast is
+       not an lvalue; fixed.
 
-1999-11-01 John R. Jackson  <jrj@purdue.edu>
+1999-10-26  Nicolas Mayencourt  <Nicolas.Mayencourt@cui.unige.ch>
 
-       * server-src/driver.c (find_diskspace): make noisy holding space log
-         message conditional on HOLD_DEBUG.
+       * server-src/amtoc.pl.in: Correct a bug for total report.
 
 1999-11-01 John R. Jackson  <jrj@purdue.edu>
 
 
 1999-10-02 John R. Jackson  <jrj@purdue.edu>
 
-       * server-src/driver.c: delete #define of HOLD_DEBUG, it was increasing
-         the size of the amdump log file by a factor of 10 or more.  Anyone
-         who needs it can define it in CFLAGS or some other way.
+       * server-src/amlogroll.c: fix minor memory leak.
 
 1999-09-29 John R. Jackson  <jrj@purdue.edu>
 
        * configure.in: wrong variable when processing LIBRARY_DIRS.  Fix
          compliments of John M. Vogtle <jmvogtle@kodak.com>.
 
+1999-09-20 John R. Jackson  <jrj@purdue.edu>
+
+       * server-src/Makefile.am: use new amlogroll utility to rename the log
+         file to the datestamped name.
+       * server-src/amcheck.c: ditto.
+       * server-src/amcleanup.sh.in: ditto and call all utilities with the
+         config file name as an argument.
+       * server-src/amdump.sh.in: ditto and call all utilities with the
+         config file name as an argument.
+       * server-src/amflush.c: ditto.
+       * server-src/amlogroll.c: new utility.
+       * server-src/driverio.c: ditto and call all utilities with the
+         config file name as an argument.
+       * server-src/reporter.c: ditto.
+
+1999-09-20  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
+
+       * amlogroll.c: It was missing; copied from the 2.4.2 branch.
+
+       * configure.in (AMANDA_TMPDIR): Added comment for config.h.in.
+
 1999-09-19 John R. Jackson  <jrj@purdue.edu>
 
        * server-src/amverify.sh.in: this script is important enough it should
        * server-src/amstatus.pl.in: generalize the "driver: state" parsing
          so it can handle current and future information.
 
-1999-09-15  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server/driver.c (main): use the holding disk even if the
-       datestamped directory already exist.
-
-1999-09-14  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
-
-       * configure.in: Get snapshot date from SNAPSHOT file, if it exists.
-       (VERSION): Add the date to it.
-       (SNAPSHOT_STAMP): AC_SUBST to the SNAPSHOT file, if it exists.
-       * Makefile.am (EXTRA_DIST): Added $(SNAPSHOT_STAMP).
-       (config.status): Depend on $(SNAPSHOT_STAMP).
-       (SNAPSHOT): Dummy rule to allow reconfigure if it's removed.
-
-       * config/Makefile.am: Remove all traces of acconfig.h.
-
-       * server-src/changer.c (changer_command): Fix for amwait_t != int.
-
-1999-09-13  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
-
-       * config/acinclude.m4i: Added comments for config/config.h.in to all
-       AC_DEFINEs.
-       * configure.in: Likewise.
-       * config/acconfig.h: Deleted.
-       * autogen: Updated.
-
-1999-09-13 John R. Jackson  <jrj@purdue.edu>
-
-       * server-src/amverify.sh.in: protect against uname not returning
-         anything.
-
-1999-09-12  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/amcheck.c (start_server_check): use tapefile instead of
-       conf_tapelist to open the file (we no longer cd to the config file).
-
-1999-09-11 John R. Jackson  <jrj@purdue.edu>
-
-       * server-src/reporter.c: sigh -- it was right the first time.
-
-1999-09-11 John R. Jackson  <jrj@purdue.edu>
-
-       * server-src/reporter.c: lost a few too many lines with the amlogroll
-         changes to amreport.
-
-1999-09-11 John R. Jackson  <jrj@purdue.edu>
-
-       * server-src/amindex.c: minor memory leak.
-
-1999-09-11 John R. Jackson  <jrj@purdue.edu>
-
-       * server-src/amcheck.c: remove duplicated code.
-
-1999-09-11 John R. Jackson  <jrj@purdue.edu>
-
-       * server-src/Makefile.am: use new amlogroll utility to rename the log
-         file to the datestamped name.
-       * server-src/amcheck.c: ditto.
-       * server-src/amcleanup.sh.in: ditto and call all utilities with the
-         config file name as an argument.
-       * server-src/amdump.sh.in: ditto and call all utilities with the
-         config file name as an argument.
-       * server-src/amflush.c: ditto.
-       * server-src/amlogroll.c: new utility.
-       * server-src/driverio.c: ditto and call all utilities with the
-         config file name as an argument.
-       * server-src/reporter.c: ditto.
-
-1999-09-10 John R. Jackson  <jrj@purdue.edu>
-
-       * client-src/rundump.c: minor compiler warnings.
-       * common-src/security.c: minor compiler warnings.
-       * server-src/amindexd.c: minor compiler warnings.
-       * server-src/conffile.c: minor compiler warnings.
-
-1999-09-10 John R. Jackson  <jrj@purdue.edu>
-
-       * client-src/sendsize.c: typo in previous patch and pick a better
-         variable name (ala other similar code).
-
-1999-09-10 John R. Jackson  <jrj@purdue.edu>
+1999-09-15 John R. Jackson  <jrj@purdue.edu>
 
-       * client-src/amandad.c: clean up error messages after a fork or exec*
-         failure.
-       * client-src/rundump.c: ditto.
-       * client-src/runtar.c: ditto.
-       * client-src/sendbackup.c: ditto.
-       * client-src/sendsize.c: ditto.
-       * restore-src/amidxtaped.c: ditto.
-       * server-src/amflush.c: ditto.
+       * common-src/bsd-security.c: if the user field is not present in the
+         .amandahosts file, it should default to the local user, not the
+         remote user.  For our purposes, that is CLIENT_USER, not the user
+         we are running as (although they should be the same).
 
-1999-09-07 John R. Jackson  <jrj@purdue.edu>
+1999-09-14 John R. Jackson  <jrj@purdue.edu>
 
        * configure.in: Add --with-tmpdir to ./configure and use it for
          all Amanda temporary files.  Default --with-dbgdir to --with-tmpdir.
        * common-src/alloc.c: ditto.
        * common-src/amanda.h: ditto.
        * common-src/amflock.c: ditto.
+       * common-src/bsd-security.c: ditto.
        * common-src/debug.c: ditto.
        * common-src/file.c: ditto.
        * common-src/genversion.c: ditto.
-       * common-src/security.c: ditto.
-       * config/acconfig.h: ditto.
-       * dumper-src/gnutar.pl.in: ditto.
        * restore-src/amidxtaped.c: ditto.
        * server-src/Makefile.am: ditto.
        * server-src/amadmin.c: ditto.
        * server-src/amverify.sh.in: ditto.
        * server-src/changer.c: ditto.
        * server-src/changer.h: ditto.
+       * server-src/conffile.c: ditto.
        * server-src/conffile.h: ditto.
        * server-src/diskfile.c: ditto.
        * server-src/driver.c: ditto.
        * server-src/tapefile.c: ditto.
        * server-src/taper.c: ditto.
 
-1999-09-05 John R. Jackson  <jrj@purdue.edu>
+1999-09-14  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
+
+       * common-src/bsd-security.c (bsd_stream): fn should take an ssize_t.
+       (bsd_stream_read): Likewise, declaration.
+       * common-src/rsh-security.c (rsh_stream): Likewise.
+       (rsh_stream_read): Likewise, declaration and definition.
+       * common-src/krb4-security.c (dummy): Compile when disabled.
+       * common-src/krb5-security.c (dummy): Likewise.
 
-       * common-src/Makefile.am: change OBJ_EXTENSION to OBJEXT in line
-         related to the "security" test tool.
+       * server-src/reporter.c (sDivZero): Change from float to double, to
+       build with DEC cc.
+
+       * configure.in: Get snapshot date from SNAPSHOT file, if it exists.
+       (VERSION): Add the date to it.
+       (SNAPSHOT_STAMP): AC_SUBST to the SNAPSHOT file, if it exists.
+       * Makefile.am (EXTRA_DIST): Added $(SNAPSHOT_STAMP).
+       (config.status): Depend on $(SNAPSHOT_STAMP).
+       (SNAPSHOT): Dummy rule to allow reconfigure if it's removed.
+
+       * config/Makefile.am: Remove all traces of acconfig.h.
+
+       * server-src/changer.c (changer_command): Fix for amwait_t != int.
+
+1999-09-13  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
+
+       * config/acinclude.m4i: Added comments for config/config.h.in to all
+       AC_DEFINEs.
+       * configure.in: Likewise.
+       * config/acconfig.h: Deleted.
+       * autogen: Updated.
 
 1999-09-05 John R. Jackson  <jrj@purdue.edu>
 
        * changer-src/chg-chio.pl.in: add -w to #! line to catch more errors.
-       * client-src/amandad.c: fix some compiler warnings.
-       * common-src/protocol.c: fix some compiler warnings.
        * recover-src/display_commands.c: fix some compiler warnings.
        * recover-src/extract_list.c: fix some compiler warnings.
        * restore-src/amrestore.c: fix some compiler warnings.
-       * server-src/conffile.c: fix some compiler warnings.
-       * server-src/diskfile.c: fix some compiler warnings.
-       * server-src/holding.c: fix some compiler warnings.
        * server-src/planner.c: fix some compiler warnings.
 
 1999-09-05 John R. Jackson  <jrj@purdue.edu>
 
        * common-src/stream.c: make sure errno is returned properly from
          stream_client() and stream_server().
-       * client-src/sendbackup.c: report errors from stream_server() and
+       * server-src/taper.c: report errors from stream_server() and
          abort.
-       * server-src/taper.c: ditto.
        * recover-src/extract_list.c: make sure errno is preserved.
 
-1999-09-05 John R. Jackson  <jrj@purdue.edu>
-
-       * client-src/amandad.c: clean up a couple of debugging messages.
-
-1999-09-05 John R. Jackson  <jrj@purdue.edu>
-
-       * recover-src/amrecover.c: add missing ntohs calls.  Reported by
-         Kent Kalnasy <kkalnasy@ms.washington.edu>
-       * recover-src/extract_list.c: ditto.
-
 1999-09-05 John R. Jackson  <jrj@purdue.edu>
 
        * configure.in: make sure the dump and restore programs are defined
        (get_dumptype): Use read_dumptype.
        (main): Read disklist, so that custom dumptypes are shown.
        * server-src/conffile.h (read_dumptype): Declare.
-       * server-src/diskfile.c (read_diskline): Use read_dumptype if
-       dumptype starts with `{'.
+       * server-src/diskfile.c (parse_diskline): Get line_num and line by
+       reference.  New argument diskf.  Use read_dumptype if dumptype
+       starts with `{'.
+       (main): Update.
        * man/amanda.8.in (disklist): Document it.
        * NEWS: Likewise.
        * example/disklist: Exemplify it.
 
 1999-08-23 John R. Jackson  <jrj@purdue.edu>
 
-       * server-src/reporter.c (copy_template_file): make sure all data is
-         written to label template pipeline.
+       * recover-src/amrecover.c (main): fix test for IPPORT_RESERVED.
+       * recover-src/extract_list.c (extract_files_setup): ditto.
 
-1999-08-21  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-       Patch by Peter Conrad <conrad@opus5.de>
+1999-08-23 John R. Jackson  <jrj@purdue.edu>
 
-       * docs/INTERNALS: documented splitting of dumps across multiple
-         holding disks.
-       * server-src/conffile.c: make sure that disksize and chunksize
-         are multiple of TAPE_BLOCK_SIZE.
-       * server-src/diskfile.c (find_disk): new function to see if a
-         given disk is contained in a list structure.
-       * server-src/diskfile.h (find_disk): prototype.
-       * server-src/driverio.h (RQ_MORE_DISK): Added message.
-       * server-src/driverio.h (free_assignedhd): prototype.
-       * server-src/driverio.h (assignedhd_t): new data structure.
-       * server-src/driverio.c (cmdstr): added comamnd RQ-MORE-DISK.
-       * server-src/driverio.c (dumper_cmd): Modified format of CONTINUE
-       * server-src/driverio.c (free_assignedhd): new function to free an
-         array of assignedhd_t.
-       * server-src/driver.c (roomq): new queue to replace stoppedq.
-       * server-src/driver.c (find_diskspace, assign_holdingdisk, 
-         adjust_diskspace, delete_diskspace): rewrite.
-       * server-src/driver.c (continue_dumps): new function to determine
-         which dump should be continued.
-       * server-src/driver.c (handle_taper_result): call continue_dumps
-         to restart a roomq dump.
-       * server-src/driver.c (handle_dumper_result): some rewrite, 
-         modified semantics of NO_ROOM, new message RQ-MORE-DISK.
-       * server-src/dumper.c (main): Modified parsing of FILE_DUMP, 
-         handling of use.
-       * server-src/dumper.c (write_dataptr): NO-ROOM is informational only,
-         trucate the file to a multiple of TAPE_BLOCK_BYTES.
-       * server-src/dumper.c (update_dataptr): rewrite to emit RQ-MORE-DISK
-         command.
+       * server-src/reporter.c (copy_template_file): make sure all data is
+         written to label template pipeline.
 
 1999-08-16  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        Reported by Brian Cuttler <brian@wadsworth.org>
 
 1999-08-15  Jon LaBadie  <jon@jgcomp.com>
-
+       
        * tape-src/tapetype.c: Speed it up by using larger sections in the
        second pass.
 
        not-that-portable `head -1'.
        Reported by Andrew Lare <lare@eos913c.gsfc.nasa.gov>
 
-1999-06-20  Thomas Hepper <th@ant.han.de>
-
-       * changer-src/chg-scsi.c: 2 new config keywords, changerident/tapeident
-       
-       * changer-src/scsi-changer-driver.c: deleted the linux driver at the
-       beginning, (wrong window on cut and paste .......)
-
-       * changer-src/scsi-defs.h: new element in Changer_IO which describes
-       the type of device which is handled by this entry (tape/robot)
-
-       * changer-src/scsi-changer-driver.c: New parameter to OpenDevice
-       to override the selection of the driver for this device. (See
-       also docs/TAPE.CHANGERS)
-
 1999-06-19  Alexander Zangerl  <az@Austria.EU.net>
 
        * client-src/sendbackup-dump.c (re_table): Match Solaris vxdump
        output.
 
-1999-06-18  Thomas Hepper <th@ant.han.de>
-
-       * server-src/changer.c: (changer_find) check if serachlabel is NULL
-       if yes don't print it to the debug file
-
-       * changer-src/scsi-solaris.c: (SCSI_ExecuteCommand) Add missing
-       parameter to DecodeExtSense.
-
-       * changer-src/scsi-aix.c: (SCSI_ExecuteCommand) Add missing
-       parameter to DecodeExtSense.
-
-       * changer-src/scsi-hpux.c: Added static char rcsid[] = ...
-       * changer-src-/chg-scsi.c: dito
-       * changer-src/scsi-changer-driver.c: dito
+1999-06-18 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-1999-06-17  Thomas Hepper <th@ant.han.de>
+       * server-src/dumper.c (read_indexfd): typo
 
-       * configure.in: Add new example files amanda.conf.chg-scsi, 
-       chg-scsi-linux.conf, chg-scsi-solaris.conf, chg-scsi-hpux.conf
-
-       * changer-src/chg-scsi-chio.c: Add parameter to find_empty
-
-       * changer-src/chg-scsi.c: Changed the way files are opened, added
-       FILE *debug_file because now it is possible to send some output to
-       stdout. (scsi-changer-driver.c).
-       (ask_clean) return 0  if result from get_clean_state is < 0
-       if get_current_slot returns < 0 try to find the used slot by asking
-       the robot. (happens if no slot file is available, or slot file is empty)
-       
-       * changer-src/scsi-changer-driver.c: New tape/robot types.
-       (find_empty) new parameter to specify range where to search.
-       More checks for NULL pointer ....
-       (DumpDev) new function to print the info for the device struct.
-       (ChangerStatus) some more output ....
-       
-       * changer-src/scsi-linux.c: Complete rewrite of SCSI_OpenDevice.
-
-       * common-src/debug.c: (debug_fp) new function to return the FILE *
-       to the debug file.
-
-       * contrib/sst/sst.c: Removed the inquiry call, this is handled by
-       chg-scsi. The old version will hang if for example no tape is loaded.
-       
-       * contrib/sst/Makefile: New Makefile, the old one does not work if not
-       the complete SUNdrv kit is installed.
+1999-06-18 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
+       * server-src/dumper.c (do_dump): Close the indexout fh and wait
+       for the completion of the index compress process.
+       * server-src/dumper.c (read_mesgfd,read_datafd): Call stop_dump only
+       if the index fd is already shut down.
+       * server-src/dumper.c (read_indexfd): On EOF, call stop_dump() if both
+       the mesg and data fd are shut down.
 
 1999-06-15  Adam Hammer  <hammer@math.purdue.edu>
 
        slightly different.
        Reported by Julian Stevens <julian.stevens@baedsl.co.uk>
 
+1999-06-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/util.c (fullread, fullwrite): versions of
+       read()/write() that keep looping until the buffer is
+       completely read/written, or an error occurs.
+       * common-src/Makefile.am: build util.c/util.h
+       * common-src/fileheader.c, common-src/fileheader.h
+       (fill_buffer): remove, replaced with fullread()
+       * server-src/holding.c: use fullread() instead of fill_buffer().
+       * common-src/bsd-security.c, restore-src/amrestore.c,
+       server-src/amcheck.c, server-src/driverio.c, server-src/dumper.c,
+       server-src/logfile.c, server-src/taper.c: use fullread/fullwrite
+       instead of doing the retry loops manually.
+
+1999-06-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (read_mesgfd, read_datafd): upon EOF,
+       close the stream.  If the other stream is also closed, shut
+       down.
+
+1999-06-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.c (REP_TIMEOUT): bump up to six hours, for slow
+       machines.
+       (exit_check): remove waitpid(), let the service reap its own
+       children.
+       (s_repwait): rename 'err' to 'errstr' to avoid conflict with
+       function in some libcs.
+       (s_ackwait): if no pipes were opened by this service, then shut
+       it down here.
+       (process_netfd): on EOF, be sure to also close the network
+       stream.  Also, if this is the last stream to be closed, shut
+       down the service.
+       (allocstream): correct a comment
+       (service_delete): only close the security handle if it is still
+       open.  Reap our children here instead of in exit_check().
+
+1999-06-01  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/taper.c (write_buffer): assert properly
+
 1999-06-01  John Williams  <williams@morinda.com>
 
        * changer-src/scsi-hpux.c (eject_tape): Enable it, it works.
        * config/acconfig.h: Add UDPPORTRANGE.
        * common-src/dgram.c: Implement it.
 
+1999-05-27  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/alloc.c (alloc, debug_alloc, newalloc, debug_newalloc):
+       make the size argument a size_t.
+       (alloc): if an allocation fails, in the error message print how
+       many bytes we tried to alloc.  This helps us determine if the
+       alloc call was errant, or we really were out of memory.
+       * common-src/amanda.h: update alloc/newalloc prototypes for
+       size_t changes.
+
 1999-05-27  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * config/ltconfig, config/ltmain.sh, config/libtool.m4i: Updated
        to libtool 1.3.2 plus a few patches.
        * config/config.guess, config/config.sub: Ditto.
 
+1999-05-26  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/protocol.c: retry connection failures three times,
+       waiting five seconds between each attempt.  Also, fix a lot
+       of untrue comments.
+
+1999-05-26  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.c: add a lot more dbprintfs so we know what's
+       going on.
+       (service_new): use error() instead of dbprintf(); exit()
+
+
 1999-05-25  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * docs/FAQ (tar-patch): Mention sparse file problem.
        * Makefile.am: Create acinclude.m4 in the top-level directory.
        * config/Makefile.am: Create link to acconfig.h in the top-level
        directory.
-       * configure.in: Add AMANDA_CFLAGS to CFLAGS.
+       * configure.in: Add AMANDA_CFLAGS to CFLAGS.  Set DUMPER_DIR without 
+       trying to run it.
        * common-src/Makefile.am: Create genversion.h with #defines, to
        avoid genversion-specific CPPFLAGS.
        * common-src/genversion.c: #include genversion.h
-       * common-src/version.h: VERSION_COMMENT must be const, as in
-       version.c.
+
+1999-05-24 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amandad.c (state2str): string "s_processrep" is 13
+       caracters.
 
 1999-05-24  Mike Grupenhoff <kashmir@munge.com>
 
        out the error message we generate, instead of whatever junk
        happens to be in the buffer.
 
+1999-05-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (bsd_stream_read): remove old
+       code that was part of something that ended up not happening.
+       (stream_read_callback): use ssize_t.
+
+1999-05-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (event_register): restructure asserts, and
+       for EV_READFD/EV_WRITEFD, assert that the fd is < FD_SETSIZE.
+
+1999-05-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/queue.h: move the multiple-inclusion #defines
+       into application namespace.  #undef each macro before defining
+       it, in case the OS has an identical macro.
+
 1999-05-23  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * server-src/amindex.h: Keep P macro expression in a single line.
        use value from the infofile only the datestamp are equal.
        Write all available value.
 
+1999-05-18  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/strerror.c (strerror): restructure so that it doesn't
+       need to malloc.
+
+1999-05-17  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/genversion.c (prvar): prototype declared it static,
+       but actual function was still extern.
+
 1999-05-15 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/planner.c (pick_inclevel): check for base_level+1 if
        1 on success.
        * server-src/driverio.h (taper_cmd, dumper_cmd): prototype.
 
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: make prototypes consistent, (putresult):
+       make first arg const.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/conffile.c (getconf_byname): islower takes an int
+       for an arg.
+       * server-src/diskfile.c (upcase): islower takes an int for an
+       arg.
+       * server-src/driver.c (update_failed_dump_to_tape): prototype.
+       * server-src/holding.c (insert_dirname, scan_holdingdisk):
+       prototype and make static, (is_datestr): isdigit takes an int
+       for an arg.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/calcsize.c (basename): make static, prototype, and
+       only include if BUILTIN_EXCLUDE_SUPPORT is defined and
+       HAVE_BASENAME is not defined.
+       * client-src/getfsent.c (dev2rde, samefile): prototype and
+       make static.
+       * client-src/sendbackup-dump.c, client-src/sendbackup-gnutar.c
+       (start_backup, end_backup): prototype.
+       * client-src/sendbackup.c (index_closed, save_fd): prototype
+       and make static.
+       * client-src/versionsuffix.c (main): prototype.
+       * common-src/alloc.c (internal_vstralloc): prototype.
+       * common-src/file.c (mk1dir): prototype, make static, and make
+       first arg const.
+       * server-src/amadmin.c (check_dumpuser): prototype.
+       * server-src/amflush.c (get_letter_from_user): prototype and make
+       static.
+       * server-src/amindexd.c: prototype and make static numerous local
+       functions.
+       * server-src/amlabel.c (main): prototype.
+       * server-src/amtrmidx.c (main): prototype.
+       * server-src/changer.c (report_bad_resultstr, run_changer_command):
+       prototype.
+       * server-src/conffile.h: properly prototype getconf_holdingdisks()
+       * server-src/driverio.h: properly prototype init_driverio().
+       * server-src/find.c (find_compare, parse_taper_datestamp_log):
+       prototype.
+       * server-src/infofile.c (zero_info, open_txinfofile,
+       close_txinfofile, read_txinfofile, write_txinfofile,
+       delete_txinfofile): prototype and make static.
+       * server-src/planner.c (main, askfor): prototype.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/server_util.c: include server_util.h for prototypes
+       * server-src/tapefile.h: properly prototype lookup_nb_tape()
+       * server-src/driverio.c (childstr): make static, make return
+       val const.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/find.h: properly prototype find_log()
+       * server-src/amtrmlog.c (main): prototype.  find_log() takes
+       no arguments.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/reporter.c: make all functions and globals
+       static.  Prototype all functions, and make them consistent wrt
+       K&R.  Place all prototypes together.  Place data type
+       declarations before the prototypes that use them.  Remove
+       unused sort_by_time().
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (process_dumpline): clean up the error
+       return code
+       * server-src/dumper.c (log_msgout): no need to reuse errf global,
+       it makes me nervous.  Also, use amfree instead of free.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/packet.c (pkt_cat): remove a bogus assert - len is
+       a size_t, which is unsigned, so it will always be >= 0.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.c (action_t): consolidate A_PKTTIMEOUT and
+       A_REPTIMEOUT into just A_TIMEOUT.
+
+1999-05-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h, common-src/alloc.c, common-src/event.c,
+       common-src/rsh-security.c, server-src/driver.c,
+       server-src/dumper.c: (min, max): consolidate all min/max
+       definitions into amanda.h
+
 1999-05-14  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * docs/TAPE.CHANGERS (chg-rth): URL for chs is no longer valid.
 
+1999-05-12  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h, common-src/alloc.c, common-src/file.c:
+       const the filename arg to all of the dbmalloc versions of
+       alloc and io functions
+
+1999-05-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/protocol.c (proto_t): don't need prev and next ptrs
+       anymore
+
+1999-05-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h, common-src/alloc.c: remove the static
+       buffer manager - nothing uses it.  It can be resurrected in
+       the future if needed.
+
+1999-05-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: define stringconcat() macros that
+       concatenate two const strings together
+       * common-src/versuff.c.in (versionsuffix, version): generate
+       data at compile time using stringconcat().
+       * common-src/genversion.c: simplify, don't need to alloc anything
+       * common-src/Makefile.am (genversion_LDADD): this doesn't need
+       alloc.o or error.o anymore
+
+1999-05-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/security.c (security_handleinit, security_streaminit):
+       change default error message "unknown error" to "unknown protocol
+       error" or "unknown stream error" to help identify where an
+       messageless error was triggered.
+
+1999-05-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.c (main): call initgroups(), and also set
+       the real gid.
+
+1999-05-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driver.c (start_some_dumps): if a dumper is
+       constrained, and some dumpers or the taper are active, register
+       a EV_WAIT event.
+       * server-src/driver.c (handle_taper_result,
+       handle_dumper_result):  wakeup constrained dumpers after we
+       have freed some resources.
+
+1999-05-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/fileheader.c, common-src/fileheader.h: rework the
+       fileheader parse and format code to remove a lot of duplicated
+       code (in the F_DUMPFILE and F_CONT_DUMPFILE cases), consting
+       arguments, and simplifying parse code.
+
 1999-05-10  Mike Grupenhoff <kashmir@munge.com>
 
        * client-src/sendsize.c (getsize_dump): print out the strerror
        if we can't exec killpgrp.
 
+1999-05-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (add_msg_data): first two arguments
+       to memmove() were backwards.
+
 1999-05-07 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * example/amanda.conf.in: typo
 
+1999-05-07  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/alloc.c (safe_env): allow DISPLAY into the
+       environment for purify.
+       * server-src/holding.c (rename_tmp_holding): if fill_buffer
+       returns 0, don't try to parse a nonexistant header.
+       * server-src/taper.c (file_reader_side): init datestamp to
+       NULL, and don't try to free it if it's still NULL on exit.
+
+1999-05-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driver.c (start_some_dumps): sleep_time is an
+       offset, not an absolute.  Leave it that way when we return from
+       this function.
+
 1999-05-05  Mike Grupenhoff <kashmir@munge.com>
 
        * server-src/amverify.sh.in (pecho): new function.  Like echo
        flags and also know if it supports \r.  So we just punt and use
        perl.
 
+1999-05-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driver.c: convert to use event handler.
+       (some_dumps_in_progress, lookup_dumper): nuke.
+       (sleep_time): make a time_t and static.
+       (IDLE_NO_DUMPERS): give a lower precedence than IDLE_START_WAIT.
+       (start_some_dumps): make this work on one dumper instead of all.
+       Call when a dumper is finished and needs more work.
+       (handle_idle_wait): callback for dumpers waiting for delayed
+       disks to start up.
+       * server-src/driverio.c: initialize event handles for dumpers
+       and the taper.  Nuke addfd().
+       * server-src/driverio.h: add event handles for each dumper, and
+       one global one for the taper.  Nuke maxfd and readset globals.
+
+1999-05-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driver.c (taper_queuedisk): new function that takes
+       a disk_t, and, if the taper is not busy, tells it to write it out,
+       or else adds it to the tapeq.  Make use_lffo global static.
+       * server-src/driver.c (handle_taper_result, handle_dumper_result):
+       call taper_queuedisk() instead of queueing ourself.
+
+1999-04-30  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driver.c: make all local functions static.
+       Exposed two prototypes for nonexistant functions
+       (diskname2filename, driver_main), and one function (dump_state)
+       that was never called.  #if 0 out dump_state.
+       Nuke inside_dump_to_tape global - it's value was never used.
+       Make pending_aborts global a static local in handle_dumper_result.
+
+1999-04-30  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driverio.h (dumper_t): merge infd and outfd into
+       just 'fd'.  Comment the other members of the struct.
+       * server-src/driverio.c: infd/outfd -> fd
+       * server-src/driver.c (handle_dumper_result): merge some common
+       code between the FAILED and TRYAGAIN cases.  Comment the
+       ABORT_FINISHED case.  Also infd/outfd -> fd.
+
 1999-04-29 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/planner.c (when_overwrite): return a big number (1024)
        * config/ltconfig, config/ltmain.sh, config/libtool.m4i: Updated
        from libtool 1.3.
 
+1999-04-29  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/driver.c (handle_dumper_result): remove FATAL_TRYAGAIN
+       case, nothing uses it.
+       * server-src/driverio.c, server-src/driverio.h: garbage collect
+       FATAL_TRYAGAIN.  static & const cmdstr.
+
+1999-04-28  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/diskfile.c (read_diskfile): rework to take a
+       disklist_t * as an argument, and return -1 on error, or 0 on
+       success.  const the filename argument.  Kill a few globals.
+       * server-src/diskfile.c (lookup_host, lookup_disk): const
+       arguments
+       * server-src/diskfile.h: adjust prototypes for above changes
+       * server-src/amadmin.c, server-src/amcheck.c,
+       server-src/amcleanupdisk.c, server-src/amflush.c,
+       server-src/amindexd.c, server-src/amtrmidx.c,
+       server-src/amtrmlog.c, server-src/driver.c,
+       server-src/planner.c, server-src/reporter.c: adjust calls to
+       read_diskfile() to deal with convention
+
+1999-04-28  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (read_mesgfd, read_indexfd): on EOF, just
+       stop reading these streams.  We let EOF on the data stream cause
+       the entire dump to be stopped.
+
+1999-04-27  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/rsh-security.c (conn_read_callback): cast
+       event_wakeup() arg to event_id_t.
+
 1999-04-25  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * common-src/versuff.c.in: Adjust constness to match version.h.
 
        * server-src/amdump.sh.in: execute amtrmlog.
 
+1999-04-24 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * client-src/sendbackup.c: rename write_tapeheader to info_taperheader
+       we already have a write_tapeheader function in dumper.c
+       * client-src/sendbackup.h: ditto
+       * client-src/sendbackup-dump.c: ditto
+       * client-src/sendbackup-gnutar.c: ditto
+
+1999-04-23 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * dumper-src/gnutar.pl.in: add debuging code.
+       * server-src/planner.c (getsize): send optionstr() for estimate 
+       with a wrapper.
+       * client-src/selfcheck.c: init program_is_wrapper to 0.
+       * client-src/sendsize.c: implement DUMPER-API, support only
+        estimate-direct.
+
 1999-04-22 John R. Jackson  <jrj@purdue.edu>
 
        * configure.in: add --with-broken-fsf to use a read() loop instead
        * config/acconfig.h: ditto
        * tape-src/tapeio.c (tapefd_fsf): ditto
 
-1999-04-22  Alexandre Oliva  <oliva@dcc.unicamp.br>
+1999-04-22  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * docs/SYSTEM.NOTES: Typo
+       * docs/SAMBA: Update on samba-largefs patch.
+       * docs/FAQ: New FAQ about promotion of full dumps.
+
+1999-04-20  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * tape-src/tapeio.c (tape_open): Retry after EBUSY and EINTR too.
+       Comment out test that would set filename to /dev/null.
+
+1999-04-18  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * docs/WISHLIST: Global reformat.  Removed fixed issues.  Added
+       auto-flush mode.
+
+1999-04-17 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/server_util.c: use snprintf instead of ap_snprintf.
+
+1999-04-17 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/server_util.c: new file for utility function.
+       New function construct_datestamp.
+       * server-src/server_util.h: ditto
+       * server-src/Makefile.am: link server_util.c with libamserver.
+       * amcleanupdisk.c (construct_datestamp): remove function.
+       * server-src/driver.c: ditto
+       * server-src/dumper.c: ditto
+       * server-src/amflush.c: ditto
+       * server-src/planner.c: ditto
+
+1999-04-17  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c: this doesn't need queue.h
+
+1999-04-17  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c: Insert new events at the head of the eventq,
+       not the tail, so we don't loop forever if a newly registered
+       event has the same type as the one currently firing.  Noticed
+       and diagnosed by Jean-Louis Martineau.
+       Use a LIST for the eventq, instead of a TAILQ, since we don't need
+       to do tail insertions anymore.
+       Make the eventq_* functions take a queue name so we can also use
+       them for the handle cache.  Rename eventq_append() to eventq_add().
+
+1999-04-17 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * dumper-src/gnutar.pl.in: add DUMPER_DIR to INC.
+
+1999-04-17 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * client-src/selfcheck.c: Implement DUMPER-API.
+       * dumper-src/gnutar.pl.in (command_selfcheck): print OK, the function
+       is not implemented.
+       * dumper-src/generic-dumper.pl.in (parse_options): option are
+       separated by ;
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: make dumpsize and headersize static.  Rename
+       nb_header_block to headersize and also make it static.  headersize
+       now counts bytes instead of blocks, just like the other two.
+       Use SEEK_SET in an lseek instead of hardcoding 0.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: implement --with-cflags to allow turning on
+       compiler warnings and optimizations
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (gethandle, puthandle): new functions that
+       keep a cache of handles to reduce calls to malloc/free.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/alloc.c (dbmalloc_caller_loc): const the file
+       arg, use the queue macros to maintain the list.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/versuff.c.in: const the return str of version()
+       and versionsuffix.  Bump copyright to 1999.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.c, client-src/amandad.h,
+       client-src/sendbackup-dump,c, client-src/sendbackup-gnutar.c,
+       client-src/sendbackup.c, common-src/bsd-security.c,
+       common-src/dgram,c, common-src/dgram.h, common-src/event.c,
+       common-src/event.h, common-src/krb4-security.c,
+       common-src/krb5-security.c, common-src/packet.c,
+       common-src/packet.h, common-src/protocol.c, common-src/security.c,
+       common-src/security.h, server-src/amcheck.c, server-src/conffile.c,
+       server-src/conffile.h, server-src/dumper.c:
+       update copyright to 1999 on things I've touched this year.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: remove version_info extern.  Bump
+       copyright to 1999
+       * common-src/genversion.c: constify version_info.  Emit
+       {KRB4,KRB5,RSH}_SECURITY.  Bump copyright.
+       * common-src/version.h: const VERSION_COMMENT and version_info.
+       const return str and fully prototype versionsuffix() and version()
+       prototypes.  Bump copyright.
+       * server-src/planner.c (main): iterate through version_info using
+       an index instead of a pointer.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/conffile.c: explicitly give the seen_columnspec global
+       an int type instead of letting the compiler default to it.
+
+1999-04-16  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.h (event_id_t): a new typedef for the
+       first arg to event_register.  Should be wide enough to
+       reasonably hold an int or a pointer (but it is ok to trunc
+       the pointer if necessary).  Update proto for event_register()
+       and event_wakeup().
+       * common-src/event.c: struct event_handle->data is now an
+       event_id_t.
+       (event_register, event_wakeup): adjust args for event_id_t)
+       (event_register): event_id_t is unsigned, no need to assert
+       positivity anymore.
+       * common-src/rsh-security.c (rsh_stream_read): cast first arg to
+       event_register() to event_id_t.
+
+
+1999-04-15  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (release): nuke, and inline into event_loop.
+       * common-src/event.c (event_loop): flesh out the timeout comment.
+       Combone the EV_WAIT and EV_DEAD empty cases in the post-select loop.
+       * common-src/event.h: flesh out the event_type_t comment.
+
+1999-04-15  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (fire): inline this with a macro.  Remove
+       timestamp arg.  eh->lastfired is now only valid for EV_TIME
+       events.  Removes several time() systems from the critical path.
+       * common-src/event.c (event_wakeup): have this fire EV_WAIT events
+       directly instead of deferring back to the event loop.  Removes the
+       sequencing restriction for event_wakeup.
+
+1999-04-15  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/planner.c (getsize): put the hosts disks on the waitq
+       before sending the request, not after.
+
+1999-04-15  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * docs/UPGRADE: Update URL for archived message.
+
+1999-04-14 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/amcheck.c (main): should not set real uid to 0.
+
+1999-04-13 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/bsd-security.c (bsd_connect): dgram_bind return the port
+       number, we don't need ntohs().
+
+1999-04-12  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/dgram.c,common-src/dgram.h: nothing uses dgram_alloc()
+       anymore, gc them.
+
+1999-04-12  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/amindexd.c: dgram.h not needed
+
+1999-04-12  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c: fix a bunch of inaccurate comments.
+       * common-src/event.c (event_loop): prune dead events in the
+       pre-select pass instead of in the EV_WAIT pass.
+       * common-src/event.c (fire): factor out all code that fires
+       events into a 'fire' function.
+       * common-src/event.c (signal_handler): bounds check the signal
+       number against the size of sigtable instead of assuming sigtable
+       is NSIG big.
+
+1999-04-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.c (allocstream): if security_stream_server()
+       fails, dbprintf the error.
+
+1999-04-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: implement --with-rsh-security
+       * common-src/rsh-security.c: first attempt at using rsh or a rsh-like
+       command for dump transport and authentication.  Still has lots
+       of "issues"
+       * common-src/Makefile.am: build rsh-security.c
+       * common-src/security.c: add rsh_security_driver to the drivers array
+       * config/acconfig.h: define RSH_SECURITY
+
+1999-04-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (runcompress): use the proper end of the pipe
+       for writing and reading.  Also, grab errno early on fork error
+       before calling close.
+       * server-src/dumper.c (sendbackup_response): make sure the client
+       at least send us a mesgfd and datafd.
+
+1999-04-10  Mike Grupenhoff <kashmir@munge.com>
 
-       * docs/SYSTEM.NOTES: Typo
-       * docs/SAMBA: Update on samba-largefs patch.
-       * docs/FAQ: New FAQ about promotion of full dumps.
+       * client-src/amandad.c (main): don't dup stdout to db_fd - it might
+       be needed by the security driver
+       * client-src/amandad.c (s_ackwait, allocstream,): on error, don't
+       attempt to event_release a handle we haven't attached yet.
 
-1999-04-20  Alexandre Oliva  <oliva@dcc.unicamp.br>
+1999-04-10  Mike Grupenhoff <kashmir@munge.com>
 
-       * tape-src/tapeio.c (tape_open): Retry after EBUSY and EINTR too.
-       Comment out test that would set filename to /dev/null.
+       * ap_snprintf -> snprintf, ap_vsnprintf -> vsnprintf
 
-1999-04-18  Alexandre Oliva  <oliva@dcc.unicamp.br>
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
 
-       * docs/WISHLIST: Global reformat.  Removed fixed issues.  Added
-       auto-flush mode.
+       * client-src/Makefile.am (noinst_HEADERS): add amandad.h
 
-1999-04-17 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
 
-       * server-src/server_util.c: new file for utility function. 
-       New function construct_datestamp.
-       * server-src/server_util.h: ditto
-       * server-src/makefile.am: link server_util.c with libamserver.
-       * amcleanupdisk.c (construct_datestamp): remove function.
-       * server-src/driver.c: ditto
-       * server-src/dumper.c: ditto
-       * server-src/amflush.c: ditto
-       * server-src/planner.c: ditto
+       * common-src/Makefile.am (libamanda_la_SOURCES): build
+       krb4-security.c
 
-1999-04-15  Alexandre Oliva  <oliva@dcc.unicamp.br>
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
 
-       * docs/UPGRADE: Update URL for archived message.
+       * configure.in: implement --with-dbmalloc=[dir], where dir is
+       where the dist is unpacked and built.  This could be improved on,
+       because it doesn't handle the case where it's installed.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/sendbackup.c: security changes:
+       remove krb4 code and NAUGHTY_BITS macros.
+       (parse_options): don't look for krb4 options
+       (main): don't close pipes that were handed to us from amandad.
+       Don't open stream directly - just use the pipes given to us.
+       * client-src/sendbackup-dump.c, client-src/sendbackup-gnutar.c:
+       Remove krb4 code and NAUGHTY_BITS macros.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * client-src/amandad.h: new file describing the pipes between
+       amandad and children.
+       * client-src/amandad.c: rewrite for security changes.  Can
+       now handle multiple requests simultaneously, and has a state
+       machine to deal with each active request.
+       This handles all network transmissions and authentication.
+       Each child process (sendbackup, selfcheck) gets three general
+       purpose pipes to amandad which it may allocate for anything.
+       amandad relays these pipes to equivalent security_streams.
+       Lots of other stuff.
+       Finally, NEED_KEYPIPE stuff removed.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: security changes:
+       Remove krb4 includes and NAUGHTY_BITS macros.
+       Remove no-longer-true comment about DATABUF_SIZE ==
+       TAPE_BLOCK_BYTES for krb4
+       Remove file descriptor and event handle from streams array.  Add
+       a security_stream_t.
+       Remove global read buffer.
+       (check_options): remove krb4 code.
+       (service_ports_init): remove, now handled by individual security
+       drivers.
+       (main): remove dgram usage.
+       (do_dump): remove DUMPER_SOCKET_BUFFERING - now handled in the
+       bsd driver.  schedule reads on the streams using
+       security_stream_read.
+       (read_mesgfd,read_datafd,read_indexfd): adapt to
+       security_stream_read callback interface.
+       (stop_dump): just call security_stream_close on all non-null
+       streams.
+       (sendbackup_response): adapt to new protocol layer error return.
+       Remove krb4 code.
+       (startup_dump): stinky hack to parse the security driver string out of
+       the options passed to us from driver.
+       Lookup the security driver with said string.
+       Remove krb4 code.
+       Free request after calling protocol_sendreq().
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/planner.c: security changes:
+       (main): Remove dgram usage.  Call protocol_init().  Remove
+       krb4 code.
+       (getsize): remove krb4 code.  Handle protocol layer api changes.
+       Lookup security driver/complain if not found.  Free request
+       after calling sendreq.  All hosts get put on the waitq since
+       sendreq never returns an error.
+       (handle_result): deal with new protocol layer error semantics.
+       Remove krb4 code.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/conffile.c: remove INTERFACE undef hack.  Our
+       namespace isn't polluted by krb4 headers anymore, so it's
+       unneeded.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/amcheck.c: security changes:
+       (main): ignore SIGPIPE - some security drivers might get it.
+       Remove all usages of dgram.
+       Make our real uid root and our effective uid amanda so we can
+       get back to root later (on most os's :()
+       (start_client_checks): remove krb4 bits.
+       The dump user check should check the effective uid.
+       Get the name of the security driver for this host out of
+       host->diskp->security_driver.
+       Free req after calling protocol_sendreq() because it will internalize
+       it.
+       protocol_sendreq doesn't return any errors - they're all returned
+       via handle_response.
+       (handle_result): renamed from handle_response for consistency.
+       The protocol layer doesn't pass us a proto_t anymore, so detect
+       errors based on pkt being NULL.
+       Remove krb4 bits - security violations will be indicated by a 
+       NULL pkt.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/protocol.[ch]: rewrite for security api.  The entry
+       points now have the 'protocol' prefix.  See protocol.h for more
+       info.
+       * common-src/security.c: rewrite for security api.  This now contains
+       the functions for the 'base class' or some approximation of it.
+       See security.h for the entry points, or docs/SECURITY-API.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: rip out krb4 defines, headers, and
+       prototypes.  Also, make assert() abort() after calling error().
+       * common-src/krb4-security.c: stub file that pulls in the real
+       krb4-security out of amanda-krb-2 if KRB4_SECURITY is defined.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/conffile.h: aggregate all of the compress defines
+       (COMP_{NONE,FAST,BEST,...}) into an enum and typedef it to comp_t.
+       Make dumptype_t->compress a comp_t.
+       * server-src/dumper.c: make srvcompress global a comp_t.
+       * server-src/dumper.c (runcompress): add a comp_t third arg
+       that specifies the level of compression for this fd.
+       * server-src/dumper.c (do_dump): always compress index files
+       with COMP_BEST compression, as pointed out by Jean-Louis Martineau.
+       * server-src/dumper.c (read_indexfd): read the indexfd, not the
+       datafd.  Also noted by Jean-Louis Martineau.
+
+1999-04-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/planner.c (main): ignore SIGPIPE.  tcp based
+       security drivers may get this while getting estimates.
+       Set the real uid to root, and the effective uid to the amanda
+       user, so we can get back to root later if needed.
+       * server-src/planner.c (handle_result): rework error logic
+       so we don't need to use p->state, which will eventually go
+       away.
+
+1999-04-08  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: rewrite to use the event handler instead
+       of a select loop.  Also, compress the index output using
+       runcompress() instead of forking a compress ourselves.
+
+1999-04-08  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (sendbackup_response): don't krb4 authenticate
+       streams if krb4_auth if false.
+
+1999-04-08  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (do_dump): some formatting cleanups.  Nuke
+       'killerr' - we can do without it.
+
+1999-04-08  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (do_dump): store compresspid inside of
+       the databuf
+
+1999-04-08  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (parse_info_line): parse info lines
+       from sendbackup directly into the 'file' global.  Eliminate
+       the backup_name, recover_cmd, and compress_suffix globals.
+       * server-src/dumper.c (finish_tapeheader): nuke usage
+       of above globals.  Nuke unneeded explicit nul terminations (we
+       memset the whole thing in fn_init).
+
+1999-04-08  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (process_dumpline): rewrite to use strtok
+       and const the argument.
+       * server-src/dumper.c (make_tapeheader): rename to finish_tapeheader
+       and prototype it.  Remove the 'type' arg, since it's always
+       F_DUMPFILE.  Remove call to fn_init().
+       * server-src/dumper.c (do_dump): call fh_init on 'file' while
+       initializing globals.  Call finish_tapeheader after getting info
+       endline.
 
 1999-04-07 John R. Jackson  <jrj@purdue.edu>
 
        * server-src/taper.c: allow tapedev to be /dev/null.
        * man/amanda.8.in: allow tapedev to be /dev/null.
 
+1999-04-07  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: collect got_info_endline, got_sizeline,
+       got_endline, and header_done into one bitmask global, and make it
+       static.  Also, make 'file' static.
+
 1999-04-06 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/reporter.c (TextRule): Fix to write the full string.
 
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: MIT krb5 has libk5crypto, Cygnus kerbnet 1.2
+       calls it libcrypto.  Check for both.
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (check_user): if an .amandahosts
+       file is missing or unreadable, log this fact to the debug file
+       instead of claiming that a user doesn't have permission.
+       * common-src/bsd-security.c (bsd_stream_client): if
+       DUMPER_SOCKET_BUFFERING is defined, set the socket read buffer to
+       be twice the size of our read buffer.
+
 1999-04-06  David Mankins <dm@k12-nis-2.bbn.com>
 
        * common-src/security.c (bsd_security_ok): if an .amandahosts
        file is missing or unreadable, log this fact to the debug file
        instead of claiming that a user doesn't have permission.
 
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: put all of the streams (data,mesg,index)
+       into an array with a name tag.
+       * server-src/dumper.c (stop_dump): new function that cleans up
+       and shuts down all of the streams.
+       * server-src/dumper.c (sendbackup_response): make static, pass
+       response_error through p->datap instead of making it global.
+       Rewrite the parsing to use strtok() and take advantage of the
+       streams array instead of repeading code for all three streams.
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (main): keep our real uid as 0, and make
+       our effective uid nonprivlidged, so we can get back to root
+       later.  Don't print what port we bound to.  This info won't
+       always be available or even applicable.
+       * server-src/dumper.c (do_dump): create the stats line with one
+       snprintf instead of a huge amount of code.
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (startup_dump): make static, and const all
+       of the string args
+       * server-src/dumper.c (do_dump): make static
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (do_dump): no need to have a separate buffer
+       to read the mesgfd - just reuse the one we used for data reads.
+       Gets rid of one more global.  Also, we don't need to leave
+       space for a NUL anymore.
+       * server-src/dumper.c (main): wait for children after closing
+       our fds.  Some children may be blocked waiting for EOF on outfd,
+       effectively causing deadlock between dumper and child.
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (add_msg_data): now takes a 'len' arg, and
+       doesn't expect the data to be nul terminated.  Also, move
+       the buffer from global scope into the function, and have a NULL
+       arg flush it out if there is leftover data at the end.  Finally,
+       resize the buffer in 256 byte chunks.
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/stream.c, common-src/stream.h (stream_client): add
+       yet another arg - if nonzero, do a nonblocking connect
+       * server-src/dumper.c: catch up with extra arg to stream_client()
+
+1999-04-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c, common-src/security.h: attempt
+       to decouple security streams from security handles.  Lots of
+       other restructuring.
+
 1999-04-01 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amcheck.c: -t should read the tapelist to validate
        * changer-src/chg-chio.pl.in (changeTape): do not print status to
        both stdout and stderr; this causes failures on FreeBSD
 
+1999-03-23  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/stream.c, common-src/stream.h (stream_client):
+       const the hostname arg
+
+1999-03-22 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * configure.in: AC_SUBST(GNUTAR_LISTED_INCREMENTAL_DIR)
+       * dumper-src/gnutar.pl.in: use @GNUTAR_LISTED_INCREMENTAL_DIR@
+
+1999-03-21 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * configure.in: default for DUMPER_DIR is $exec_prefix/dumper.
+       * Makefile.am: make dumper-src directory
+       * dumper-src: directory for program that implement the DUMPER-API.
+       * dumper-src/Makefile.am:
+       * dumper-src/generic-dumper.pl.in: first draft of a generic wrapper.
+       * dumper-src/gnutar.pl.in: first draft of a gnutar wrapper.
+
 1999-03-21  Elmar Bartel  <bartel@Informatik.TU-Muenchen.DE>
 
        * conffile.h, conffile.c: new columnspec option
        the regular expressions, so as to make us more adaptable to future
        minor changes and bugfixes the the output format of some dumps
 
-1999-03-15 Thomas Hepper <th@ant.han.de>
+1999-03-16 Thomas Hepper <th@ant.han.de>
        * changer-src/chg-scsi.c: If the open of the TapeDevice fails
        the programm is not terminated.
        * changer-src/scsi-aix.c: The wrong ident string was checked
        Wrong fd passwd to LogSense.
        * docs/TAPE.CHANGERS: added note about linux and aha1542
 
-1999-03-15   Michael Povel  <mcp@ladyada.han.de>
-       * server-src/amlabel.c: Wrong parameter to changer_label
-       * server-src/amtape.c: New function update_one_slot,
-       update_labeldb
-       * server-src/changer.c: Changed slotsp from int to char, some
-       debug prints.
-       * server-src/changer.h: Changed prototype for changer_label
+1999-03-15  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/packet.h: explicitly list the numeric values for
+       the pktype_t enum, so we can use them on the wire
 
 1999-03-15  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * config/libtool.m4i, config/config.guess, config/config.sub: ditto
        * configure.in: dropped AC_PROG_RANLIB, as suggested by libtoolize
 
+1999-03-15  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (recv_security_ok): bring over
+       increased verbosity change from common-src/security.c
+
 1999-03-14  Mathias Herberts  <Mathias.Herberts@ago.fr>
 
        * man/amrecover.8.in: document mode and setmode
 
 1999-03-07 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/dumper.c (startup_dump): rename dumpname to progname. 
+       * configure.in: new option --with-dumperdir=DIR to specify the 
+       directory for the dumpers (dumper api).
+       * config/acconfig.h: add def of DUMPER_DIR
+
+1999-03-07 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/conffile.c: accept any string for the program.
+       * server-src/amcheck.c: add the keyword DUMPER to the request if 
+       the program is not DUMP or GNUTAR.
+       * server-src/planner.c: ditto
+       * server-src/dumper.c: ditto
+
+1999-03-07 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * server-src/dumper.c (startup_dump): rename dumpname to progname.
        the function will use the parameter progname instead of the
        global variable.
 
        <rgebhart@cybernet-ag.net>, sparc-unknown-openbsd2.3 is supported;
        I assume other openbsd platforms work too.
 
+1999-03-06 Thomas Hepper <th@ant.han.de>
+
+       * client-src/sendbackup-gnutar.c: Replaced #fi with #endif
+       * changer-src/: Get in sync with 2.4.2 Version
+
 1999-03-05 Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * configure.in: set SAMBA_VERSION
 1999-03-05 Mathias Herberts <Mathias.Herberts@ago.fr>
 
        * recover-src/amrecover.h (set_mode, show_mode) declare new functions.
-       * recover-src/amrecover.h (SAMBA_SMBCLIENT, SAMBA_TAR) define new
+       * recover-src/amrecover.h (SAMBA_SMBCLIENT, SAMBA_TAR) define new 
        constant.
        * recover-src/extract_list.c: declare variable samba_extract_method.
-       * recover-src/extract_list.c (extract_files_child): set dumptype 
+       * recover-src/extract_list.c (extract_files_child): set dumptype
        according to samba_extract_method.
        * recover-src/help.c (help_list): print help for new command mode
        and showmode.
        * recover-src/uscan.l:
        * recover-src/uparse.y:
 
-1999-03-04  Thomas Hepper <th@ant.han.de>
-       * configure.in Check if samba tar accept the q option
-       * changer-src/chg-scsi.c New command -status. Display slot status.
-       add debug prints to parse_args. Missing {} in case COM_SLOT 
-       add put_current_slot if reset was successfull
-       * changer-src/aix.c Init struct pwork with 0's.
-       Fixed error in copy of the product indent form the inquiry
-       * changer-src/scsi-bsd.c see aix.c
-       * changer-src/scsi-hpux_new.c see aix.c
-       * changer-src/scsi-irix.c see aix.c
-       * changer-src/scsi-linux.c see aix.c
-       * changer-src/scsi-solaris.c see aix.c
-       * changer-src/scsi-changer-driver.c New function TerminatString,
-       places 0 from the end of a string until first char/num
-       Fixed wrong parameter for GenericRewind in LogSense
-       In GenericElementStatus terminate VOL Tag String with 0
-       New function CHangerStatus. dumps changer info on stdout.
-       * changer-src/scsi-defs.h VolTag[TAG_SIZE+1] to have place for
-       terminating 0
-       * client-src/sendbackup-gnutar.c Add option q to tar call if
-       samba tar understand q option
-       * config/acconfig.h New define if samba tar accepts q option
-       * docs/TAPE.CHANGERS Add note on how to init the labelfile      
+1999-03-05  Mike Grupenhoff <kashmir@munge.com>
 
+       * common-src/amanda.h: use ssize_t in writev return value
+       * common-src/bsd-security.c (bsd_stream_write,bsd_stream_read):
+       use ssize_t over int
+       * common-src/file.c (areads): use ssize_t to hold read() return val
+       * common-src/fileheader.c (fill_buffer): usse ssize_t to hold read()
+       return val
+       * common-src/security.h: stream_read's callback now takes a ssize_t
+       as the third argument.
+       * common-src/writev.c (writev): return a ssize_t
+
+1999-03-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: check for ssize_t, make it int if not present
+       * config/acconfig.h: add def for ssize_t
+
+1999-03-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/base64.c (base64encode): don't cast away a const
+       needlessly.
+
+1999-03-04  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * common-src/bsd-security.c (stream_read_callback): change n to int
+       since ssize_t doesn't exist on all OS.
 
 1999-03-03  Ralf Fassel <ralf@akutech.de>
 
        * common-src/conffile.h: bit field of length 1 should be unsigned int,
        not int.
 
+1999-03-03  Ralf Fassel <ralf@akutech.de>
+
+       * common-src/bsd-security.c (stream_read_callback): n should be ssize_t.
+
+1999-03-03  Ralf Fassel <ralf@akutech.de>
+
+       * changer-src/scsi-changer-driver.c (CloseDevice): wrong assignment.
+
+1999-03-03  Ralf Fassel <ralf@akutech.de>
+
+       * common-src/base64.c (base64encode): remove warning from sgi cc
+       compiler.
+
+1999-03-03  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c: use EV_WAIT events instead of
+       maintaining a queue of listeners.  Refcnt the dgram read event
+       handle.
+
 1999-03-01  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/driverio.h: new parameter level to update_info_taper().
        * server-src/driverio.c (startup_dump_processes): new parameter
        inparallel is used instead of global variable.
        * server-src/driver.c (main): call init_driverio.
-       * server-src/driver.c (main): call startup_dump_processes with
+       * server-src/driver.c (main): call startup_dump_processes with 
        inparallel parameter.
        * server-src/amflush.c (main): call init_driverio.
 
 1999-03-01  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/amrmtape.sh.in: work with "last_level" and 
+       * server-src/amrmtape.sh.in: work with "last_level" and
        "consecutive_runs" in the ouput of "amadmin export".
 
+1999-03-01  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/security.h: implement security_connect callback and
+       security_status_t changes
+
+1999-03-01  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (bsd_connect): properly munge the uids
+       to get a reserved port
+       * common-src/bsd-security.c: adapt to the security_connect
+       callback changes
+       * common-src/bsd-security.c (bsd_sendpkt): dgram_cat is varargs now,
+       so skip the vstralloc
+
+1999-03-01  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c: implement EV_WAIT events.  Implement macros
+       for adding/removing/traversing the event queue
+       * common-src/event.h: define EV_WAIT, and prototype event_wakeup()
+
 1999-02-28  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * docs/WISHLIST: protocol between the driver and dumpers.
        * server-src/amtoc.pl.in: output the datestamp of each dump, because
        amflush can flush the same disk multiple date.
 
-1999-02-27  Thomas Hepper <th@ant.han.de>
-       * server-src/amlabel.c fixed call to changer_label
-
 1999-02-26  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/holding.h: declare struct holding_t.  Remove
-       declaration of insert_dirname, scan_holdingdisk.  Declare
+       * server-src/holding.h: declare struct holding_t.  Remove 
+       declaration of insert_dirname, scan_holdingdisk.  Declare 
        new function free_holding_list.  pick_datestamp and 
        pick_all_datestamp now return (holding_t *).
        * server-src/holding.c (insert_dirname): new parameter holding_list
        pick_all_datestamp.
        * server-src/amflush.c: use the list return by pick_datestamp.
        * server-src/amcleanupdisk.c (check_disks): use the list return by
-        pick_all_datestamp.
-
-1999-02-26 Thomas Hepper <th@ant.han.de>
-
-       * changer-src/chg-scsi.c Added global structs for the openend
-       devices. Added new options label and search for the barcode
-       support. New function MapBarCode, map barcode from reader
-       to amanda tape labels.
-       *changer-src/scsi-aix.c Error in copying SCSI ident fixed. 
-       A space mut not be the end of the string...
-       * changer-src/scsi-bsd.c same as scsi-aix.c 
-       * changer-src/scsi-irix.c same as scsi-aix.c 
-       * changer-src/scsi-solaris.c same as scsi-aix.c 
-       * changer-src/scsi-hpux_new.c same as scsi-aix.c 
-       * changer-src/scsi-linux.c same as scsi-aix.c , fixed
-       error in check if we open an sg device.
-       * changer-src/scsi-changer-driver.c Removed LookupFunction
-       and LookupDevice functions .
-       * docs/TAPE.CHANGERS update info about chg-scsi
-
-1999-02-26  Michael Povel  <mcp@ladyada.han.de>
-
-       * server-src/amcheck.c Added debug output for barcode
-       support
-       * server-src/amlabel.c Added debug output, inform chg-scsi
-       on new label
-       * server-src/amtape.c Added debug output, inform chg-scsi
-       on new label
-       * server-src/changer.c Added debug output, filled function
-       changer-label with live, label search should work now
+       pick_all_datestamp.
 
 1999-02-23  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
 1999-02-15  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/driverio.c (startup_tape_process): new taper_program 
+       * server-src/driverio.c (startup_tape_process): new taper_program
        argument.
        * server-src/driverio.h: remove declaration of taper_program.
        * server-src/driver.c (main): declare taper_program.
        new dumper_program argument.
        * server-src/driverio.h: remove declaration of dumper_program.
        * server-src/driver.c: declare dumper_program.
-       * server-src/driver.c: call startup_dump_process and 
+       * server-src/driver.c: call startup_dump_process and
        startup_dump_processes with the new dumper_program argument.
 
-1999-02-15  Thomas Hepper <th@ant.han.de>
-
-       * changer-src/scsi-changer-driver.c forget to increment retry
-       in SCSI_* functions
-       * changer-src/chg-scsi.c (clean_tape) added sleep(60) after
-       loading the cleaning tape and before unloading
-
 1999-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/list_dir.h: remove global variable dir_list, declare
 
 1999-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-        * server-src/holding.h: remove declaration of get_letter_from_user()
-        and select_dir().
-        * server-src/holding.c: remove function get_letter_from_user() and
-        select_dir().
-        * server-src/holding.c (pick_datestamp): return empty array instead
-        of calling exit if no directory are found.
-        * server-src/amflush.c (get_letter_from_user): new function copied
-        from holding.c.
-        * server-src/amflush.c (confirm): write a message and exit if no
-        directory were found.
-
-1999-02-14  Thomas Hepper <th@ant.han.de>
-
-       * changer-src/scsi-changer-driver.c New function SCSI_Move
-       removed move in GenericMove, call now SCSI_Move
-       Now check in GenericMove if the move is legal, based on the info
-       from the device capabilities page
-       * changer-src/scsi-linux.c (SCSI_OpenDevice) check if the device
-       is an sg device, or an link to an sg device. If no set SCSI flag to 0
-       Set timeout for SCSI commands, the default will not work if there is an
-       IES on slow changers, if not set high maschine hangs with lot of SCSI  bus
-       resets.....
-
-1999-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
-
-       * server-src/amindexd.c: remove duplication inclusion of version.h.
-       Include tapefile.h to get read_tapelist() prototype.
-       * server-src/amindexd.c (build_disk_table): remove a plethora of
-       unused local vars.
-       * server-src/planner.c: FORCE_FULL command was not cleared.
+       * server-src/holding.h: remove declaration of get_letter_from_user()
+       and select_dir().
+       * server-src/holding.c: remove function get_letter_from_user() and
+       select_dir().
+       * server-src/holding.c (pick_datestamp): return empty array instead
+       of calling exit if no directory are found.
+       * server-src/amflush.c (get_letter_from_user): new function copied
+       from holding.c.
+       * server-src/amflush.c (confirm): write a message and exit if no
+       directory were found.
 
 1999-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 1999-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/holding.h (get_dumpfile): new function
-       * server-src/holding.c (get_dumpfile): new function to fill a
+       * server-src/holding.c (get_dumpfile): new function to fill a 
        dumpfile_t struct from a holding file.
 
 1999-02-14  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/diskfile.h (host_t): new start_t field.
        * server-src/diskfile.c (read_diskline): set start_t to 0.
-       * server-src/driver.c (start_some_dumps): Don't start a dump if 
+       * server-src/driver.c (start_some_dumps): Don't start a dump if
        the host->start_t > now.
-       * server-src/driver.c (start_some_dumps): set host->start_t to 15 sec 
+       * server-src/driver.c (start_some_dumps): set host->start_t to 15 sec
        in the future when starting a FILE_DUMP.
-       * server-src/driver.c (dump_to_tape): set host->start_t to 15 sec in 
+       * server-src/driver.c (dump_to_tape): set host->start_t to 15 sec in
        the future when starting a PORT_DUMP.
 
-1999-02-12  Thomas Hepper <th@ant.han.de>
-       * changer-src/Makefile.am added tape-src to the include list
-       * changer-src/chg-scsi.c removed the changes for not using the
-       statfile.
-       * changer-src/scsi-aix.c Added debug output in SCSI_ExecuteCommand
-       added size parameter to the SCSI_Inquiry call
-       * changer-src/scsi-bsd.c added size parameter to the SCSI_Inquiry call
-       * changer-src/scsi-hpux_new.c same as above 
-       * changer-src/scsi-irix.c same as above
-       * changer-src/scsi-solaris.c same as above
-       * changer-src/scsi-linux swich from ioctl interface to sg interface.
-       Not full tested yet !!
-       * changer-src/scsi-changer-driver.c Added new structs for new devices.
-       complete rewrite of Sense Handling. Removed now unused functions.
-       Added first functions for Barcode reader support.
-       Now use MODE_SENSE to get the number of Drives/Slots/Robots.
-       Split up functions in SCSI functions (prefix SCSI, Generic functions,
-       prefix Generic. Not complete yet). Rewrite of GenericElementStatus
-       * changer-src/scsi-defs.h added new structs, reordered some defines.
-       * changer-src/chg-scsi-chio.c New file(copy of chg-scsi.c). 
-       Too difficult to maintain chg-scsi and chg-scsi-chio from one file
-
 1999-02-10  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * server-src/amlabel.c (main): try to read just-written tape label
        --exclude-from, not --exclude-list
        Reported by Tom Schutter <tom@platte.com>
 
-1999-02-01  Alexandre Oliva  <oliva@dcc.unicamp.br>
-
        * client-src/sendbackup-gnutar.c (re_table): ignore `session request 
        to' message printed by Samba 2.0.0
 
 1999-01-28  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * man/amanda.8.in (comprate): it is not used when there is history
-       information; useful for large disks that compress little
+       information; useful for large disks that compress little
        Reported by job bogan <job@piquin.uchicago.edu>
 
-1999-01-28  Alexandre Oliva  <oliva@dcc.unicamp.br>
-
        * Makefile.am: select which SUBDIRS to descend to here
        * client-src/Makefile.am: removed if WANT_CLIENT
        * tape-src/Makefile.am: removed if WANT_TAPE
 
 1999-01-27  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
-       * NEWS: chg-scsi ports and Samba 2.0.0 support
+       * NEWS: chg-scsi ports, Samba 2.0.0 support and SECURITY API
 
        * configure.in (USE_AMANDAHOSTS): enable by default
        * example/config.site: ditto
        to the output of whoami otherwise
        Reported by Tom Schutter <tom@platte.com>
 
-1999-01-26     Thomas Hepper <th@ant.han.de>   
-       * Makefile.am Added sst driver files to EXTAR_DIST
+1999-01-26  Thomas Hepper <th@ant.han.de>
+       * Makefile.am Added sst driver files to EXTRA_DIST
 
 1999-01-26     Thomas Hepper <th@ant.han.de>   
+       * changer-src/Makefile.am added to LDADD 
+       ../tape-src/libamtape.$(LIB_EXTENSION)
        * changer-src/chg-scsi.c If statfile is not set try to get the info
        about the current loaded tape direct from the changer.
        Fixed debug output for the eject value if > 1
 
 1999-01-22  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
-       * configure.in: require autoconf 2.12.2
+       * common-src/bsd-security.c (check_user): there was no uid variable
+       here; replace with getuid()
 
-       * changer-src/Makefile.am (LDADD): add libamtape, because
-       tapefd_rdlabel() is used in scsi-changer-driver.c
+1999-01-22  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * server-src/planner.c (output_scheduleline): removed `or historical
        data' from `no estimate' message; historical data doesn't matter any 
        instead of /dev/null if we run in background.
        * server-src/amcleanup.sh.in: rename $logdir/amflush.
 
+1999-01-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (make_tapeheader): explicitly compare
+       srvcompress against srvcomp_none instead of assuming that
+       srvcomp_none's value is 0.
+
+1999-01-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c: move max() macro to top of file.  Add min()
+       * server-src/dumper.c (databuf_write): use min() to determine the
+       copy size
+       * server-src/dumper.c (databuf_flush): more clearly calculate the
+       buffer offset in the write loop
+
+1999-01-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (databuf_write): Egads!  Also increment the
+       source pointer doing a partial buf copy
+
+1999-01-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (check_user): use getpwnam(CLIENT_LOGIN)
+       instead of getpwuid(getuid()), in case our caller has not done
+       the setuid().
+
+1999-01-12  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (add_msg_data): properly check for half-sent
+       msg lines.
+
 1999-01-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/amstatus.pl.in: fix a divide by zero error.
 
-1999-01-10  Thomas Hepper <th@ant.han.de>
-        * rewite of the scsi-changer-driver.c and the os depnedent
-          parts. Removed one layer of functions (Move, Eject, Clean ...)
+1999-01-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (add_msg_data): clarify and comment.  Remove
+       'len' arg.  Const 'str' arg.
+       * server-src/dumper.c (do_dump): compresspid and indexpid should
+       be pid_t's.  Also, remove len from add_msg_data call.
+
+1999-01-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/fileheader.c (parse_file_header): const the buffer
+       argument
+       * server-src/fileheader.h: update parse_file_header proto for const
+       change
 
 1999-01-05  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        reusable
        * man/amlabel.8.in: document that tapes are added to tapelist
 
+1998-12-19  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (runcompress): new function.  Given an output
+       file descriptor, inserts a gzip/compress in front of that descriptor.
+       * server-src/dumper.c (do_dump): if srvcompress is true, insert
+       the gzip (using runcompress) in front of the output fd instead
+       of the input fd.  Only do this after the tapeheader has been written.
+
+1998-12-19  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (startup_chunker): new function.  When doing
+       chunking, fork a piped subprocess that reads in a fileheader and
+       a data stream, and writes out the headered, chunked files.  This
+       allows us to treat unchunked, chunked, and port-dump dumps exactly
+       the same.
+       * server-src/dumper.c (main): file-dump: if chunksize > 0,
+       call startup_chunker for our outfd.  Otherwise, open the
+       holding file directly.
+
+1998-12-19  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (struct databuf): add a chunk_size member,
+       the size of each chunk.  Remove chunksize global.
+       * server-src/dumper.c (main): add a chunksize local var
+       * server-src/dumper.c (databuf_init): init the chunk_size member
+       with the same value as split_size
+       * server-src/dumper.c (databuf_flush): increment db->split_size
+       by the amount in db->chunk_size instead of the global chunksize
+
 1998-12-19  John R. Jackson  <jrj@purdue.edu>
 
        * server-src/amstatus.pl.in: instead of just displaying why no
        taper and each dumper is busy, how much time N dumpers are busy
        and why no dumpers were busy.
 
+1998-12-18  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (struct databuf): add 'filename', 'filename_seq',
+       and 'split_size' members to replace the equivalent globals.  Nuke
+       those globals.
+       * server-src/dumper.c (databuf_init): add 'filename' and 'split_size'
+       args to init those members.  Init filename_seq to 0.
+       * server-src/dumper.c (main): declare and init the databuf here
+       * server-src/dumper.c (databuf_flush): refer to split_size, filename,
+       and filename_seq in the databuf instead of the globals.
+       * server-src/dumper.c (do_dump): now takes a databuf instead of an
+       output file descriptor.
+
 1998-12-18  John R. Jackson  <jrj@purdue.edu>
 
        * server-src/amstatus.pl.in: fix two perl warnings.
        after the dumpers since it writes more information to the amdump
        file (helps prevent mixed messages).
 
+1998-12-17  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (databuf_flush): return 0 on success
+
+1998-12-17  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (databuf_flush): new function.  Writes
+       the contents of the databuf out to its backing file, doing splitting
+       if necessary
+       * server-src/dumper.c (databuf_write): call databuf_flush when the
+       databuf fills up.  Fully complete all writes (no short writes)
+       * server-src/dumper.c (do_dump): databuf_write now guarantees complete
+       writes, so remove retry loop.  Call databuf_flush() when eof is hit.
+       Do not close datafd on eof, because our caller (main) passed it to
+       us and therefore owns it (and main does close it again).
+
+1998-12-17  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (databuf_init): new function, initializes
+       a struct databuf.
+       * server-src/dumper.c (update_dataptr): rename to databuf_write,
+       and have it take a buffer and a size, and return how many bytes
+       of the buffer were written
+       * server-src/dumper.c (do_dump): use databuf_init to initialize db.
+       Use databuf_write to add incomign data to the databuf.
+       Make size1 and size2 local to the blocks they are used in.
+
 1998-12-17  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * common-src/Makefile.am (noinst_DATA): removed; bogus
        * docs/INSTALL: fixed URL to gnuplot; recommend autoconf and
        automake from CVS
 
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/genversion.c (main): rip out krb4 defines.  If we
+       need this info, each driver will have to do it individually.
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/conffile.c: remove KRB4_AUTH, BSD_AUTH tokens, auth
+       element from dumptype_t, and get_auth() lookup func.  Add
+       security_driver to dumptype_t and parse value of AUTH keyword
+       as a string.
+       * server-src/conffile.h: nuke auth_t.  Remove auth_t auth, int s_auth
+       from typetype_t; add char *security_driver, int s_security_driver.
+       * server-src/diskfile.c: nuke auth_t auth from disk_t, add
+       char *security_driver.  Inherit security_driver from the dumptype_t
+       for this disk.
+       * server-src/diskfile.h: ditto
+       * server-src/amadmin.c (disklist_one): output the security-driver
+       string in place of the auth type
+       * server-src/amcheck.c (start_client_checks, handle_response):
+       enum type hostp->disks->auth is gone.  check the string in the
+       security_driver for this disk for krb4 auth.
+       * server-src/planner.c (getsize, handle_result): check the string
+       in hostp->disks->security_driver for the auth type.
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/amindexd.c: no need to include protocol.h
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/amindexd.c: remove duplication inclusion of version.h.
+       Include tapefile.h to get read_tapelist() prototype
+       * server-src/amindexd.c (build_disk_table): remove a plethora of
+       unused local vars
+       * server-src/amindexd.c (main): rename security_ok() call to
+       check_security(), and define check_security() locally.  security_ok
+       will disappear when the new security api goes in
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/changer.c (changer_label): make it return void
+       to keep gcc warning about control reaching the end of a nonvoid
+       function.
+       * server-src/changer.c: update changer_label's proto for previous
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: define SET, CLR, ISSET macros for dealing
+       with bitmasks
+       * server-src/amadmin.c: use the bitmask macros for setting
+       and clearing the bits in the infofile command word
+       * server-src/planner.c: ditto.  This fixes a bug in the code that
+       tried to clear FORCE_FULL with an xor expression that was
+       never assigned (x ^ FORCE_FULL)
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (bsd_sendpkt): cast uid's to long and
+       use %ld to print them.
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/dgram.h: mark dgram_cat with gcc's printf attribute
+       * common-src/packet.h: ditto for pkt_cat
+       * common-src/security.h: likewise for security_seterror
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/error.c (error): const the format arg
+       * common-src/amanda.h: mark error with gcc's noreturn attribute, and
+       const its format arg
+
+1998-12-14  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/debug.c (debug_printf): const the format arg
+       * common-src/amanda.h: const debug_printf's format arg
+
 1998-12-14  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * configure.in (BSD SCSI): test ... -a ... is not portable, and less 
        * common-src/amflock.c (main): remove call set_pname() for
        CONFIGURE_TEST since error.o is not linked in.
 
+1998-12-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (struct databuf): add a fd member - the file
+       descriptor that we are buffering
+       * server-src/dumper.c (update_dataptr): remove
+       outf arguments, use the fd in the passed databuf.  Return 0 on
+       success, and -1 on error.
+       * server-src/dumper.c (update_dataptr): rework and comment the
+       chunk code a bit.  Get rid of the cont_filename global.
+       * server-src/dumper.c (do_dump): init the fd member of the databuf
+       * server-src/dumper.c (write_dataptr): fold back into update_dataptr
+
 1998-12-10  John R. Jackson  <jrj@purdue.edu>
 
        * common-src/amflock.c (main): report CONFIGURE_TEST error messages to
        * common-src/amflock.c (main): call set_pname() for CONFIGURE_TEST.
        * configure.in: do not set up pname global for lnlock CONFIGURE_TEST.
 
+1998-12-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (update_dataptr): remove pointless backups
+       of the databuf and associated vars when creating next chunk.
+       Remove duplicate setting of file.cont_filename.
+
+1998-12-10  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (main): reuse outfd to clear the open files
+       passed to us.  Nuke the fd var.
+       * server-src/dumper.c (update_dataptr): nuke 'split' argument - it
+       was always set to 1
+
+1998-12-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (write_tapeheader): kill dead code
+       * server-src/dumper.c (main): remove useless amfree of datestamp.
+       Add missing break to 'default' case in command loop.
+       * server-src/dumper.c: kill databuf, spaceleft, and dataptr globals.
+       Create a 'struct databuf' that holds all three.
+       * server-src/dumper.c (write_dataptr, update_dataptr): make
+       these take a 'struct databuf *' as an argument, and have them
+       operate on its contents instead of the aforementioned globals
+       * server-src/dumper.c (do_dump): declare a 'struct databuf' here.
+       Make it static, because it's large.  Use it instead of the
+       globals.
+
+1998-12-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (main): rework the command loop a bit.
+       Consolidate all duplicated error cleanup into one place at the
+       end of the loop after each command has been processed.  Exit
+       with exit(), not return.
+
+1998-12-09  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/dumper.c (main, getcmd, write_dataptr): kill argc and
+       argv globals, pass them as arguments to getcmd() via struct cmdargs.
+       * server-src/dumper.c (getcmd): make the command lookup table driven.
+       * server-src/dumper.c (write_dataptr): restructure the command
+       logic a bit to hopefully clarify things.
+
 1998-12-09  Henning P. Schmiedehausen  <henning@tanstaafl.de>
 
        * client-src/sendbackup.c (parse_options): Added check whether the
-       pathname of the exclude file is relative and if yes, use the
-       mountpoint of the filesystem as anchor.  So you can put your exclude
-       file in the root of the filesystem to backup.
+       pathname of the exclude file is relative and if yes, use the
+       mountpoint of the filesystem as anchor.  So you can put your exclude
+       file in the root of the filesystem to backup.
        * client-src/sendsize.c (getsize_gnutar): added the same check as
-       above so sendsize uses the same exclude file.
+       above so sendsize uses the same exclude file.
 
 1998-12-09  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/dumper.c (update_dataptr): open .tmp for new chunk.
        * server-src/amstatus.pl.in (dump_size): return size of .tmp file.
 
+1998-12-07  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/amtape.c (main, usage): make command lookup and usage
+       table-driven
+
+1998-12-07  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/amadmin.c: make command lookup and usage table-driven
+       * server-src/amadmin.c (balance, tape, bumpsize): add
+       argc/argv arguments to make them like the rest
+       * server-src/amadmin.c (show_version): new function, implements
+       the version command, so it is done like the other commands
+       * server-src/amadmin.c (main): iterate through cmdtab[] when
+       looking up the command, instead of a huge if/then/else
+       * server-src/amadmin.c (usage): iterate through cmdtab[] when
+       displaying usage strings.  Display the "disklist" usage string.
+
 1998-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * NEWS: document new force-bump, force-no-bump and unforce-bump 
+       * config/acconfig.h: add "#undef HAVE_WRITEV_DECL".
+
+1998-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
+
+       * NEWS: document new force-bump, force-no-bump and unforce-bump
        command in amadmin.
 
 1998-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * server-src/holding.c (size_holding_files): new function to
        return the sum of the size of all chunk of an image.
        * server-src/holding.h (size_holding_files): declare.
-       * server-src/driver.c (adjust_diskspace): use size_holding_files 
+       * server-src/driver.c (adjust_diskspace): use size_holding_files
        instead of doing a stat of only the first chunk.
 
 1998-12-07  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
        * docs/FAQ (large filesystems): fixed reference to results missing
        (results missing): updated to 64Kb UDP packets
 
+1998-12-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: implement WIFSIGNALED() if not already
+       defined
+       * server-src/amcheck.c: ream out compat definitions of WEXITSTATUS(),
+       WTERMSIG(), and WIFSIGNALED().  These are already handled in amanda.h
+       * server-src/changer.c: ditto
+
+1998-12-03  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (recv_security_ok): only check for
+       a reserved port for REQ packets
+
+1998-12-03  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (recvpkt_callback): only compare
+       the sin_addr and sin_port fields in the sockaddr when determining
+       what handle an incoming packet belongs to.
+       * common-src/bsd-security.c (pkthdr2str): use %s for the handle,
+       since it's a string.
+
+1998-12-03  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (bsd_sendpkt): newline-terminate
+       the 'SECURITY USER' line in the packet
+       * common-src/bsd-security.c (check_user): fix many bugs
+       in the USE_AMANDAHOSTS case
+
+1998-12-03  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: AC_REPLACE_FUNCS(writev)
+
 1998-12-02  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/infofile.h: rename PLANNER_FORCE to FORCE_FULL
        * server-src/planner.c: rename PLANNER_FORCE to FORCE_FULL
        * server-src/amadmin.c: rename PLANNER_FORCE to FORCE_FULL
 
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * config/acconfig.h: add KRB5_SECURITY.  Update comment above
+       krb4 define to make clear that they are for krb4
+
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: if we're doing krb4 and -lcom_err is there, pull
+       it in
+       * configure.in: implement --with-krb5-security.
+
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/dgram.c (dgram_cat): now can take printf-style
+       arguments
+       * common-src/dgram.g (dgram_cat): update prototype
+
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c: wrap entire file in #ifdef BSD_SECURITY
+       * common-src/bsd-security.c (bsd_connect): catch up with
+       security interface changes - upper layer now allocates our handle
+       Also, pass up useful error message about why connects failed
+       via the handle we are given
+       * common-src/bsd-security.c (gethandle): rename to inithandle,
+       since we are now passed the handle's memory.  No need to allocate
+       memory or initialize the error msg pointer
+       * common-src/bsd-security.c (bsd_close): now an empty function - no
+       memory to free
+       * common-src/bsd-security.c (recvpkt_callback): allocate the handle
+       before calling inithandle() (nee gethandle()).
+       * common-src/bsd-security.c (stream_read_callback): put
+       strerror(errno) in the handle's error buffer before passing a
+       read error up to the caller
+
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/krb5-security.c: new stub file that pulls in the
+       krb5 bits from the amanda-krb-2 tree if KRB5_SECURITY is
+       defined
+
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/base64.{c,h}: new files, implement base64 encoding
+       and decoding.  Implementation based on routines in bind, and so
+       copyright is held by ISC and IBM (but is BSD-like).
+
+1998-12-02  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/security.h: add 'handlesize' to the driver struct, also
+       make the connect function pointer return int and take a handle
+       argument
+       * common-src/security.h (security_connect): addd a 'const char **'
+       errmsg argument for returning connect errors
+
 1998-12-01  John R. Jackson  <jrj@purdue.edu>
 
        * server-src/amcheck.c: make -t mean do the tape checks, add new -l
        * man/amcheck.8.in: document above changes and clean up some minor
        formatting issues.
 
+1998-12-01  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (release): nuke bogus comment about signal
+       handler release
+       * common-src/event.c (event_loop): move the reentrancy assert
+       after the empty queue check.  Otherwise, calling event_loop()
+       with an empty event queue would cause the entry count to get
+       out of sync.  Also, on exit, assert that the entry count has
+       gone to 0
+       * common-src/event.c (event_loop): fix bogus comment about event
+       removal
+
+1998-12-01  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/arglist.h: implement arglist_function3()
+
 1998-11-30  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/driver.c (start_some_dumps): In degraded mode,
        as command.
        * server-src/amadmin.c (force_one,unforce_one,info_one): work
        with info.command with bit operator.
-       * server-src/planner.c (setup_estimate): work with info.command 
+       * server-src/planner.c (setup_estimate): work with info.command
        with bit operator, support for FORCE_BUMP and FORCE_NO_BUMP command.
 
 1998-11-27  Thomas Hepper    <th@icem.de>
        * server-src/amadmin.c(import_one): import the last_level and
        consecutive_runs field.
 
+1998-11-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: uhh, every other decl has a leading
+       'extern' so writev() should as well
+
+1998-11-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: if no writev() decl exists, declare one
+
+1998-11-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * configure.in: check for <sys/uio.h>, check for a writev() decl
+       in <unistd.h> and/or <sys/uio.h>
+
+1998-11-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/writev.c (writev): new file, implements writev for
+       systems that lack it
+
+1998-11-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/amanda.h: include <sys/uio.h> if it exists.  Otherwise,
+       define struct iovec
+
 1998-11-24  John R. Jackson  <jrj@purdue.edu>
 
        * server-src/amlabel.c: insist on being run as the dump user (ala
        consistency cleanup in the messages.
        * man/amcheck.8.in: document the changes.
 
+1998-11-24  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/dgram.c (dgram_bind): always try to get a reserved
+       port, even if KRB4_SECURITY is defined
+
+1998-11-23  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (struct bsd_handle): change 'int handle'
+       to 'char proto_handle[32]' because the remote client might generate
+       handles that aren't completely numerical
+       * common-src/bsd-security.c (gethandle, str2pkthdr): the 'handle' arg
+       is now a string
+       * common-src/bsd-security.c (bsd_connect): convert our generated
+       handle into a string to pass to gethandle()
+       * common-src/bsd-security.c (str2pkthdr): rewrite to parse with
+       strtok().  Parse the handle as a string instead of trying to
+       convert it into a number
+
 1998-11-20  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * server-src/amcleanup.sh.in (logdir/amdump): arrange that it is
        renamed if it exists, even if no log file could be found.
 
-1998-11-19  Alexandre Oliva  <oliva@dcc.unicamp.br>
+1998-11-20  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c: define STREAM_BUFSIZE to be
+       the size of the tcp socket buffers
+       * common-src/bsd-security.c (bsd_stream_server, bsd_stream_client):
+       adapt to the stream_server() interface changes.  Set socket
+       buffers to STREAM_BUFSIZE.
+
+1998-11-20  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * config/ltmain.sh, config/ltconfig, config/libtool/libtool.m4:
        updated to current CVS libtool
        * man/amanda.8.in: add some chunksize comments and clean up a few
        minor odds and ends.
 
+1998-11-19  Mike Grupenhoff <kashmir@munge.com>
+
+       Give amrecover its own security bits.  It has different needs
+       and a different protocol than the rest of amanda, so it shouldn't
+       try to reuse the security bits
+       * recover-src/amrecover.c (get_security): new function, implements
+       bsd security
+       * recover-src/amrecover.c (main): call get_security()
+       * recover-src/amrecover.h: get_security() prototype
+       * recover-src/extract_list.c (extract_files_setup): call
+       get_security()
+       * restore-src/amidxtaped.c (check_security): new function, implements
+       * restore-src/amidxtaped.c (main): call check_security()
+
+1998-11-19  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/stream.c (stream_server, stream_client): cast 4th
+       arg of setsockopt() to (void *) to quash a compiler warning
+       under solaris.
+
 1998-11-19  John R. Jackson  <jrj@purdue.edu>
 
        * recover-src/amrecover.c (main): use set_host to find the initial
 1998-11-17  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * example/amanda.conf.in: document that infofile is supposed to be a
-       directory with the default database format
+       directory with the default database format
        * docs/FAQ: New questions: `infofile update failed' and `using the
-       same host in different configurations'
+       same host in different configurations'
 
 1998-11-17  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * changer-src/scis-linux.c: Add additional param to Tape_Ready
        * changer-src/scsi-solaris.c: same as scsi-hpux_new.c
 
+1998-11-11  Mike Grupenhoff <kashmir@munge.com>
+
+       * server-src/security.h: add driver entry points and macros
+       for security_stream_accept() and security_stream_auth()
+       * server-src/bsd-security.c: implement security_stream_accept()
+       and security_stream_auth() for bsd security
+
 1998-11-11  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
        * server-src/driver.c (main): redo my patch about total_disksize that
 
 1998-11-09  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
-       * server-src/infofile.h (struct info_s): add last_level and
+       * server-src/infofile.h (struct info_s): add last_level and 
        consecutive_runs.
        * server-src/infofile.c: support new last_level and consecutive_runs
        * server-src/planner.c (last_level): return ip->last_level.
        * server-src/planner.c (runs_at): return ip->consecutive_runs.
        * server-src/driverio.c (update_info_dumper): update inf.last_level
        and inf.consecutive_runs.
+       
+1998-11-09  Mike Grupenhoff <kashmir@munge.com>
 
-1998-11-09  Mike Grupenhoff <kashmir@munge.com> 
        * client-src/sendbackup-dump.c (start_backup): don't close indexf
        if it was never open
        * client-src/sendbackup-gnutar.c (start_backup): ditto
 
 1998-11-07  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
+       * Makefile.am (EXTRA_DIST): added EVENT-API, SECURITY-API and
+       STRATEGY-API
+       * docs/STRATEGY-API: new file
+
        * configure.in (GNUTAR): accept tar from Free paxutils, the new name
        of GNU tar
 
 
        * changer-src/scsi-solaris.c: added missing #endif
 
-       * configure.in: merge with camlib.h patch from Oct 31.
+       * configure.in: merge with camlib.h patch from Oct 31
        remove all uses of test ... -a ...; this is not portable.
        (AC_CHECK_HEADERS) added header files for Linux and Solaris
 
        * changer-src/Makefile.am: New conditional for building chg-scsi-chio
        and chg-scsi. chg-scsi-chio is the old chg-scsi
 
-1998-11-05  John R. Jackson  <jrj@purdue.edu>
+1998-11-06  Mike Grupenhoff <kashmir@munge.com>
 
-       * server-src/amverify.sh.in: tolerate extra amtape output.
+       * common-src/bsd-security.c (bsd_stream_write): callback's third
+       arg should now be an int.
+       * common-src/bsd-security.c: quash some gcc -Wall warnings
+
+1998-11-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/security.h: the callback to stream_read should
+       take signed type as its 'length' argument so errors can be
+       expressed as a negative number.
+
+1998-11-06  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c (stream_read_callback): do reads into
+       a buffer of size TAPE_BLOCK_BYTES, instead of 256, and place the
+       buffer in the stream handle instead of on the stack, since it's
+       huge
+
+1998-11-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (event_loop): Consider error conditions on
+       file descriptors as read or write events.  The caller will be
+       able to differentiate when they call read or write and it
+       fails.
+
+1998-11-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (event_loop): print out WHY select failed
+
+1998-11-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c: adjust for the recvpkt timeout
+       interface changes
+       * common-src/bsd-security.c (handleq_remove): add a missing ; after
+       an assertion
+       * common-src/bsd-security.c (gethandle): initialize the error buffer
+       in the security handle, since errors may be set before the handle
+       is passed up to the general security layer
+       * common-src/bsd-security.c (bsd_recvpkt_cancel): allow it to be
+       called several times, or when no recvpkt was scheduled
+
+1998-11-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/security.h: define security_recvpkt_status_t
+       * common-src/security.h: security_driver_t->recvpkt() now
+       takes a timeout argument, and its callback takes a
+       security_recvpkt_status_t
+       * common-src/security.h: adjust the security_recvpkt() macro
+       for the above changes
+
+1998-11-05  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (event_loop): assert that we are not firing
+       a dead event
 
 1998-11-05  Jean-Louis Martineau <martineau@IRO.UMontreal.CA>
 
 
        * server-src/amstatus.pl.in: remove warning.
 
+1998-11-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c (event_register): delete some improper debug
+       code that shouldn't have made it in
+
+1998-11-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/bsd-security.c: new file: security driver that
+       implements "BSD" security.
+
+1998-11-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/security.h: new file: the security api header
+
+1998-11-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/event.c: new file: the event handler.  Handles file
+       descriptor io, signals, and timed events.
+       * common-src/event.h: new file: interface for the event handler.
+
+1998-11-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/packet.c: new file: description of pkt_t's and routines
+       for formatting
+       * common-src/packet.h: new file: header for common-src/packet.c
+
+1998-11-04  Mike Grupenhoff <kashmir@munge.com>
+
+       * common-src/queue.h: new file: the 4.4BSD queue macros, with
+       additions from NetBSD
+
+1998-11-04  John R. Jackson  <jrj@purdue.edu>
+
+       * server-src/amverify.sh.in: tolerate extra amtape output.
+
 1998-11-04  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
+       * configure.in: bumped to 2.5.0
+
        * server-src/taper.c (read_file): if a new tape cannot be found,
        report a no-tape error to the log file and exit, just like it does
        for the first tape
index 360006876f4c5faca167e6ea5732fa817abd2e1c..9ebd7062a56828e0e9ca92e4c5f146cd1840f91e 100644 (file)
@@ -7,7 +7,7 @@ LIBTOOL_M4I = $(srcdir)/config/libtool.m4i
 ACINCLUDE_M4_DEPS = $(ACINCLUDE_M4I) $(LIBTOOL_M4I)
 
 if WANT_CLIENT
-CLIENT_SUBDIRS = client-src
+CLIENT_SUBDIRS = client-src dumper-src
 endif
 if WANT_TAPE
 TAPE_SUBDIRS = tape-src
@@ -28,8 +28,8 @@ endif
 SUBDIRS = \
        config \
        common-src \
-       $(CLIENT_SUBDIRS) \
        $(TAPE_SUBDIRS) \
+       $(CLIENT_SUBDIRS) \
        $(SERVER_SUBDIRS) \
        $(RESTORE_SUBDIRS) \
        $(RECOVER_SUBDIRS) \
@@ -43,6 +43,7 @@ pkgdata_DATA = \
 
 EXTRA_DIST = $(SNAPSHOT_STAMP) \
        $(pkgdata_DATA)                 \
+        autogen                        \
        contrib/README                  \
        contrib/dbbackup.README         \
        contrib/dbbackup.ksh            \
@@ -57,6 +58,15 @@ EXTRA_DIST = $(SNAPSHOT_STAMP) \
        contrib/sst/sst.conf            \
        contrib/sst/sst_def.h           \
        contrib/sst/sstest.c            \
+       contrib/gsc/README              \
+       contrib/gsc/cfggsc.c            \
+       contrib/gsc/defgsc.c            \
+       contrib/gsc/gsc.add             \
+       contrib/gsc/gscdd.c             \
+       contrib/gsc/gscdds.h            \
+       contrib/gsc/makefile            \
+       contrib/gsc/tstinq.c            \
+       contrib/gsc/ucfggsc.c           \
        patches/regex-3.6alpha.patch    \
        patches/samba-largefs.patch     \
        patches/tar-1.12.patch          \
index bf280cf8be1399009ebfbaa901d55011500c54cc..995ad39ec6ac1a303814eeac6c4a54e24e4656a0 100644 (file)
@@ -70,8 +70,9 @@ pkgdataDATA_INSTALL = $(INSTALL_DATA)
 DATA = $(pkgdata_DATA)
 ETAGS = etags
 CTAGS = ctags
-DIST_SUBDIRS = config common-src client-src tape-src server-src \
-       changer-src restore-src recover-src amplot man docs example
+DIST_SUBDIRS = config common-src tape-src client-src dumper-src \
+       server-src changer-src restore-src recover-src amplot man docs \
+       example
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -130,7 +131,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -142,9 +145,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -157,6 +163,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -219,10 +226,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -278,7 +288,7 @@ ACINCLUDE_M4 = $(srcdir)/acinclude.m4
 ACINCLUDE_M4I = $(srcdir)/config/acinclude.m4i
 LIBTOOL_M4I = $(srcdir)/config/libtool.m4i
 ACINCLUDE_M4_DEPS = $(ACINCLUDE_M4I) $(LIBTOOL_M4I)
-@WANT_CLIENT_TRUE@CLIENT_SUBDIRS = client-src
+@WANT_CLIENT_TRUE@CLIENT_SUBDIRS = client-src dumper-src
 @WANT_TAPE_TRUE@TAPE_SUBDIRS = tape-src
 @WANT_SERVER_TRUE@SERVER_SUBDIRS = server-src changer-src
 @WANT_RESTORE_TRUE@RESTORE_SUBDIRS = restore-src
@@ -288,8 +298,8 @@ ACINCLUDE_M4_DEPS = $(ACINCLUDE_M4I) $(LIBTOOL_M4I)
 SUBDIRS = \
        config \
        common-src \
-       $(CLIENT_SUBDIRS) \
        $(TAPE_SUBDIRS) \
+       $(CLIENT_SUBDIRS) \
        $(SERVER_SUBDIRS) \
        $(RESTORE_SUBDIRS) \
        $(RECOVER_SUBDIRS) \
@@ -303,6 +313,7 @@ pkgdata_DATA = \
 
 EXTRA_DIST = $(SNAPSHOT_STAMP) \
        $(pkgdata_DATA)                 \
+        autogen                        \
        contrib/README                  \
        contrib/dbbackup.README         \
        contrib/dbbackup.ksh            \
@@ -317,6 +328,15 @@ EXTRA_DIST = $(SNAPSHOT_STAMP) \
        contrib/sst/sst.conf            \
        contrib/sst/sst_def.h           \
        contrib/sst/sstest.c            \
+       contrib/gsc/README              \
+       contrib/gsc/cfggsc.c            \
+       contrib/gsc/defgsc.c            \
+       contrib/gsc/gsc.add             \
+       contrib/gsc/gscdd.c             \
+       contrib/gsc/gscdds.h            \
+       contrib/gsc/makefile            \
+       contrib/gsc/tstinq.c            \
+       contrib/gsc/ucfggsc.c           \
        patches/regex-3.6alpha.patch    \
        patches/samba-largefs.patch     \
        patches/tar-1.12.patch          \
@@ -544,7 +564,7 @@ distclean-tags:
 distdir: $(DISTFILES)
        $(am__remove_distdir)
        mkdir $(distdir)
-       $(mkdir_p) $(distdir)/amplot $(distdir)/changer-src $(distdir)/client-src $(distdir)/common-src $(distdir)/contrib $(distdir)/contrib/sst $(distdir)/example $(distdir)/patches $(distdir)/regex-src $(distdir)/regex-src/fake $(distdir)/server-src
+       $(mkdir_p) $(distdir)/amplot $(distdir)/changer-src $(distdir)/client-src $(distdir)/common-src $(distdir)/contrib $(distdir)/contrib/gsc $(distdir)/contrib/sst $(distdir)/dumper-src $(distdir)/example $(distdir)/patches $(distdir)/regex-src $(distdir)/regex-src/fake $(distdir)/server-src
        @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
        topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
        list='$(DISTFILES)'; for file in $$list; do \
diff --git a/NEWS b/NEWS
index 62afb4572afce0037f035e9a57796c1d33cc1695..c5b65a9cc4d240c269256ec72b1053669dbfd86e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,18 @@
+Changes in release 2.5.0
+
+* Communication security/authentication: Kerberos 4/5, OpenSSH
+* Data security: Symmetric/Assymetric encrytion algorithms (aesutil
+  and gpg encryption),  Encryption can be done on server or client,
+  Custom encryption utilities can be used.
+* Compression: Ability to add custom compression tools. This is a
+  really useful feature especially since it can specified for a DLE.  You
+  can use different compression algorithm for images, binaries, ascii files
+  and so on.
+* Dump images spanning multiple media volumes - Dump images are no
+  longer restricted to a single media volume (tape or vtape).  Data restoration
+  can be done using amrecover and amfetchdump commands.
+* Auto tape labelling - This optional feature is good for disk backups.
+
 Change in release 2.4.5p1
 
 * New [--days <num>] argument to 'amadmin <conf> tape'.
@@ -119,13 +134,9 @@ Changes in release 2.4.3b1
 * new autoflush option.
 * new dumperstr option to specify the priority order of each dumper.
 
-Changes in release 2.4.2p2
+Changes in release 2.4.2
 
-* Mostly bug fixes.
 * Samba passwords are now sent to smbclient via a pipe and never displayed.
-* Amrecover should now work with xfsrestore.
-* Amrecover no longer binds an incorrect port that resulted in connection
-  failures on some systems.
 * Debug files in /tmp/amanda (--with-debug-dir) are now timestamped and old
   ones automatically cleaned out.  This means more space (a few KBytes) will
   be used since in a given run, several of the programs are called more than
@@ -133,16 +144,6 @@ Changes in release 2.4.2p2
   be lost by the file being overwritten.  The length of time to keep the
   files is controlled by --with-debug-days (default: 4).  The old flag
   --with-pid-debug-files is no longer needed and is ignored.
-* updated chg-zd-mtx.sh.in changer.
-
-Changes in release 2.4.2p1
-
-* Bugs fix release, the most annoying one is that amanda could retry
-  the same filesystem indefinitely if it is larger than the holding
-  disk but the estimate was smaller.
-
-Changes in release 2.4.2
-
 * dumptypes can be specialized in the disklist file
 * Amanda will never use more space than specified (use) for an holding
   disk
@@ -158,7 +159,7 @@ Changes in release 2.4.2
 * new force-bump, force-no-bump and unforce-bump command in amadmin.
 * Increased the maximum number of filesystems that can be backed up
   from a single host, by increasing the maximum UDP request packet
-  size
+  size.
 * A new `dtimeout' keyword in amanda.conf to replace the READ_TIMEOUT
   constant in dumper.c.
 * A new `ctimeout' keyword in amanda.conf to replace the CHECK_TIMEOUT
diff --git a/README b/README
index 66237de6c9c8a44214b608d978a0c7bf204381a1..ea01abe945a57bf3a1c6da48eb322c5097925ec2 100644 (file)
--- a/README
+++ b/README
@@ -36,8 +36,11 @@ Here are some features of Amanda:
     the unix command line.
   * supports Kerberos 4 security, including encrypted dumps.  The Kerberos
     support is available as a separate add-on package, see the file
-    KERBEROS.HOW-TO-GET on the ftp site, and the file docs/KERBEROS in this
-    package, for more details.
+    KERBEROS.HOW-TO-GET on the sourceforge site, and the file docs/KERBEROS 
+    in this package, for more details.
+  * Supports secure communication between server and client using OpenSSH.
+  * Can encrypt dumps on Amanda client or on Amanda client using GPG or any
+    encryption program.
   * for a restore, tells you what tapes you need, and finds the proper
     backup image on the tape for you.
   * recovers gracefully from errors, including down or hung machines.
@@ -49,7 +52,7 @@ Here are some features of Amanda:
     send an e-mail report of any problems that could cause the backups to
     fail.
   * can compress dumps before sending or after sending over the net, with
-    either compress or gzip.
+    either compress or gzip or custom program.
   * can optionally synchronize with external backups, for those large
     timesharing computers where you want to do full dumps when the system
     is down in single-user mode (since BSD dump is not reliable on active
@@ -86,8 +89,6 @@ than the holding disk: Amanda will send those dumps directly to tape one at
 a time.  If you have many such dumps you will be limited by the dump speed
 of those machines.
 
-Amanda does not yet support single backup images larger than a tape.
-
 
 WHAT SYSTEMS DOES AMANDA RUN ON?
 --------------------------------
@@ -96,7 +97,7 @@ Amanda should run on any modern Unix system that supports dump or GNU
 tar, has sockets and inetd, and either system V shared memory, or BSD
 mmap implemented.
 
-In particular, Amanda 2.4.1p1 has been compiled, and the client side tested
+In particular, Amanda has been compiled, and the client side tested
 on the following systems:
        AIX 3.2 and 4.1
        BSDI BSD/OS 2.1 and 3.1
@@ -104,6 +105,7 @@ on the following systems:
        FreeBSD 2.2.5
        IRIX 5.2 and 6.3
        GNU/Linux on x86, m68k, alpha, sparc, arm and powerpc
+        Mac OS X 10
        NetBSD 1.0
        Nextstep 3 (*)
        OpenBSD 2.5 x86, sparc, etc (ports available)
@@ -111,22 +113,18 @@ on the following systems:
        Ultrix 4.2
        HP-UX 9.x and 10.x (x >= 01)
 
-The Amanda 2.4.1p1 server side is known to run on all of the other
+The Amanda server side is known to run on all of the other
 machines except on those marked with an asterisk.
 
-If you know of any system that is not listed here on which amanda
-builds successfully, either client&server or client-only, please
-report to amanda-hackers@amanda.org.
-
 
 WHERE DO I GET AMANDA?
 ----------------------
 
-There are several versions of Amanda.  The latest version at the time
-of this writing is available at:
-
-       ftp://ftp.amanda.org/pub/amanda
+Amanda is a sourceforge.net project (http://sourceforge.net/projects/amanda).
+Amanda source tree is available at the sourceforge website.
 
+Most Linux distributions include amanda rpms pre-built for various
+architectures.  
 
 HOW DO I GET AMANDA UP AND RUNNING?
 -----------------------------------
@@ -134,18 +132,21 @@ HOW DO I GET AMANDA UP AND RUNNING?
 Read the file docs/INSTALL.  There are a variety of steps, from compiling
 Amanda to installing it on the tape server host and the client machines.
     docs/INSTALL       contains general installation instructions.
-    docs/SYSTEM.NOTES  contains system-specific information.
-    docs/FAQ            contains answers to frequently asked questions.
-    docs/KERBEROS      explains installation under Kerberos 4.
-    docs/TAPE.CHANGERS explains how to customize the changer interface.
-    docs/WHATS.NEW     details new features.
+    docs/NEWS          details new features in each release.
+
+You can read Amanda documentation at the official project-site
 
+http://www.amanda.org
+
+and at the AMANDA-Wiki at
+
+http://wiki.zmanda.com and
 
 WHO DO I TALK TO IF I HAVE A PROBLEM?
 -------------------------------------
 
-Amanda is completely unsupported and made available as-is.  However,
-you may be able to get useful information in the Amanda mailing lists:
+You can get Amanda help and questions answered from the mailing lists and
+Amanda forums:
 
 ==> To join a mailing list, DO NOT, EVER, send mail to that list.  Send
     mail to <listname>-request@amanda.org, or amanda-lists@amanda.org,
@@ -163,11 +164,9 @@ you may be able to get useful information in the Amanda mailing lists:
 
     amanda-users
         The amanda-users mailing list is for questions and general discussion
-        about the Amanda Network Backup Manager.  This package and related
-        files are available via anonymous FTP from ftp.amanda.org in the
-        pub/amanda directory.  NOTE: the amanda-users list is itself on the
-        amanda-announce distribution, so you only need to subscribe to one of
-        the two lists, not both.
+        about the Amanda Network Backup Manager.  NOTE: the amanda-users list 
+       is itself on the amanda-announce distribution, so you only need to 
+        subscribe to one of the two lists, not both.
        To subscribe, send a message to amanda-users-request@amanda.org.
 
     amanda-hackers
@@ -176,6 +175,7 @@ you may be able to get useful information in the Amanda mailing lists:
         ports, bugs, fixes, and alpha testing of new versions.
        To subscribe, send a message to amanda-hackers-request@amanda.org.
 
+==> Amanda forums: http://forums.zmanda.com
 
 Share and Enjoy,
 The Amanda Development Team
index 90accfde066f0ebab46fd0d000cb7317b3458c67..b55bdb06f702cd7b50058c90657ea8a878b4f554 100644 (file)
@@ -499,9 +499,94 @@ dnl Remember, if the system already had a valid <stdint.h>, the generated
 dnl file will include it directly. No need for fuzzy HAVE_STDINT_H things...
 dnl
 dnl @, (status: used on new platforms) (see http://ac-archive.sf.net/gstdint/)
-dnl @version $Id: acinclude.m4i,v 1.1.2.5.8.3 2004/04/29 20:47:22 martinea Exp $
+dnl @version Id: ax_create_stdint_h.m4,v 1.5 2005/01/06 18:27:27 guidod Exp
 dnl @author  Guido Draheim <guidod@gmx.de> 
 
+AC_DEFUN([AX_CHECK_DATA_MODEL],[
+   AC_CHECK_SIZEOF(char)
+   AC_CHECK_SIZEOF(short)
+   AC_CHECK_SIZEOF(int)
+   AC_CHECK_SIZEOF(long)
+   AC_CHECK_SIZEOF(void*)
+   ac_cv_char_data_model=""
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model=""
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+   AC_MSG_CHECKING([data model])
+   case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+    122/242)     ac_cv_data_model="IP16"  ; n="standard 16bit machine" ;;
+    122/244)     ac_cv_data_model="LP32"  ; n="standard 32bit machine" ;;
+    122/*)       ac_cv_data_model="i16"   ; n="unusual int16 model" ;;
+    124/444)     ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+    124/488)     ac_cv_data_model="LP64"  ; n="standard 64bit unixish" ;;
+    124/448)     ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+    124/*)       ac_cv_data_model="i32"   ; n="unusual int32 model" ;;
+    128/888)     ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+    128/*)       ac_cv_data_model="i64"   ; n="unusual int64 model" ;;         
+    222/*2)      ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+    333/*3)      ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+    444/*4)      ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+    666/*6)      ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+    888/*8)      ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+    222/*|333/*|444/*|666/*|888/*) :
+                 ac_cv_data_model="iDSP"  ; n="unusual dsptype" ;;
+     *)          ac_cv_data_model="none"  ; n="very unusual model" ;;
+   esac
+   AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
+])
+
+dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
+AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
+AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
+ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_uintptr_t 
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+  done
+  AC_MSG_CHECKING([for stdint uintptr_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
+AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
+ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h stdint.h]) ; do
+   unset ac_cv_type_uint32_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint uint32_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
+AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
+ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_u_int32_t
+   unset ac_cv_type_u_int64_t
+   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint u_int32_t])
+ ])
+])
+
 AC_DEFUN([AX_CREATE_STDINT_H],
 [# ------ AX CREATE STDINT H -------------------------------------
 AC_MSG_CHECKING([for stdint types])
@@ -535,94 +620,35 @@ fi
 if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
 
 dnl .....intro message done, now do a few system checks.....
-dnl btw, all CHECK_TYPE macros do automatically "DEFINE" a type, therefore
-dnl we use the autoconf implementation detail _AC CHECK_TYPE_NEW instead
+dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, 
+dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW 
+dnl instead that is triggered with 3 or more arguments (see types.m4)
 
 inttype_headers=`echo $2 | sed -e 's/,/ /g'`
 
 ac_cv_stdint_result="(no helpful system typedefs seen)"
-AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
- ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
-  AC_MSG_RESULT([(..)])
-  for i in stdint.h inttypes.h sys/inttypes.h $inttype_headers ; do
-   unset ac_cv_type_uintptr_t 
-   unset ac_cv_type_uint64_t
-   _AC_CHECK_TYPE_NEW(uintptr_t,[ac_cv_header_stdint_x=$i],dnl
-     continue,[#include <$i>])
-   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
-   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)"
-   break;
-  done
-  AC_MSG_CHECKING([for stdint uintptr_t])
- ])
+AX_CHECK_HEADER_STDINT_X(dnl
+   stdint.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
 
 if test "_$ac_cv_header_stdint_x" = "_" ; then
-AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
- ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
-  AC_MSG_RESULT([(..)])
-  for i in inttypes.h sys/inttypes.h stdint.h $inttype_headers ; do
-   unset ac_cv_type_uint32_t
-   unset ac_cv_type_uint64_t
-   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],dnl
-     continue,[#include <$i>])
-   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
-   ac_cv_stdint_result="(seen uint32_t$and64 in $i)"
-   break;
-  done
-  AC_MSG_CHECKING([for stdint uint32_t])
- ])
+AX_CHECK_HEADER_STDINT_O(dnl,
+   inttypes.h sys/inttypes.h stdint.h $inttype_headers,
+   ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
 fi
 
 if test "_$ac_cv_header_stdint_x" = "_" ; then
 if test "_$ac_cv_header_stdint_o" = "_" ; then
-AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
- ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
-  AC_MSG_RESULT([(..)])
-  for i in sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do
-   unset ac_cv_type_u_int32_t
-   unset ac_cv_type_u_int64_t
-   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],dnl
-     continue,[#include <$i>])
-   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
-   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)"
-   break;
-  done
-  AC_MSG_CHECKING([for stdint u_int32_t])
- ])
+AX_CHECK_HEADER_STDINT_U(dnl,
+   sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
 fi fi
 
 dnl if there was no good C99 header file, do some typedef checks...
 if test "_$ac_cv_header_stdint_x" = "_" ; then
    AC_MSG_CHECKING([for stdint datatype model])
    AC_MSG_RESULT([(..)])
-   AC_CHECK_SIZEOF(char)
-   AC_CHECK_SIZEOF(short)
-   AC_CHECK_SIZEOF(int)
-   AC_CHECK_SIZEOF(long)
-   AC_CHECK_SIZEOF(void*)
-   ac_cv_stdint_char_model=""
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_char"
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_short"
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_int"
-   ac_cv_stdint_long_model=""
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_int"
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_long"
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_voidp"
-   name="$ac_cv_stdint_long_model"
-   case "$ac_cv_stdint_char_model/$ac_cv_stdint_long_model" in
-    122/242)     name="$name,  IP16 (standard 16bit machine)" ;;
-    122/244)     name="$name,  LP32 (standard 32bit mac/win)" ;;
-    122/*)       name="$name        (unusual int16 model)" ;; 
-    124/444)     name="$name, ILP32 (standard 32bit unixish)" ;;
-    124/488)     name="$name,  LP64 (standard 64bit unixish)" ;;
-    124/448)     name="$name, LLP64 (unusual  64bit unixish)" ;;
-    124/*)       name="$name        (unusual int32 model)" ;; 
-    128/888)     name="$name, ILP64 (unusual  64bit numeric)" ;;
-    128/*)       name="$name        (unusual int64 model)" ;; 
-    222/*|444/*) name="$name        (unusual dsptype)" ;;
-     *)          name="$name        (very unusal model)" ;;
-   esac
-   AC_MSG_RESULT([combined for stdint datatype model...  $name])
+   AX_CHECK_DATA_MODEL
 fi
 
 if test "_$ac_cv_header_stdint_x" != "_" ; then
@@ -655,6 +681,7 @@ fi
 AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
 $ac_cv_stdint_result])
 
+dnl -----------------------------------------------------------------
 # ----------------- DONE inttypes.h checks START header -------------
 AC_CONFIG_COMMANDS([$ac_stdint_h],[
 AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
@@ -667,7 +694,10 @@ echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
 echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
 if test "_$ac_cv_header_stdint_t" != "_" ; then 
 echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
-fi
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
 
 cat >>$ac_stdint <<STDINT_EOF
 
@@ -727,9 +757,9 @@ fi
 echo "" >>$ac_stdint
 
 echo "/* which type model has been detected */" >>$ac_stdint
-if test "_$ac_cv_stdint_char_model" != "_" ; then
-echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_stdint_char_model" >>$ac_stdint
-echo "#define   _STDINT_LONG_MODEL" "$ac_cv_stdint_long_model" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define   _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
 else
 echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
 echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
@@ -814,6 +844,7 @@ typedef u_int64_t uint64_t;
 /* .. here are some common heuristics using compiler runtime specifics */
 #if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 
@@ -827,12 +858,14 @@ typedef unsigned __int64 uint64_t;
 /* note: all ELF-systems seem to have loff-support which needs 64-bit */
 #if !defined _NO_LONGLONG
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 #endif
 
 #elif defined __alpha || (defined __mips && defined _ABIN32)
 #if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
 typedef long int64_t;
 typedef unsigned long uint64_t;
 #endif
@@ -918,6 +951,7 @@ typedef          int     int32_t;
 /* assuming the system has a "long long" */
 #ifndef _HAVE_UINT64_T
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef unsigned long long uint64_t;
 typedef          long long  int64_t;
 #endif
@@ -1003,12 +1037,87 @@ typedef           long   intptr_t;
 #endif
 #endif
 
+/* The ISO C99 standard specifies that in C++ implementations these
+   should only be defined if explicitly requested.  */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed.  */
+# define INT8_C(c)      c
+# define INT16_C(c)     c
+# define INT32_C(c)     c
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INT64_C(c)    c ## L
+# else
+#  define INT64_C(c)    c ## LL
+# endif
+
+/* Unsigned.  */
+# define UINT8_C(c)     c ## U
+# define UINT16_C(c)    c ## U
+# define UINT32_C(c)    c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define UINT64_C(c)   c ## UL
+# else
+#  define UINT64_C(c)   c ## ULL
+# endif
+
+/* Maximal type.  */
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INTMAX_C(c)   c ## L
+#  define UINTMAX_C(c)  c ## UL
+# else
+#  define INTMAX_C(c)   c ## LL
+#  define UINTMAX_C(c)  c ## ULL
+# endif
+
+  /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types.  */
+# define INT8_MIN               (-128)
+# define INT16_MIN              (-32767-1)
+# define INT32_MIN              (-2147483647-1)
+# define INT64_MIN              (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types.  */
+# define INT8_MAX               (127)
+# define INT16_MAX              (32767)
+# define INT32_MAX              (2147483647)
+# define INT64_MAX              (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types.  */
+# define UINT8_MAX              (255)
+# define UINT16_MAX             (65535)
+# define UINT32_MAX             (4294967295U)
+# define UINT64_MAX             (__UINT64_C(18446744073709551615))
+
+/* Minimum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MIN         INT8_MIN
+# define INT_LEAST16_MIN        INT16_MIN
+# define INT_LEAST32_MIN        INT32_MIN
+# define INT_LEAST64_MIN        INT64_MIN
+/* Maximum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MAX         INT8_MAX
+# define INT_LEAST16_MAX        INT16_MAX
+# define INT_LEAST32_MAX        INT32_MAX
+# define INT_LEAST64_MAX        INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size.  */
+# define UINT_LEAST8_MAX        UINT8_MAX
+# define UINT_LEAST16_MAX       UINT16_MAX
+# define UINT_LEAST32_MAX       UINT32_MAX
+# define UINT_LEAST64_MAX       UINT64_MAX
+
   /* shortcircuit*/
 #endif
   /* once */
 #endif
 #endif
 STDINT_EOF
+fi
     if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
       AC_MSG_NOTICE([$ac_stdint_h is unchanged])
     else
@@ -1029,8 +1138,8 @@ ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
 ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
 ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
 ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
-ac_cv_stdint_char_model="$ac_cv_stdint_char_model"
-ac_cv_stdint_long_model="$ac_cv_stdint_long_model"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
 ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
 ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
 ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
@@ -1175,7 +1284,7 @@ rm="rm -f"
 default_ofile=libtool
 can_build_shared=yes
 
-# All known linkers require a `.a' archive for static linking (except M$VC,
+# All known linkers require a `.a' archive for static linking (except MSVC,
 # which needs '.lib').
 libext=a
 ltmain="$ac_aux_dir/ltmain.sh"
@@ -1391,8 +1500,8 @@ if test "X${echo_test_string+set}" != Xset; then
 # find a string as large as possible, as long as the shell can cope with it
   for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
     # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
        (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
     then
       break
@@ -1561,7 +1670,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case "`/usr/bin/file conftest.o`" in
+    case `/usr/bin/file conftest.o` in
     *32-bit*)
       case $host in
         x86_64-*linux*)
@@ -1643,7 +1752,7 @@ AC_CACHE_CHECK([$1], [$2],
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
    (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
@@ -1682,7 +1791,7 @@ AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
    LDFLAGS="$LDFLAGS $3"
    printf "$lt_simple_link_test_code" > conftest.$ac_ext
    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
-     # The compiler can only warn and ignore the option if not recognized
+     # The linker can only warn and ignore the option if not recognized
      # So say no if there are warnings
      if test -s conftest.err; then
        # Append any errors to the config.log.
@@ -1757,7 +1866,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
     elif test -x /usr/sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
     else
-      lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
     fi
     # And add a safety zone
     lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
@@ -1769,7 +1878,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
     # nice to cause kernel panics so lets avoid the loop below.
     # First set a reasonable default.
     lt_cv_sys_max_cmd_len=16384
-    # 
+    #
     if test -x /sbin/sysconfig; then
       case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
         *1*) lt_cv_sys_max_cmd_len=-1 ;;
@@ -1886,7 +1995,7 @@ int main ()
 }]
 EOF
   if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) $1 ;;
@@ -2035,7 +2144,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
    (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
@@ -2053,7 +2162,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
        _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
      fi
    fi
-   chmod u+w .
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
    $rm conftest*
    # SGI C++ compiler will create directory out/ii_files/ for
    # template instantiation
@@ -2313,7 +2422,8 @@ cygwin* | mingw* | pw32*)
       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
       dldir=$destdir/`dirname \$dlpath`~
       test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
       dlpath=$dir/\$dldll~
        $rm \$dlpath'
@@ -2366,7 +2476,7 @@ darwin* | rhapsody*)
   soname_spec='${libname}${release}${major}$shared_ext'
   shlibpath_overrides_runpath=yes
   shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
   # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
   if test "$GCC" = yes; then
     sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
@@ -2404,7 +2514,14 @@ kfreebsd*-gnu)
 freebsd* | dragonfly*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
   version_type=freebsd-$objformat
   case $version_type in
     freebsd-elf*)
@@ -2449,7 +2566,7 @@ hpux9* | hpux10* | hpux11*)
   version_type=sunos
   need_lib_prefix=no
   need_version=no
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     shrext_cmds='.so'
     hardcode_into_libs=yes
@@ -2546,27 +2663,10 @@ linux*)
   # before this can be enabled.
   hardcode_into_libs=yes
 
-  # find out which ABI we are using
-  libsuff=
-  case "$host_cpu" in
-  x86_64*|s390x*|powerpc64*)
-    echo '[#]line __oline__ "configure"' > conftest.$ac_ext
-    if AC_TRY_EVAL(ac_compile); then
-      case `/usr/bin/file conftest.$ac_objext` in
-      *64-bit*)
-        libsuff=64
-        sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
-        ;;
-      esac
-    fi
-    rm -rf conftest*
-    ;;
-  esac
-
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,   ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -2628,7 +2728,11 @@ nto-qnx*)
 openbsd*)
   version_type=sunos
   need_lib_prefix=no
-  need_version=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
   shlibpath_var=LD_LIBRARY_PATH
@@ -2858,7 +2962,7 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN],
 
 # AC_LIBTOOL_WIN32_DLL
 # --------------------
-# declare package support for building win32 dll's
+# declare package support for building win32 DLLs
 AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
 [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
 ])# AC_LIBTOOL_WIN32_DLL
@@ -3032,7 +3136,7 @@ dnl not every word.  This closes a longstanding sh security hole.
       if test -n "$file_magic_test_file"; then
        case $deplibs_check_method in
        "file_magic "*)
-         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
          MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
          if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
            $EGREP "$file_magic_regex" > /dev/null; then
@@ -3142,7 +3246,7 @@ AC_CACHE_VAL(lt_cv_path_LD,
     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
       lt_cv_path_LD="$ac_dir/$ac_prog"
       # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some GNU ld's only accept -v.
+      # but apparently some variants of GNU ld only accept -v.
       # Break only if it was the GNU/non-GNU ld that we prefer.
       case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
       *GNU* | *'with BFD'*)
@@ -3174,7 +3278,7 @@ AC_PROG_LD_GNU
 AC_DEFUN([AC_PROG_LD_GNU],
 [AC_REQUIRE([AC_PROG_EGREP])dnl
 AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
 case `$LD -v 2>&1 </dev/null` in
 *GNU* | *'with BFD'*)
   lt_cv_prog_gnu_ld=yes
@@ -3288,7 +3392,7 @@ gnu*)
 
 hpux10.20* | hpux11*)
   lt_cv_file_magic_cmd=/usr/bin/file
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
     lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
@@ -3462,13 +3566,13 @@ esac
 # -----------------------------------
 # sets LIBLTDL to the link flags for the libltdl convenience library and
 # LTDLINCL to the include flags for the libltdl header and adds
-# --enable-ltdl-convenience to the configure arguments.  Note that LIBLTDL
-# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
-# DIRECTORY is not provided, it is assumed to be `libltdl'.  LIBLTDL will
-# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with
-# '${top_srcdir}/' (note the single quotes!).  If your package is not
-# flat and you're not using automake, define top_builddir and
-# top_srcdir appropriately in the Makefiles.
+# --enable-ltdl-convenience to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# it is assumed to be `libltdl'.  LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!).  If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
 AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
 [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
   case $enable_ltdl_convenience in
@@ -3487,13 +3591,13 @@ AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
 # -----------------------------------
 # sets LIBLTDL to the link flags for the libltdl installable library and
 # LTDLINCL to the include flags for the libltdl header and adds
-# --enable-ltdl-install to the configure arguments.  Note that LIBLTDL
-# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
-# DIRECTORY is not provided and an installed libltdl is not found, it is
-# assumed to be `libltdl'.  LIBLTDL will be prefixed with '${top_builddir}/'
-# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
-# quotes!).  If your package is not flat and you're not using automake,
-# define top_builddir and top_srcdir appropriately in the Makefiles.
+# --enable-ltdl-install to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
 # In the future, this macro may have to be called after AC_PROG_LIBTOOL.
 AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
 [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
@@ -3676,7 +3780,7 @@ test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
 # are all built from PIC.
-case "$host_os" in
+case $host_os in
 aix3*)
   test "$enable_shared" = yes && enable_static=no
   if test -n "$RANLIB"; then
@@ -3743,7 +3847,7 @@ _LT_AC_TAGVAR(postdeps, $1)=
 _LT_AC_TAGVAR(compiler_lib_search_path, $1)=
 
 # Source file extension for C++ test sources.
-ac_ext=cc
+ac_ext=cpp
 
 # Object file extension for compiled C++ test sources.
 objext=o
@@ -3959,7 +4063,7 @@ case $host_os in
        # Exported symbols can be pulled into shared objects from archives
        _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
        _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
-       # This is similar to how AIX traditionally builds it's shared libraries.
+       # This is similar to how AIX traditionally builds its shared libraries.
        _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
       fi
     fi
@@ -3998,7 +4102,7 @@ case $host_os in
     fi
   ;;
       darwin* | rhapsody*)
-        case "$host_os" in
+        case $host_os in
         rhapsody* | darwin1.[[012]])
          _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
          ;;
@@ -4036,7 +4140,7 @@ case $host_os in
           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
         fi
         _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
           if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
             _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           else
@@ -4049,7 +4153,7 @@ case $host_os in
          output_verbose_link_cmd='echo'
           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
           _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -4129,7 +4233,7 @@ case $host_os in
     ;;
   hpux10*|hpux11*)
     if test $with_gnu_ld = no; then
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*)
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
@@ -4145,7 +4249,7 @@ case $host_os in
         ;;
       esac
     fi
-    case "$host_cpu" in
+    case $host_cpu in
     hppa*64*)
       _LT_AC_TAGVAR(hardcode_direct, $1)=no
       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
@@ -4171,7 +4275,7 @@ case $host_os in
        _LT_AC_TAGVAR(ld_shlibs, $1)=no
        ;;
       aCC*)
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
          ;;
@@ -4192,7 +4296,7 @@ case $host_os in
       *)
        if test "$GXX" = yes; then
          if test $with_gnu_ld = no; then
-           case "$host_cpu" in
+           case $host_cpu in
            ia64*|hppa*64*)
              _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
              ;;
@@ -4288,12 +4392,12 @@ case $host_os in
        ;;
       pgCC*)
         # Portland Group C++ compiler
-       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
-       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
        _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
         ;;
       cxx*)
        # Compaq C++
@@ -4525,10 +4629,11 @@ case $host_os in
     case $cc_basename in
       CC*)
        # Sun C++ 4.2, 5.x and Centerline C++
+        _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
        _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
-       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
        _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-       $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
 
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
        _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
@@ -4548,15 +4653,7 @@ case $host_os in
        esac
        _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
 
-       # Commands to make compiler produce verbose output that lists
-       # what "hidden" libraries, object files and flags are used when
-       # linking a shared library.
-       #
-       # There doesn't appear to be a way to prevent this compiler from
-       # explicitly linking system object files so we need to strip them
-       # from the output so that they don't get included in the library
-       # dependencies.
-       output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       output_verbose_link_cmd='echo'
 
        # Archives containing C++ object files must be created using
        # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -4717,7 +4814,7 @@ if AC_TRY_EVAL(ac_compile); then
   # The `*' in the case matches for architectures that use `case' in
   # $output_verbose_cmd can trigger glob expansion during the loop
   # eval without this substitution.
-  output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
 
   for p in `eval $output_verbose_link_cmd`; do
     case $p in
@@ -4793,6 +4890,21 @@ fi
 
 $rm -f confest.$objext
 
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+solaris*)
+  case $cc_basename in
+  CC*)
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
+    ;;
+  esac
+esac
+])
+
 case " $_LT_AC_TAGVAR(postdeps, $1) " in
 *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
 esac
@@ -4862,7 +4974,7 @@ test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
 # are all built from PIC.
-case "$host_os" in
+case $host_os in
 aix3*)
   test "$enable_shared" = yes && enable_static=no
   if test -n "$RANLIB"; then
@@ -5765,7 +5877,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        ;;
       *)
@@ -5834,7 +5946,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
          aCC*)
            _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
            _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
-           case "$host_cpu" in
+           case $host_cpu in
            hppa*64*|ia64*)
              # +Z the default
              ;;
@@ -5875,7 +5987,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
            # Portland Group C++ compiler.
            _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
            _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
-           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
            ;;
          cxx*)
            # Compaq C++
@@ -6039,7 +6151,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -6086,7 +6198,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -6116,12 +6228,12 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
        _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
        _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
         ;;
-      pgcc* | pgf77* | pgf90*)
+      pgcc* | pgf77* | pgf90* | pgf95*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
        # which looks to be a dead project)
        _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
        _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
-       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
         ;;
       ccc*)
         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
@@ -6204,7 +6316,7 @@ if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
     [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
 fi
-case "$host_os" in
+case $host_os in
   # For platforms which do not support PIC, -DPIC is meaningless:
   *djgpp*)
     _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
@@ -6300,7 +6412,7 @@ ifelse([$1],[CXX],[
   if test "$with_gnu_ld" = yes; then
     # If archive_cmds runs LD, not CC, wlarc should be empty
     wlarc='${wl}'
-    
+
     # Set some defaults for GNU ld with shared library support. These
     # are reset later if shared libraries are not supported. Putting them
     # here allows them to be overridden if necessary.
@@ -6321,7 +6433,7 @@ ifelse([$1],[CXX],[
       *\ 2.11.*) ;; # other 2.11 versions
       *) supports_anon_versioning=yes ;;
     esac
-    
+
     # See if GNU ld supports shared libraries.
     case $host_os in
     aix3* | aix4* | aix5*)
@@ -6395,11 +6507,12 @@ EOF
        tmp_addflag=
        case $cc_basename,$host_cpu in
        pgcc*)                          # Portland Group C compiler
-         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
          ;;
-       pgf77* | pgf90* )                       # Portland Group f77 and f90 compilers
-         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
-         tmp_addflag=' -fpic -Mnomain' ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
        ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
          tmp_addflag=' -i_dynamic' ;;
        efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
@@ -6604,7 +6717,7 @@ EOF
          # Exported symbols can be pulled into shared objects from archives
          _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
          _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
-         # This is similar to how AIX traditionally builds it's shared libraries.
+         # This is similar to how AIX traditionally builds its shared libraries.
          _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
        fi
       fi
@@ -6644,7 +6757,7 @@ EOF
       ;;
 
     darwin* | rhapsody*)
-      case "$host_os" in
+      case $host_os in
         rhapsody* | darwin1.[[012]])
          _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
          ;;
@@ -6673,7 +6786,7 @@ EOF
        output_verbose_link_cmd='echo'
         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
       _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
       _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
     else
@@ -6682,7 +6795,7 @@ EOF
          output_verbose_link_cmd='echo'
          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
          _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -6748,7 +6861,7 @@ EOF
 
     hpux10* | hpux11*)
       if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
          ;;
@@ -6757,7 +6870,7 @@ EOF
          ;;
        esac
       else
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
          ;;
@@ -6767,7 +6880,7 @@ EOF
        esac
       fi
       if test "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*)
          _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
          _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
index 1efc993c6ac61716f729fcad2cde0d2214a18122..7723ed9ab859c19d82028125d23ac40b196a5a40 100644 (file)
@@ -15,7 +15,7 @@ amplotdir =           $(libexecdir)
 EXTRA_DIST =           amplot.awk              amplot.g
 
 CLEANFILES = amplot.gp.new
-DISTCLEANFILES = amplot.gp
+DISTCLEANFILES = amplot.gp amplot
 
 amplot.gp:             amplot.g
                        cat $(srcdir)/amplot.g > amplot.gp.new
index 9648a111dd52d99067d6cba8886d08859401f61a..6678bce470712f74ae06087af8702c17067b8778 100644 (file)
@@ -112,7 +112,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -124,9 +126,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -139,6 +144,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -201,10 +207,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -261,7 +270,7 @@ amplot_DATA = amcat.awk amplot.awk amplot.g amplot.gp
 amplotdir = $(libexecdir)
 EXTRA_DIST = amplot.awk                amplot.g
 CLEANFILES = amplot.gp.new
-DISTCLEANFILES = amplot.gp
+DISTCLEANFILES = amplot.gp amplot
 all: all-am
 
 .SUFFIXES:
diff --git a/autogen b/autogen
new file mode 100755 (executable)
index 0000000..2da3592
--- /dev/null
+++ b/autogen
@@ -0,0 +1,19 @@
+#! /bin/sh
+# rebuilds files generated by autoconf&automake.
+# autoconf 2.13 and automake 1.4 or newer are required
+# arguments are forwarded to the autoreconf script.
+
+cd `dirname $0`
+
+touch config/config.h.in
+
+if test x`ls -1t acinclude.m4 2>/dev/null \
+           config/acinclude.m4i config/libtool.m4i |
+         sed 1q` != x"acinclude.m4"; then
+    rm -f acinclude.m4
+    cat config/acinclude.m4i config/libtool.m4i > acinclude.m4
+fi
+
+autoreconf --warning=syntax --force ${1+"$@"}
+
+exit 0
index 68c186ced9e66a56a31a23f7a967b9457df8b807..490e987702b095353e2e68486bcd1fc1f9c01fe1 100644 (file)
@@ -1,6 +1,9 @@
 # Makefile for Amanda tape changer programs.
 
-INCLUDES =             -I$(top_srcdir)/common-src -I$(top_srcdir)/server-src -I$(top_srcdir)/tape-src
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/server-src   \
+               -I$(top_srcdir)/tape-src
 
 LIB_EXTENSION = la
 
@@ -21,6 +24,8 @@ libexec_SCRIPTS =     chg-manual      chg-multi       chg-mtx         \
                        chg-null        chg-mcutil      chg-disk        \
                        chg-iomega
 
+CLEANFILES = $(libexec_SCRIPTS)
+
 ###
 # Because libamanda includes routines (e.g. regex) provided by some system
 # libraries, and because of the way libtool sets up the command line, we
index e2c3e845338ae382d8aeefee9396e0c51fc61bfc..c504507d2ecc8eb70510c9d8e0f1496df7a87a73 100644 (file)
@@ -152,7 +152,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -164,9 +166,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -179,6 +184,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -241,10 +247,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -295,7 +304,11 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-INCLUDES = -I$(top_srcdir)/common-src -I$(top_srcdir)/server-src -I$(top_srcdir)/tape-src
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/server-src   \
+               -I$(top_srcdir)/tape-src
+
 LIB_EXTENSION = la
 @WANT_CHIO_SCSI_TRUE@CHIO_SCSI = chg-scsi-chio
 @WANT_CHG_SCSI_TRUE@CHG_SCSI = chg-scsi
@@ -305,6 +318,7 @@ libexec_SCRIPTS = chg-manual        chg-multi       chg-mtx         \
                        chg-null        chg-mcutil      chg-disk        \
                        chg-iomega
 
+CLEANFILES = $(libexec_SCRIPTS)
 
 ###
 # Because libamanda includes routines (e.g. regex) provided by some system
@@ -587,6 +601,7 @@ install-strip:
 mostlyclean-generic:
 
 clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
index 1f0b8518a441e26397da098d5fae1e590efab0f8..72dc98b3e66f7ec5ff87a9af525d349e3dea5f6a 100644 (file)
@@ -77,15 +77,40 @@ MYNAME=$0
 TAPE=`amgetconf$SUF tapedev`
 SLOTDIR=`echo $TAPE | sed 's/^file://'`
 
+isinteger() {
+           # should be exactly one arg
+       [ $# = 1 ]  || return 1
+           # if arg is null, no expr needed
+       [ "${1}" = '' ] && return 1
+           # expr will return 0 on match
+       expr "$1" : '[0-9][0-9]*$' > /dev/null 2>&1
+}
+
+# need rwx access to directory of changer file
 CHANGERFILE=`amgetconf$SUF changerfile`
+CFDir=`dirname ${CHANGERFILE}`
+[ -d ${CFDir} -a -r ${CFDir} -a -w ${CFDir} -a -x ${CFDir} ] ||
+       { echo "$MYNAME: need 'rwx' access to '$CFDir'" ; exit 2 ; }
+
+# check or create changer metadata files
 ACCESSFILE=$CHANGERFILE-access
+[ -f $ACCESSFILE -a -r $ACCESSFILE -a -w $ACCESSFILE ] ||
+       echo 0 > $ACCESSFILE ||
+       { echo "$MYNAME: could not access or create '$ACCESSFILE'" ; exit 2 ; }
 CLEANFILE=$CHANGERFILE-clean
+[ -f $CLEANFILE -a -r $CLEANFILE -a -w $CLEANFILE ] ||
+       echo 0 > $CLEANFILE ||
+       { echo "$MYNAME: could not access or create '$CLEANFILE'" ; exit 2 ; }
 SLOTFILE=$CHANGERFILE-slot
-[ ! -f $ACCESSFILE ] && echo 0 > $ACCESSFILE
-[ ! -f $CLEANFILE ] && echo 0 > $CLEANFILE
-[ ! -f $SLOTFILE ] && echo 0 > $SLOTFILE
+[ -f $SLOTFILE -a -r $SLOTFILE -a -w $SLOTFILE ] ||
+       echo 0 > $SLOTFILE ||
+       { echo "$MYNAME: could not access or create '$SLOTFILE'" ; exit 2 ; }
+
+# read and check metadata
 ACCESSCOUNT=`cat $ACCESSFILE`
+isinteger $ACCESSCOUNT || { ACCESSCOUNT=0 ; echo 0 > $ACCESSFILE ; }
 CLEANCOUNT=`cat $CLEANFILE`
+isinteger $CLEANCOUNT || { CLEANCOUNT=0 ; echo 0 > $CLEANFILE ; }
 
 FIRSTSLOT=1
 LASTSLOT=`amgetconf$SUF tapecycle`
@@ -94,6 +119,8 @@ CLEANSLOT=$LASTSLOT
 
 load() {
   WHICHSLOT=$1;
+  # unload should have been called, but just in case ...
+  [ -h $SLOTDIR/data ] && unload
   ln -s $SLOTDIR/slot$WHICHSLOT $SLOTDIR/data
   echo $WHICHSLOT > $SLOTFILE
 }
@@ -110,10 +137,8 @@ readstatus() {
 loadslot() {
   WHICHSLOT=$1
 
-  case $WHICHSLOT in
-    [0-9]*) TYPE="digit";;
-    *) TYPE="string";;
-  esac
+  TYPE=string  # default if not numeric
+  isinteger $WHICHSLOT && TYPE=digit
 
   readstatus
   NEWSLOT=0
@@ -154,10 +179,10 @@ loadslot() {
     exit 0
   fi
   if [ $NEWSLOT = $CLEANSLOT ]; then
-    expr $CLEANCOUNT + 1 > $CLEANFILE
+    expr ${CLEANCOUNT:=0} + 1 > $CLEANFILE
     echo 0 > $ACCESSFILE
   else
-    expr $ACCESSCOUNT + 1 > $ACCESSFILE
+    expr ${ACCESSCOUNT:=0} + 1 > $ACCESSFILE
     if [ $ACCESSCOUNT -gt $LASTSLOT ]; then
       $MYNAME -slot clean >/dev/null
     fi
index d6703183e2361b75aad1d2813fcf5217cd088c6f..0103c815b36a22bdfa97cd178423827bbc7596a1 100644 (file)
 #
 # chg-multi.sh - generic tape changer script
 #
-# chg-multi is 'not' intended for use with tape changers or
-# libraries.  It is primarily used to make several, individual
-# tape drives appear to amanda as a single changer or library.
-# The "multi" in the script name refers to multiple drives.
-#
 
 prefix=@prefix@
 exec_prefix=@exec_prefix@
index 2ac644481f5776d0c31abf1a89e6d7cb3e7895e8..b86074de3fbb4fb4509e90c08a92a7db4c3d583e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  $Id: chg-scsi-chio.c,v 1.1.2.3.6.3 2003/01/26 19:20:56 martinea Exp $
+ *  $Id: chg-scsi-chio.c,v 1.8 2006/01/14 04:37:18 paddy_s Exp $
  *
  *  chg-scsi.c -- generic SCSI changer driver
  *
@@ -636,6 +636,10 @@ int main(int argc, char *argv[])
   char *scsitapedevice = NULL;
 
   set_pname("chg-scsi");
+
+  /* Don't die when child closes pipe */
+  signal(SIGPIPE, SIG_IGN);
+
   dbopen();
   parse_args(argc,argv,&com);
 
index 01cc133b83c5e0288b52f3954171d7b25ed1e13a..fe7cb35b0c5eed58234e227233ad7b5d8f5d05f0 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
-static char rcsid[] = "$Id: chg-scsi.c,v 1.6.2.22.2.7.2.9 2003/07/05 16:59:01 ant Exp $";
+static char rcsid[] = "$Id: chg-scsi.c,v 1.44 2006/03/09 20:06:10 johnfranks Exp $";
 #endif
 /*
  * 
@@ -666,6 +666,7 @@ int MapBarCode(char *labelfile, MBC_T *result)
               strcpy(plabelv2->barcode, result->data.barcode);
               fwrite(plabelv2, 1, sizeof(LabelV2_T), fp);
               fclose(fp);
+             free(plabelv2);
               return(1);
             }
           break;
@@ -678,6 +679,7 @@ int MapBarCode(char *labelfile, MBC_T *result)
             {
               DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE,"MapBarCode FIND_SLOT : \n");
               memcpy(&(result->data), plabelv2, sizeof(LabelV2_T));
+             free(plabelv2);
               return(1);
            }
           break;
@@ -699,6 +701,7 @@ int MapBarCode(char *labelfile, MBC_T *result)
               plabelv2->LoadCount = plabelv2->LoadCount + result->data.LoadCount;
               fwrite(plabelv2, 1, sizeof(LabelV2_T), fp);
               fclose(fp);
+             free(plabelv2);
               return(1);
             }
           break;
@@ -718,6 +721,7 @@ int MapBarCode(char *labelfile, MBC_T *result)
               fclose(fp);
               
               memcpy(&(result->data), plabelv2, sizeof(LabelV2_T));
+             free(plabelv2);
               return(1);
             }
           break;
@@ -732,6 +736,7 @@ int MapBarCode(char *labelfile, MBC_T *result)
               fclose(fp);
               
               memcpy(&(result->data), plabelv2, sizeof(LabelV2_T));
+             free(plabelv2);
               return(1);
             }
           break;
@@ -777,14 +782,16 @@ int MapBarCode(char *labelfile, MBC_T *result)
       plabelv2->slot = result->data.slot;
       fwrite(plabelv2, 1, sizeof(LabelV2_T), fp);
       fclose(fp);
+      free(plabelv2);
       return(1);
-    }                                                                           
+    }
 
   /*
    * If we hit this point nothing was 
    * found, so return an 0
    */
   fclose(fp);
+  free(plabelv2);
   return(0);
 }
 
@@ -1043,7 +1050,6 @@ int main(int argc, char *argv[])
   char *clean_file=NULL;
   char *time_file=NULL;
 
-  char *ptr;         /* a public pointer .... */
   /*
    * For the emubarcode stuff
    */
@@ -1072,11 +1078,14 @@ int main(int argc, char *argv[])
   chg.device = NULL;
   chg.labelfile = NULL;
   chg.conf = NULL;
-  chg.debuglevel = NULL;
 #ifdef CHG_SCSI_STANDALONE
   printf("Ups standalone\n");
 #else
   set_pname("chg-scsi");
+
+  /* Don't die when child closes pipe */
+  signal(SIGPIPE, SIG_IGN);
+
   dbopen();
 
   dbprintf(("chg-scsi: %s\n",rcsid));
@@ -1093,11 +1102,6 @@ int main(int argc, char *argv[])
   memset(pDev, 0, sizeof(OpenFiles_T) * CHG_MAXDEV );
 
 
-  if ((ptr=getenv("CHG_DEBUG")) != NULL)
-    {
-      chg.debuglevel = strdup(ptr);
-    }
-
   switch(com.command_code) 
     {
     case COM_SCAN:
@@ -1607,7 +1611,7 @@ int main(int argc, char *argv[])
       
     printf("%d %d 1", loaded, use_slots);
 
-    if (BarCode(fd) == 1 || emubarcode == 1 || chg.havebarcode == 1)
+    if (BarCode(fd) == 1 || emubarcode == 1)
       {
         printf(" 1\n");
       } else {
index 2f8dfea5460e76549ac31162d526cadee82f953b..e0fe00eaeb75e142965c131576b996b8a8c04e47 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Id: libscsi.h,v 1.4.4.4.4.1 2001/07/10 22:03:14 jrjackson Exp $
+ *     $Id: libscsi.h,v 1.9 2000/06/25 18:48:11 ant Exp $
  *
  *     libscsi.h -- library header for routines to handle the changer
  *                     support for chio based systems
index 7e00fda1cf1df01a06ec3529e9933c74e70d684b..4696faf693c66d571d76a4b7a2adbd4aecf2a547 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-aix.c,v 1.1.2.14.4.3.2.3 2003/01/26 19:20:56 martinea Exp $
+ * $Id: scsi-aix.c,v 1.22 2005/10/15 13:20:47 martinea Exp $
  *
  * Interface to execute SCSI commands on an AIX System
  *
@@ -64,7 +64,7 @@
 void SCSI_OS_Version()
 {
 #ifndef lint
-   static char rcsid[] = "$Id: scsi-aix.c,v 1.1.2.14.4.3.2.3 2003/01/26 19:20:56 martinea Exp $";
+   static char rcsid[] = "$Id: scsi-aix.c,v 1.22 2005/10/15 13:20:47 martinea Exp $";
    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -89,7 +89,7 @@ int SCSI_OpenDevice(int ip)
         } else {
           DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC);
         }
-      if (DeviceFD > 0)
+      if (DeviceFD >= 0)
        {
          pDev[ip].avail = 1;
           pDev[ip].fd = DeviceFD;
@@ -137,7 +137,7 @@ int SCSI_OpenDevice(int ip)
          return(0);
        }
     } else {
-      if ((DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC)) > 0)
+      if ((DeviceFD = openx(pDev[ip].dev, O_RDWR, 0, SC_DIAGNOSTIC)) >= 0)
         {
           pDev[ip].fd = DeviceFD;
           pDev[ip].devopen = 1;
@@ -249,7 +249,8 @@ int SCSI_ExecuteCommand(int DeviceFD,
       DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
       
       if (pDev[DeviceFD].devopen == 0)
-        SCSI_OpenDevice(DeviceFD);
+        if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(SCSI_ERROR);
       Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
       SCSI_CloseDevice(DeviceFD);
       
@@ -270,7 +271,8 @@ int SCSI_ExecuteCommand(int DeviceFD,
               ds.data_length = RequestSenseLength;
               
               if (pDev[DeviceFD].devopen == 0)
-                SCSI_OpenDevice(DeviceFD);
+                if (SCSI_OpenDevice(DeviceFD) == 0)
+                  return(SCSI_ERROR);
               Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
               SCSI_CloseDevice(DeviceFD);
               return(SCSI_OK);
@@ -291,7 +293,8 @@ int SCSI_ExecuteCommand(int DeviceFD,
               ds.data_length = RequestSenseLength;
 
               if (pDev[DeviceFD].devopen == 0)
-                SCSI_OpenDevice(DeviceFD);
+                if (SCSI_OpenDevice(DeviceFD) == 0)
+                  return(SCSI_ERROR);
               Result = ioctl(pDev[DeviceFD].fd, STIOCMD, &ds);
               SCSI_CloseDevice(DeviceFD);
               return(SCSI_CHECK);
index a152b2411f344ba15e82d3794ea80d0658090996..bd010667520414e007f6e1216eea7865ea2d3d26 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-bsd.c,v 1.1.2.10.4.2.2.4 2003/06/05 20:44:23 martinea Exp $
+ * $Id: scsi-bsd.c,v 1.17 2005/10/15 13:20:47 martinea Exp $
  *
  * Interface to execute SCSI commands on an BSD System (FreeBSD)
  *
@@ -61,7 +61,7 @@
 void SCSI_OS_Version()
 {
 #ifndef lint
-   static char rcsid[] = "$Id: scsi-bsd.c,v 1.1.2.10.4.2.2.4 2003/06/05 20:44:23 martinea Exp $";
+   static char rcsid[] = "$Id: scsi-bsd.c,v 1.17 2005/10/15 13:20:47 martinea Exp $";
    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -75,7 +75,6 @@ void SCSI_OS_Version()
  * Return:
  * 0  -> device not opened
  * 1  -> sucess , device open
- * -1 -> fatal error
  */
 int SCSI_OpenDevice(int ip)
 {
@@ -93,7 +92,7 @@ int SCSI_OpenDevice(int ip)
     pDev[ip].SCSI = 0;                                                        /* This will only be set if the inquiry works */
     pDev[ip].inquiry = (SCSIInquiry_T *)malloc(INQUIRY_SIZE);
     
-    if (( pDev[ip].fd = open(pDev[ip].dev, O_RDWR)) > 0)                      /* We need the device in read/write mode */
+    if (( pDev[ip].fd = open(pDev[ip].dev, O_RDWR)) >= 0)                      /* We need the device in read/write mode */
       {
         pDev[ip].devopen = 1;                                                 /* The device is open for use */
         pDev[ip].avail = 1;                                                   /* And it is available, it could be opened */
@@ -137,7 +136,7 @@ int SCSI_OpenDevice(int ip)
       }  /* open() */
     return(0);                                                                /* Open failed .... */
   } else { /* pDev[ip].inqdone */                                             /* OK this is the way we go if the device */
-    if (( pDev[ip].fd = open(pDev[ip].dev, O_RDWR)) > 0)                      /* was opened successfull before */
+    if (( pDev[ip].fd = open(pDev[ip].dev, O_RDWR)) >= 0)                      /* was opened successfull before */
       {
         pDev[ip].devopen = 1;
         return(1);
@@ -217,9 +216,8 @@ int SCSI_ExecuteCommand(int DeviceFD,
   while (--retries > 0) {
     
     if (pDev[DeviceFD].devopen == 0)
-      {
-        SCSI_OpenDevice(DeviceFD);
-      }
+        if (SCSI_OpenDevice(DeviceFD) == 0)
+            return(SCSI_ERROR);
     Result = ioctl(pDev[DeviceFD].fd, SCIOCCOMMAND, &ds);
     SCSI_CloseDevice(DeviceFD);
    
@@ -258,9 +256,8 @@ int Tape_Ioctl( int DeviceFD, int command)
   int ret = 0;
 
   if (pDev[DeviceFD].devopen == 0)
-    {
-      SCSI_OpenDevice(DeviceFD);
-    }
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
 
   switch (command)
     {
index df966bd537e16e5661b57258f15ebd39c47466d1..e159b45facf8ab30b2f46051e2badf4f1deef105 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-cam.c,v 1.10.4.1.2.3.2.1 2004/04/29 20:47:21 martinea Exp $
+ * $Id: scsi-cam.c,v 1.14 2005/10/15 13:20:47 martinea Exp $
  *
  * Interface to execute SCSI commands on an system with cam support
  * Current support is for FreeBSD 4.x
@@ -75,7 +75,7 @@ extern FILE *debug_file;
 void SCSI_OS_Version()
 {
 #ifndef lint
-   static char rcsid[] = "$Id: scsi-cam.c,v 1.10.4.1.2.3.2.1 2004/04/29 20:47:21 martinea Exp $";
+   static char rcsid[] = "$Id: scsi-cam.c,v 1.14 2005/10/15 13:20:47 martinea Exp $";
    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -283,7 +283,11 @@ int SCSI_ExecuteCommand(int DeviceFD,
 
   if (pDev[DeviceFD].devopen == 0)
     {
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+        {
+          cam_freeccb(ccb);
+          return(SCSI_ERROR);
+       }
     }
   
   ret = cam_send_ccb(pDev[DeviceFD].curdev, ccb);
@@ -322,9 +326,8 @@ int Tape_Ioctl( int DeviceFD, int command)
   int ret = 0;
 
   if (pDev[DeviceFD].devopen == 0)
-    {
-      SCSI_OpenDevice(DeviceFD);
-    }
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
 
   switch (command)
     {
@@ -354,9 +357,8 @@ int Tape_Status( int DeviceFD)
   int ret = 0;
   
   if (pDev[DeviceFD].devopen == 0)
-    {
-      SCSI_OpenDevice(DeviceFD);
-    }
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
 
   if (ioctl(pDev[DeviceFD].fd , MTIOCGET, &mtget) != 0)
   {
index 2bc0507326119a31518c435a297efc4e5577f750..c9dad844638e9e2beda7edbf7530d45645c1ac6e 100644 (file)
@@ -1,5 +1,5 @@
- #ifndef lint
-static char rcsid[] = "$Id: scsi-changer-driver.c,v 1.1.2.27.2.7.2.10 2003/01/26 19:20:56 martinea Exp $";
+#ifndef lint
+static char rcsid[] = "$Id: scsi-changer-driver.c,v 1.49 2006/03/16 00:20:53 paddy_s Exp $";
 #endif
 /*
  * Interface to control a tape robot/library connected to the SCSI bus
@@ -103,7 +103,7 @@ void C1553APage30(LogParameter_T *, int);
 void C1553APage37(LogParameter_T *, int);
 void EXB85058HEPage39(LogParameter_T *, int);
 void EXB85058HEPage3c(LogParameter_T *, int);
-int Decode(LogParameter_T *, int *); 
+int Decode(LogParameter_T *, int *);
 int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *out);
 
 int SCSI_Run(int DeviceFD,
@@ -119,14 +119,14 @@ int SCSI_Move(int DeviceFD, unsigned char chm, int from, int to);
 int SCSI_LoadUnload(int DeviceFD, RequestSense_T *pRequestSense, unsigned char byte1, unsigned char load);
 int SCSI_TestUnitReady(int, RequestSense_T *);
 int SCSI_ModeSense(int DeviceFD, char *buffer, u_char size, u_char byte1, u_char byte2);
-int SCSI_ModeSelect(int DeviceFD, 
+int SCSI_ModeSelect(int DeviceFD,
                     char *buffer,
                     unsigned char length,
                     unsigned char save,
                     unsigned char mode,
                     unsigned char lun);
 
-int SCSI_ReadElementStatus(int DeviceFD, 
+int SCSI_ReadElementStatus(int DeviceFD,
                            unsigned char type,
                            unsigned char lun,
                            unsigned char VolTag,
@@ -167,7 +167,7 @@ SC_COM_T SCSICommand[] = {
    "UNLOAD"},
   {0x4D,
    10,
-   "LOG SENSE"}, 
+   "LOG SENSE"},
   {0xA5,
    12,
    "MOVE MEDIUM"},
@@ -205,9 +205,9 @@ ChangerCMD_T ChangerIO[] = {
    GenericRewind,
    GenericBarCode,
    GenericSearch,
-   GenericSenseHandler}, 
+   GenericSenseHandler},
   /* Exabyte Devices */
-  {"EXB-10e",      
+  {"EXB-10e",
    "Exabyte Robot [EXB-10e]",
    GenericMove,
    GenericElementStatus,
@@ -219,7 +219,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericBarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"EXB-120",   
+  {"EXB-120",
    "Exabyte Robot [EXB-120]",
    GenericMove,
    GenericElementStatus,
@@ -231,7 +231,7 @@ ChangerCMD_T ChangerIO[] = {
    EXB_BarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"EXB-210",   
+  {"EXB-210",
    "Exabyte Robot [EXB-210]",
    GenericMove,
    GenericElementStatus,
@@ -243,7 +243,7 @@ ChangerCMD_T ChangerIO[] = {
    EXB_BarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"EXB-85058HE-0000",        
+  {"EXB-85058HE-0000",
    "Exabyte Tape [EXB-85058HE-0000]",
    DoNothing,
    DoNothing,
@@ -256,7 +256,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericSearch,
    GenericSenseHandler},
   /* Tandberg Devices */
-  {"TDS 1420",              
+  {"TDS 1420",
    "Tandberg Robot (TDS 1420)",
    GenericMove,
    GenericElementStatus,
@@ -269,7 +269,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericSearch,
    GenericSenseHandler},
     /* ADIC Devices */
-  {"VLS DLT",               
+  {"VLS DLT",
    "ADIC VLS DLT Library [VLS DLT]",
    GenericMove,
    GenericElementStatus,
@@ -281,7 +281,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericBarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"VLS SDX",               
+  {"VLS SDX",
    "ADIC VLS DLT Library [VLS SDX]",
    SDXMove,
    SDXElementStatus,
@@ -293,7 +293,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericBarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"FastStor DLT",               
+  {"FastStor DLT",
    "ADIC FastStor DLT Library [FastStor DLT]",
    SDXMove,
    DLT448ElementStatus,
@@ -356,7 +356,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericBarCode,
    GenericSearch,
    GenericSenseHandler},
-  /* 
+  /*
    * And now the tape devices
    */
   /* The generic handler if nothing matches */
@@ -384,7 +384,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericBarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"DLT7000",        
+  {"DLT7000",
    "DLT Tape [DLT7000]",
    DoNothing,
    DoNothing,
@@ -396,7 +396,7 @@ ChangerCMD_T ChangerIO[] = {
    GenericBarCode,
    GenericSearch,
    GenericSenseHandler},
-  {"DLT4000",        
+  {"DLT4000",
    "DLT Tape [DLT4000]",
    DoNothing,
    DoNothing,
@@ -405,11 +405,11 @@ ChangerCMD_T ChangerIO[] = {
    DLT4000Eject,
    GenericClean,
    GenericRewind,
-   NoBarCode, 
+   NoBarCode,
    GenericSearch,
    GenericSenseHandler},
   {NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
-};           
+};
 
 
 LogPageDecode_T DecodePages[] = {
@@ -462,9 +462,9 @@ ElementInfo_T *pDTE = NULL; /*Data Transfer Element */
 int MTE = 0;                /*Counter for the above element types */
 int STE = 0;
 int IEE = 0;
-int DTE = 0; 
+int DTE = 0;
 
-char *chgscsi_datestamp = NULL;       /* Result pointer for tape_rdlabel */       
+char *chgscsi_datestamp = NULL;       /* Result pointer for tape_rdlabel */
 char *chgscsi_label = NULL;           /* Result pointer for tape_rdlabel */
 char *chgscsi_result = NULL;          /* Needed for the result string of MapBarCode */
 
@@ -515,7 +515,7 @@ void PrintConf()
   printf("sleep            ??? # How long to wait after an eject command before moving\n");
   printf("                     # the tape\n");
   printf("                     #\n");
-  
+
   for (count = 0; count < CHG_MAXDEV ; count++)
     {
       if (pDev[count].dev)
@@ -527,7 +527,7 @@ void PrintConf()
            }
        }
     }
-  
+
   /*
    * Did we reach the end of the list ?
    * If no we found an changer and now we try to
@@ -535,11 +535,11 @@ void PrintConf()
    */
   if (count < CHG_MAXDEV)
     {
-      pDev[count].functions->function_status(count, 1);  
+      pDev[count].functions->function_status(count, 1);
     } else {
       printf("changerdev   ??? # Ups nothing found. Please check the docs\n");
     }
-  
+
   printf("                     #\n");
   printf("                     # Here now comes the config for the first tape\n");
   printf("config             0 # This value is the one which is used in the amanda\n");
@@ -592,7 +592,7 @@ void PrintConf()
       printf("                     #\n");
 
   cwd = getcwd(NULL, 0);
-  
+
   printf("statfile %s/tape0-slot #\n",cwd);
   printf("cleanfile %s/tape0-clean #\n", cwd);
   printf("usagecount %s/tape0-totaltime #\n", cwd);
@@ -601,11 +601,11 @@ void PrintConf()
 }
 
 
+
 /*
  * Try to create a list of tapes and labels which are in the current
  * magazin. The drive must be empty !!
- * 
+ *
  * labelfile -> file name of the db
  * drive -> which drive should we use
  * eject -> the tape device needs an eject before move
@@ -613,7 +613,7 @@ void PrintConf()
  * stop  -> stop at slot stop
  * clean -> if we have an cleaning tape than this is the slot number of it
  *
- * return 
+ * return
  * 0  -> fail
  * 1  -> successfull
  *
@@ -626,33 +626,37 @@ void Inventory(char *labelfile, int drive, int eject, int start, int stop, int c
 {
   extern OpenFiles_T *pDev;
   int x;
-  char *datestamp = malloc(1);   /* stupid, but tapefd_rdlabel does an free at the begining ... */
-  char *label = malloc(1);       /* the same here ..... */
-  char *result;                    /* Used to store the result of MapBarCode */
-  int barcode;                   /* cache the result from the BarCode function */
-  static int inv_done = 0;       /* Inventory function called ?, marker to disable recursion */
-  MBC_T *pbarcoderes = malloc(sizeof(MBC_T));    /* Here we will pass the parameter to MapBarCode and get the result */
-  
+  char *result;                 /* Used to store the result of MapBarCode */
+  int barcode;                  /* cache the result from the BarCode function */
+  static int inv_done = 0;     /* Inventory function called ?, marker to disable recursion */
+  MBC_T *pbarcoderes;          /* Here we will pass the parameter to MapBarCode and get the result */
+
   DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, "##### START Inventory\n");
+  if ((pbarcoderes = malloc(sizeof(MBC_T))) == NULL)
+    {
+      DebugPrint(DEBUG_ERROR, SECTION_MAP_BARCODE,"##### malloc failed (-1)\n");
+      return;
+    }
   memset(pbarcoderes, 0 , sizeof(MBC_T));
 
   if (inv_done != 0)
     {
       DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, "##### STOP inv_done -> %d Inventory\n",inv_done);
+      free(pbarcoderes);
       return;
     }
   inv_done = 1;
   barcode = BarCode(INDEX_CHANGER);
-  
+
   pbarcoderes->action = RESET_VALID;
 
   MapBarCode(labelfile,pbarcoderes);
-  
+
   /*
    * Check if an tape is loaded, if yes unload it
    * and do an INIT ELEMENT STATUS
    */
-  
+
   if (pDTE[0].status == 'F')
     {
       if (eject)
@@ -661,16 +665,16 @@ void Inventory(char *labelfile, int drive, int eject, int start, int stop, int c
        }
       (void)unload(INDEX_TAPE, 0, 0);
     }
-  
+
   GenericResetStatus(INDEX_CHANGER);
+
   for (x = 0; x < STE; x++)
     {
       if (x == clean)
        {
          continue;
        }
-      
+
       /*
        * Load the tape, on error try the next
        * error could be an empty slot for example
@@ -688,10 +692,10 @@ void Inventory(char *labelfile, int drive, int eject, int start, int stop, int c
 
       SCSI_CloseDevice(INDEX_TAPE);
 
-      if ((result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &datestamp, &label)) == NULL)
+      if ((result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label)) == NULL)
       {
        pbarcoderes->action = UPDATE_SLOT;
-       strcpy(pbarcoderes->data.voltag, label);
+       strcpy(pbarcoderes->data.voltag, chgscsi_label);
        pbarcoderes->data.slot = x;
        pbarcoderes->data.from = 0;
        pbarcoderes->data.LoadCount = 1;
@@ -714,6 +718,7 @@ void Inventory(char *labelfile, int drive, int eject, int start, int stop, int c
       (void)unload(INDEX_TAPE, drive, x);
     }
   DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, "##### STOP Inventory\n");
+  free(pbarcoderes);
 }
 
 /*
@@ -748,7 +753,7 @@ int get_clean_state(char *tapedev)
   extern OpenFiles_T *pDev;
   /* Return 1 if cleaning is needed */
   int ret;
-  
+
   DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### START get_clean_state\n");
 
   if (pDev[INDEX_TAPECTL].SCSI == 0)
@@ -758,7 +763,7 @@ int get_clean_state(char *tapedev)
     }
   ret=pDev[INDEX_TAPECTL].functions->function_clean(tapedev);
   DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### STOP get_clean_state [%d]\n", ret);
-  return(ret);    
+  return(ret);
 }
 
 /*
@@ -792,7 +797,7 @@ int eject_tape(char *tapedev, int type)
        {
          SCSI_CloseDevice(INDEX_TAPE);
        }
-      
+
       chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label);
     }
 
@@ -802,7 +807,7 @@ int eject_tape(char *tapedev, int type)
       DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### STOP (SCSI)eject_tape [%d]\n", ret);
       return(ret);
     }
-  
+
   if (pDev[INDEX_TAPE].avail == 1)
     {
       ret=Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT);
@@ -832,26 +837,26 @@ int find_empty(int fd, int start, int count)
           return(-1);
         }
     }
-  
+
   if (count == 0)
     {
       end = STE;
     } else {
       end = start + count;
     }
-  
+
   if (end > STE)
     {
       end = STE;
     }
-  
+
   DebugPrint(DEBUG_INFO,SECTION_ELEMENT,"start at %d, end at %d\n", start, end);
 
   for (x = start; x < end; x++)
     {
       if (pSTE[x].status == 'E')
         {
-          DebugPrint(DEBUG_INFO,SECTION_ELEMENT,"###### END find_empty [%d]\n", x);     
+          DebugPrint(DEBUG_INFO,SECTION_ELEMENT,"###### END find_empty [%d]\n", x);
           return(x);
         }
     }
@@ -873,8 +878,8 @@ int drive_loaded(int fd, int drivenum)
 
   DebugPrint(DEBUG_INFO,SECTION_TAPE,"###### START drive_loaded\n");
   DebugPrint(DEBUG_INFO,SECTION_TAPE,"%-20s : fd %d drivenum %d \n", "drive_loaded", fd, drivenum);
-  
-  
+
+
   if (ElementStatusValid == 0)
     {
       if (pDev[INDEX_CHANGER].functions->function_status(INDEX_CHANGER, 1) != 0)
@@ -883,7 +888,7 @@ int drive_loaded(int fd, int drivenum)
          return(-1);
        }
     }
-  
+
   if (pDTE[drivenum].status == 'E') {
     DebugPrint(DEBUG_INFO,SECTION_TAPE,"###### STOP drive_loaded (empty)\n");
     return(0);
@@ -901,18 +906,23 @@ int drive_loaded(int fd, int drivenum)
  * TODO:
  * Check if the MTE is empty
  */
-int unload(int fd, int drive, int slot) 
+int unload(int fd, int drive, int slot)
 {
   extern OpenFiles_T *pDev;
   int ret;
   extern changer_t chg;         /* Needed for the infos about emubarcode and labelfile */
   extern int do_inventory;
-  MBC_T *pbarcoderes = malloc(sizeof(MBC_T));
+  MBC_T *pbarcoderes;
 
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"###### START unload\n");
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"%-20s : fd %d, slot %d, drive %d \n", "unload", fd, slot, drive);
+  if ((pbarcoderes = malloc(sizeof(MBC_T))) == NULL)
+    {
+      DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### malloc failed (-1)\n");
+      return(-1);
+    }
   memset(pbarcoderes, 0, sizeof(MBC_T));
-  
+
   /*
    * If the Element Status is not valid try to
    * init it
@@ -923,16 +933,17 @@ int unload(int fd, int drive, int slot)
        {
          DebugPrint(DEBUG_ERROR, SECTION_TAPE,"Element Status not valid, reset failed\n");
          DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP unload (-1)\n");
+         free(pbarcoderes);
          return(-1);
        }
     }
-  
-  DebugPrint(DEBUG_INFO, SECTION_TAPE,"%-20s : unload drive %d[%d] slot %d[%d]\n", "unload", 
-            drive, 
-            pDTE[drive].address, 
-            slot, 
+
+  DebugPrint(DEBUG_INFO, SECTION_TAPE,"%-20s : unload drive %d[%d] slot %d[%d]\n", "unload",
+            drive,
+            pDTE[drive].address,
+            slot,
             pSTE[slot].address);
-  
+
   /*
    * Unloading an empty tape unit makes no sense
    * so return with an error
@@ -941,32 +952,35 @@ int unload(int fd, int drive, int slot)
     {
       DebugPrint(DEBUG_ERROR, SECTION_TAPE,"unload : Drive %d address %d is empty\n", drive, pDTE[drive].address);
       DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP unload (-1)\n");
+      free(pbarcoderes);
       return(-1);
     }
-  
+
   /*
    * If the destination slot is full
    * try to find an enpty slot
    */
-  if (pSTE[slot].status == 'F')  
+  if (pSTE[slot].status == 'F')
     {
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"unload : Slot %d address %d is full\n", drive, pSTE[slot].address);
       if ( ElementStatusValid == 0)
        {
          DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, "unload: Element Status not valid, can't find an empty slot\n");
+         free(pbarcoderes);
          return(-1);
        }
-      
+
       slot = find_empty(fd, 0, 0);
       if (slot == -1 )
       {
              DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, "unload: No Empty slot found\n");
+             free(pbarcoderes);
              return(-1);
       }
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"unload : found empty one, try to unload to slot %d\n", slot);
     }
 
-  
+
 
   /*
    * If eject is not set we must read the label info
@@ -982,14 +996,14 @@ int unload(int fd, int drive, int slot)
          } else {
            pDev[INDEX_TAPE].functions->function_rewind(INDEX_TAPE);
          }
-         
+
          if (pDev[INDEX_TAPE].devopen == 1)
            {
              SCSI_CloseDevice(INDEX_TAPE);
            }
-         
+
          chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label);
-       } 
+       }
     }
 
   /*
@@ -1003,9 +1017,10 @@ int unload(int fd, int drive, int slot)
   if (pDev[INDEX_CHANGER].functions->function_status(INDEX_CHANGER , 1) != 0)
     {
       DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP unload (-1 update status failed)\n");
+      free(pbarcoderes);
       return(-1);
     }
-     
+
   /*
    * Did we get an error from tape_rdlabel
    * if no update the vol/label mapping
@@ -1020,7 +1035,7 @@ int unload(int fd, int drive, int slot)
      */
     if (BarCode(INDEX_CHANGER) == 0 && chg.emubarcode == 1)
       {
-       /* 
+       /*
         * We got something, update the db
         * but before check if the db has as entry the slot
         * to where we placed the tape, if no force an inventory
@@ -1031,8 +1046,8 @@ int unload(int fd, int drive, int slot)
        pbarcoderes->data.slot = 0;
        pbarcoderes->data.from = 0;
        pbarcoderes->data.LoadCount = 0;
-       
-       
+
+
        if ( MapBarCode(chg.labelfile, pbarcoderes) == 0) /* Nothing known about this, do an Inventory */
          {
            do_inventory = 1;
@@ -1047,6 +1062,7 @@ int unload(int fd, int drive, int slot)
   }
 
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP unload(0)\n");
+  free(pbarcoderes);
   return(0);
 }
 
@@ -1065,15 +1081,18 @@ int load(int fd, int drive, int slot)
 {
   extern changer_t chg;         /* Needed for the infos about emubarcode and labelfile */
   char *result = NULL;          /* Needed for the result of tape_rdlabel */
-  char *datestamp = NULL;       /* Result pointer for tape_rdlabel */       
-  char *label = NULL;           /* Result pointer for tape_rdlabel */
   int ret;
   extern OpenFiles_T *pDev;
   extern int do_inventory;
-  MBC_T *pbarcoderes = malloc(sizeof(MBC_T));
+  MBC_T *pbarcoderes;
 
   DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"###### START load\n");
   DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"%-20s : fd %d, drive %d, slot %d \n", "load", fd, drive, slot);
+  if ((pbarcoderes = malloc(sizeof(MBC_T))) == NULL)
+    {
+      DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### malloc failed (-1)\n");
+      return(-1);
+    }
   memset(pbarcoderes, 0 , sizeof(MBC_T));
 
   if (ElementStatusValid == 0)
@@ -1082,6 +1101,7 @@ int load(int fd, int drive, int slot)
               {
                DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### STOP load (-1)\n");
                DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### STOP load (-1 update status failed)\n");
+               free(pbarcoderes);
                return(-1);
               }
       }
@@ -1094,16 +1114,16 @@ int load(int fd, int drive, int slot)
    */
   if (slot >= STE)
     {
-      DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"load : slot %d ge STE %d\n",slot, STE); 
+      DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"load : slot %d ge STE %d\n",slot, STE);
       ChgExit("load", "slot >= STE", FATAL);
     }
-  
-  /* 
+
+  /*
    * And the same for the tape drives
    */
   if (drive >= DTE)
     {
-      DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"load : drive %d ge DTE %d\n",drive, DTE); 
+      DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"load : drive %d ge DTE %d\n",drive, DTE);
       ChgExit("load", "drive >= DTE", FATAL);
     }
 
@@ -1111,21 +1131,23 @@ int load(int fd, int drive, int slot)
             pDTE[drive].address,
             slot,
             pSTE[slot].address);
-  
+
   if (pDTE[drive].status == 'F')
     {
       DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"load : Drive %d address %d is full\n", drive, pDTE[drive].address);
       DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### STOP load (-1 update status failed)\n");
+      free(pbarcoderes);
       return(-1);
     }
-  
+
   if (pSTE[slot].status == 'E')
     {
       DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"load : Slot %d address %d is empty\n", drive, pSTE[slot].address);
       DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### STOP load (-1 update status failed)\n");
+      free(pbarcoderes);
       return(-1);
     }
-  
+
   ret = pDev[fd].functions->function_move(fd, pSTE[slot].address, pDTE[drive].address);
 
   /*
@@ -1134,6 +1156,7 @@ int load(int fd, int drive, int slot)
   if (pDev[fd].functions->function_status(fd, 1) != 0)
       {
        DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### STOP load (-1 update status failed)\n");
+       free(pbarcoderes);
        return(-1);
       }
 
@@ -1149,38 +1172,38 @@ int load(int fd, int drive, int slot)
       } else {
        pDev[INDEX_TAPE].functions->function_rewind(INDEX_TAPE);
       }
-      
+
       if (pDev[INDEX_TAPE].devopen == 1)
        {
          SCSI_CloseDevice(INDEX_TAPE);
        }
-      
-      result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &datestamp, &label);
+
+      result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label);
     }
-  
+
   /*
    * Did we get an error from tape_rdlabel
    * if no update the vol/label mapping
    */
-  if (result  == NULL && chg.labelfile != NULL && label != NULL )
+  if (result  == NULL && chg.labelfile != NULL && chgscsi_label != NULL )
     {
-      /* 
+      /*
        * We got something, update the db
        * but before check if the db has as entry the slot
        * to where we placed the tape, if no force an inventory
        */
-      strcpy(pbarcoderes->data.voltag, label);
+      strcpy(pbarcoderes->data.voltag, chgscsi_label);
       pbarcoderes->data.slot = 0;
       pbarcoderes->data.from = 0;
       pbarcoderes->data.LoadCount = 0;
-      
-      
+
+
       /*
        * If we have an barcode reader we only do an update
        * If emubarcode is set we check if the
        * info in the DB is up to date, if no we set the do_inventory flag
        */
-      
+
       if (BarCode(INDEX_CHANGER) == 1 && chg.emubarcode == 0)
        {
          pbarcoderes->action = UPDATE_SLOT;
@@ -1189,7 +1212,7 @@ int load(int fd, int drive, int slot)
          pbarcoderes->data.slot = slot;
          MapBarCode(chg.labelfile, pbarcoderes);
        }
-      
+
       if (BarCode(INDEX_CHANGER) == 0 && chg.emubarcode == 1)
        {
          pbarcoderes->action = FIND_SLOT;
@@ -1209,16 +1232,18 @@ int load(int fd, int drive, int slot)
                }
            }
        }
-      
+
       if (BarCode(INDEX_CHANGER) == 1 && chg.emubarcode == 1)
        {
          ChgExit("Load", "BarCode == 1 and emubarcode == 1", FATAL);
        }
-      
+
       DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"##### STOP load (%d)\n",ret);
+      free(pbarcoderes);
       return(ret);
     }
     DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"##### STOP load (%d)\n",ret);
+    free(pbarcoderes);
     return(ret);
 }
 
@@ -1226,7 +1251,7 @@ int load(int fd, int drive, int slot)
  * Returns the number of Storage Slots which the library has
  * fd -> pointer to the internal devie structure pDev
  * return -> Number of slots
- */ 
+ */
 int get_slot_count(int fd)
 {
   extern OpenFiles_T *pDev;
@@ -1244,7 +1269,7 @@ int get_slot_count(int fd)
    * return the number of slots in the robot
    * to the caller
    */
-  
+
 }
 
 
@@ -1252,7 +1277,7 @@ int get_slot_count(int fd)
  * retreive the number of data-transfer devices /Tape drives)
  * fd     -> pointer to the internal devie structure pDev
  * return -> -1 on failure
- */ 
+ */
 int get_drive_count(int fd)
 {
 
@@ -1289,12 +1314,12 @@ int OpenDevice(int ip , char *DeviceName, char *ConfigName, char *ident)
   extern OpenFiles_T *pDev;
   char tmpstr[15];
   ChangerCMD_T *p = (ChangerCMD_T *)&ChangerIO;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### START OpenDevice\n");
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"OpenDevice : %s\n", DeviceName);
-  
-  pDev[ip].ConfigName = stralloc(ConfigName);
-  pDev[ip].dev = stralloc(DeviceName);
+
+  pDev[ip].ConfigName = strdup(ConfigName);
+  pDev[ip].dev = strdup(DeviceName);
 
   if (SCSI_OpenDevice(ip) != 0 )
     {
@@ -1341,12 +1366,12 @@ int OpenDevice(int ip , char *DeviceName, char *ConfigName, char *ident)
               return(1);
             }
           p++;
-        }  
+        }
     } else { /* Something failed, lets see what */
       DebugPrint(DEBUG_ERROR, SECTION_SCSI,"##### STOP OpenDevice failed\n");
     }
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP OpenDevice (nothing found) !!\n");
-  return(0); 
+  return(0);
 }
 
 
@@ -1383,12 +1408,12 @@ int Tape_Ready(int fd, int wait_time)
   int true = 1;
   int ret;
   int cnt = 0;
-  
+
   RequestSense_T *pRequestSense;
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### START Tape_Ready\n");
-  
+
   /*
-   * Which device should we use to get the 
+   * Which device should we use to get the
    * tape status
    */
 
@@ -1399,7 +1424,7 @@ int Tape_Ready(int fd, int wait_time)
     {
       fd = INDEX_TAPE;
     }
-  
+
   /*
    * But if available and can do SCSI
    * the scsitapedev
@@ -1408,14 +1433,14 @@ int Tape_Ready(int fd, int wait_time)
     {
       fd = INDEX_TAPECTL;
     }
-  
+
   if (pDev[fd].avail == 1 && pDev[fd].SCSI == 0)
     {
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"Tape_Ready : Can't send SCSI commands, try ioctl\n");
       /*
        * Do we get an non negative result.
        * If yes this function is available
-       * and we can use it to get the status 
+       * and we can use it to get the status
        * of the tape
        */
       ret = Tape_Status(fd);
@@ -1437,7 +1462,7 @@ int Tape_Ready(int fd, int wait_time)
          DebugPrint(DEBUG_INFO, SECTION_TAPE,"Tape_Ready : not ready, stop after %d seconds\n",cnt);
          DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP Tape_Ready\n");
          return(0);
-         
+
        } else {
          DebugPrint(DEBUG_INFO, SECTION_TAPE,"Tape_Ready : no ioctl interface, will sleep for %d seconds\n", wait_time);
          sleep(wait_time);
@@ -1445,23 +1470,23 @@ int Tape_Ready(int fd, int wait_time)
          return(0);
        }
     }
-  
+
   if ((pRequestSense = (RequestSense_T *)malloc(sizeof(RequestSense_T))) == NULL)
     {
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"Tape_Ready : malloc failed\n");
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP Tape_Ready\n");
       return(-1);
     }
-  
+
   /*
    * Ignore errors at this point
    */
   GenericRewind(fd);
-  
+
   /*
    * Wait until we get an ready condition
    */
-  
+
   while (true && cnt < wait_time)
     {
       ret = SCSI_TestUnitReady(fd, pRequestSense );
@@ -1486,6 +1511,7 @@ int Tape_Ready(int fd, int wait_time)
              break;
            case SENSE_ABORT:
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"TapeReady (TestUnitReady) SENSE_ABORT\n");
+             free(pRequestSense);
              return(-1);
              break;
            case SENSE_RETRY:
@@ -1499,6 +1525,7 @@ int Tape_Ready(int fd, int wait_time)
          break;
        case SCSI_ERROR:
          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"TapeReady (TestUnitReady) SCSI_ERROR\n");
+         free(pRequestSense);
          return(-1);
          break;
        case SCSI_BUSY:
@@ -1515,10 +1542,9 @@ int Tape_Ready(int fd, int wait_time)
       cnt++;
     }
 
-  free(pRequestSense);
-
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"Tape_Ready after %d sec\n", cnt);
-  DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP Tape_Ready\n"); 
+  DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP Tape_Ready\n");
+  free(pRequestSense);
   return(0);
 }
 
@@ -1563,7 +1589,7 @@ int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *o
 
   /* Jump over the Parameter List header  and an offset if we have something
    * Unknown at the start (ADIC-218) at the moment
-   * 
+   *
    */
   buffer = buffer + 4 + offset;
 
@@ -1583,7 +1609,7 @@ int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *o
        fprintf(out, "DecodeModeSense : Block Length %d\n", V3(buffer));
       buffer = buffer + 3;
     }
-  
+
   while (length > 0)
     {
       switch (*buffer & 0x3f)
@@ -1595,7 +1621,7 @@ int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *o
         case 0x1:
           prp = (ReadWriteErrorRecoveryPage_T *)buffer;
          if (out != NULL)
-          { 
+          {
                fprintf(out, "DecodeModeSense : Read/Write Error Recovery Page\n");
                fprintf(out,"\tTransfer Block            %d\n", prp->tb);
                fprintf(out,"\tEnable Early Recovery     %d\n", prp->eer);
@@ -1614,9 +1640,9 @@ int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *o
                fprintf(out, "DecodeModeSense : Disconnect/Reconnect Page\n");
                fprintf(out,"\tBuffer Full Ratio     %d\n", pdrp->BufferFullRatio);
                fprintf(out,"\tBuffer Empty Ratio    %d\n", pdrp->BufferEmptyRatio);
-               fprintf(out,"\tBus Inactivity Limit  %d\n", 
+               fprintf(out,"\tBus Inactivity Limit  %d\n",
                   V2(pdrp->BusInactivityLimit));
-               fprintf(out,"\tDisconnect Time Limit %d\n", 
+               fprintf(out,"\tDisconnect Time Limit %d\n",
                   V2(pdrp->DisconnectTimeLimit));
                fprintf(out,"\tConnect Time Limit    %d\n",
                   V2(pdrp->ConnectTimeLimit));
@@ -1631,21 +1657,21 @@ int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *o
          if (out != NULL)
          {
                fprintf(out,"DecodeModeSense : Element Address Assignment Page\n");
-               fprintf(out,"\tMedium Transport Element Address     %d\n", 
+               fprintf(out,"\tMedium Transport Element Address     %d\n",
                     V2(pEAAPage->MediumTransportElementAddress));
-               fprintf(out,"\tNumber of Medium Transport Elements  %d\n", 
+               fprintf(out,"\tNumber of Medium Transport Elements  %d\n",
                     V2(pEAAPage->NoMediumTransportElements));
-               fprintf(out, "\tFirst Storage Element Address       %d\n", 
+               fprintf(out, "\tFirst Storage Element Address       %d\n",
                     V2(pEAAPage->FirstStorageElementAddress));
-               fprintf(out, "\tNumber of  Storage Elements         %d\n", 
+               fprintf(out, "\tNumber of  Storage Elements         %d\n",
                     V2(pEAAPage->NoStorageElements));
-               fprintf(out, "\tFirst Import/Export Element Address %d\n", 
+               fprintf(out, "\tFirst Import/Export Element Address %d\n",
                     V2(pEAAPage->FirstImportExportElementAddress));
-               fprintf(out, "\tNumber of  ImportExport Elements    %d\n", 
+               fprintf(out, "\tNumber of  ImportExport Elements    %d\n",
                     V2(pEAAPage->NoImportExportElements));
-               fprintf(out, "\tFirst Data Transfer Element Address %d\n", 
+               fprintf(out, "\tFirst Data Transfer Element Address %d\n",
                     V2(pEAAPage->FirstDataTransferElementAddress));
-               fprintf(out, "\tNumber of  Data Transfer Elements   %d\n", 
+               fprintf(out, "\tNumber of  Data Transfer Elements   %d\n",
                     V2(pEAAPage->NoDataTransferElements));
          }
           buffer++;
@@ -1707,7 +1733,7 @@ int DecodeModeSense(char *buffer, int offset, char *pstring, char block, FILE *o
           return(-1);
         }
       length = length - *buffer - 2;
-      buffer = buffer + *buffer + 1;      
+      buffer = buffer + *buffer + 1;
     }
   return(0);
 }
@@ -1781,7 +1807,7 @@ int DecodeSense(RequestSense_T *sense, char *pstring, FILE *out)
       fprintf(out,"\t\tReserved\n");
       break;
     }
-  return(0);      
+  return(0);
 }
 
 int DecodeExtSense(ExtendedRequestSense_T *sense, char *pstring, FILE *out)
@@ -1796,7 +1822,7 @@ int DecodeExtSense(ExtendedRequestSense_T *sense, char *pstring, FILE *out)
   fprintf(out,"\tLog Parameter Page Code         %02X\n", sense->LogParameterPageCode);
   fprintf(out,"\tLog Parameter Code              %02X\n", sense->LogParameterCode);
   fprintf(out,"\tUnderrun/Overrun Counter        %02X\n", sense->UnderrunOverrunCounter);
-  fprintf(out,"\tRead/Write Error Counter        %d\n", V3((char *)sense->ReadWriteDataErrorCounter)); 
+  fprintf(out,"\tRead/Write Error Counter        %d\n", V3((char *)sense->ReadWriteDataErrorCounter));
   if (sense->AdditionalSenseLength > sizeof(RequestSense_T))
     {
       if (sense->PF)
@@ -1903,18 +1929,18 @@ int TreeFrogBarCode(int DeviceFD)
           return(-1);
         }
     }
-  
+
   if (SCSI_ModeSense(DeviceFD, pModePage, 0xff, 0x0, 0x3f) == 0)
     {
       DecodeModeSense(pModePage, 0, "TreeFrogBarCode :", 0, debug_file);
-      
+
       if (pVendorUnique == NULL)
       {
          dbprintf(("TreeFrogBarCode : no pVendorUnique\n"));
          return(0);
       }
       pVendor = ( ModePageTreeFrogVendorUnique_T *)pVendorUnique;
-    
+
       dbprintf(("TreeFrogBarCode : EBARCO %d\n", pVendor->EBARCO));
       dbprintf(("TreeFrogCheckSum : CHKSUM  %d\n", pVendor->CHKSUM));
 
@@ -1929,7 +1955,7 @@ int EXB_BarCode(int DeviceFD)
   extern OpenFiles_T *pDev;
 
   ModePageEXB120VendorUnique_T *pVendor;
-  ModePageEXB120VendorUnique_T *pVendorWork;
+  ModePageEXB120VendorUnique_T *pVendorWork = NULL;
 
   DebugPrint(DEBUG_INFO, SECTION_BARCODE,"##### START EXB_BarCode\n");
   if (pModePage == NULL && LibModeSenseValid == 0)
@@ -1947,7 +1973,7 @@ int EXB_BarCode(int DeviceFD)
          LibModeSenseValid = -1;
        }
     }
-  
+
   if (LibModeSenseValid == 1)
     {
       if (pVendorUnique == NULL)
@@ -1956,7 +1982,7 @@ int EXB_BarCode(int DeviceFD)
          return(0);
       }
       pVendor = ( ModePageEXB120VendorUnique_T *)pVendorUnique;
-    
+
       DebugPrint(DEBUG_INFO, SECTION_BARCODE,"EXB_BarCode : NBL %d\n", pVendor->NBL);
       DebugPrint(DEBUG_INFO, SECTION_BARCODE,"EXB_BarCode : PS  %d\n", pVendor->PS);
       if (pVendor->NBL == 1 && pVendor->PS == 1 )
@@ -1977,19 +2003,20 @@ int EXB_BarCode(int DeviceFD)
               /* Hack !!!!!!
                */
               pVendor->NBL = 0;
-              
+
               /* And now again !!!
                */
               GenericResetStatus(DeviceFD);
             } else {
               DebugPrint(DEBUG_INFO, SECTION_BARCODE,"EXB_BarCode : SCSI_ModeSelect failed\n");
             }
+           amfree(pVendorWork);
         }
       dump_hex((char *)pDev[INDEX_CHANGER].inquiry, INQUIRY_SIZE, DEBUG_INFO, SECTION_BARCODE);
       DebugPrint(DEBUG_INFO, SECTION_BARCODE,"EXB_BarCode : vendor_specific[19] %x\n",
                 pDev[INDEX_CHANGER].inquiry->vendor_specific[19]);
     }
-  
+
   return(1);
 }
 
@@ -2003,7 +2030,7 @@ int NoBarCode(int DeviceFD)
 int GenericBarCode(int DeviceFD)
 {
   extern changer_t chg;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_BARCODE,"##### START GenericBarCode\n");
   if ( chg.havebarcode  >= 1)
     {
@@ -2048,7 +2075,7 @@ int TapeStatus()
   int ret;
   int true = 1;
   int cnt = 0;
-  RequestSense_T *pRequestSense;
+  RequestSense_T *pRequestSense = NULL;
 
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### START TapeStatus\n");
 
@@ -2064,7 +2091,7 @@ int TapeStatus()
          dbprintf(("%-20s : malloc failed\n","TapeStatus"));
          return(-1);
        }
-      
+
       while (true && cnt < 60)
        {
          ret = SCSI_TestUnitReady(INDEX_TAPECTL, pRequestSense);
@@ -2117,11 +2144,12 @@ int TapeStatus()
          sleep(2);
          cnt++;
        }
+        amfree(pRequestSense);
     } else {
       ret = Tape_Status(INDEX_TAPE);
       if ( ret & TAPE_ONLINE)
        {
-         pDTE[0].status ='F'; 
+         pDTE[0].status ='F';
          DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### FULL\n");
        } else {
          pDTE[0].status = 'E';
@@ -2153,47 +2181,49 @@ int DLT4000Eject(char *Device, int type)
   if ((pExtendedRequestSense = malloc(sizeof(ExtendedRequestSense_T))) == NULL)
     {
       dbprintf(("%-20s : malloc failed\n","DLT4000Eject"));
+      free(pRequestSense);
       return(-1);
     }
-    
+
   if ( type > 1)
     {
       dbprintf(("DLT4000Eject : use mtio ioctl for eject on %s\n", pDev[INDEX_TAPE].dev));
+      free(pExtendedRequestSense);
+      free(pRequestSense);
       return(Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT));
     }
-  
-  
-  
+
+
+
   if (pDev[INDEX_TAPECTL].SCSI == 0)
     {
       dbprintf(("DLT4000Eject : Device %s not able to receive SCSI commands\n", pDev[INDEX_TAPE].dev));
+      free(pExtendedRequestSense);
+      free(pRequestSense);
       return(Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT));
     }
-  
-  
+
+
   dbprintf(("DLT4000Eject : SCSI eject on %s = %s\n", pDev[INDEX_TAPECTL].dev, pDev[INDEX_TAPECTL].ConfigName));
-  
-  RequestSense(INDEX_TAPECTL, pExtendedRequestSense, 0); 
+
+  RequestSense(INDEX_TAPECTL, pExtendedRequestSense, 0);
   DecodeExtSense(pExtendedRequestSense, "DLT4000Eject : ", debug_file);
   /* Unload the tape, 0 ==  wait for success
-   * 0 == unload 
+   * 0 == unload
    */
   ret = SCSI_LoadUnload(INDEX_TAPECTL, pRequestSense, 0, 0);
 
-  RequestSense(INDEX_TAPECTL, pExtendedRequestSense, 0); 
+  RequestSense(INDEX_TAPECTL, pExtendedRequestSense, 0);
   DecodeExtSense(pExtendedRequestSense, "DLT4000Eject : ", debug_file);
-  
+
   /* < 0 == fatal */
-  if (ret < 0)
-    return(-1);
-  
-  if ( ret > 0)
-    {
+  if (ret >= 0) {
+      free(pExtendedRequestSense);
+      free(pRequestSense);
+      return(-1);
     }
-  
+
   true = 1;
-  
-  
   while (true && cnt < 300)
     {
       ret = SCSI_TestUnitReady(INDEX_TAPECTL, pRequestSense);
@@ -2220,8 +2250,9 @@ int DLT4000Eject(char *Device, int type)
              break;
            case SENSE_ABORT:
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"DLT4000Eject (TestUnitReady) SENSE_ABORT\n");
+             free(pExtendedRequestSense);
+             free(pRequestSense);
              return(-1);
-             break;
            case SENSE_RETRY:
              DebugPrint(DEBUG_INFO, SECTION_SCSI,"DLT4000Eject (TestUnitReady) SENSE_RETRY\n");
              break;
@@ -2233,8 +2264,9 @@ int DLT4000Eject(char *Device, int type)
          break;
        case SCSI_ERROR:
          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"DLT4000Eject (TestUnitReady) SCSI_ERROR\n");
+         free(pExtendedRequestSense);
+         free(pRequestSense);
          return(-1);
-         break;
        case SCSI_BUSY:
          DebugPrint(DEBUG_INFO, SECTION_SCSI,"DLT4000Eject (TestUnitReady) SCSI_BUSY\n");
          break;
@@ -2245,17 +2277,17 @@ int DLT4000Eject(char *Device, int type)
          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"DLT4000Eject (TestUnitReady) unknown (%d)\n",ret);
          break;
        }
-      
+
       cnt++;
       sleep(2);
     }
-  
-  
-  free(pRequestSense);
-  
+
   dbprintf(("DLT4000Eject : Ready after %d sec, true = %d\n", cnt * 2, true));
+
+  free(pExtendedRequestSense);
+  free(pRequestSense);
+
   return(0);
-  
 }
 
 /*
@@ -2273,40 +2305,37 @@ int GenericEject(char *Device, int type)
   int ret;
   int cnt = 0;
   int true = 1;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_TAPE, "##### START GenericEject\n");
-  
+
   if ((pRequestSense = malloc(sizeof(RequestSense_T))) == NULL)
     {
       DebugPrint(DEBUG_ERROR, SECTION_TAPE, "%-20s : malloc failed\n","GenericEject");
       return(-1);
     }
-    
-  DebugPrint(DEBUG_INFO, SECTION_TAPE,"GenericEject : SCSI eject on %s = %s\n", pDev[INDEX_TAPECTL].dev, pDev[INDEX_TAPECTL].ConfigName);
-  
+
+  DebugPrint(DEBUG_INFO, SECTION_TAPE,"GenericEject : SCSI eject on %s = %s\n",
+             pDev[INDEX_TAPECTL].dev, pDev[INDEX_TAPECTL].ConfigName);
+
   /*
    * Can we use SCSI commands ?
    */
   if (pDev[INDEX_TAPECTL].SCSI == 1)
     {
       LogSense(INDEX_TAPECTL);
-      /* 
+      /*
        * Unload the tape, 1 == don't wait for success
-       * 0 == unload 
+       * 0 == unload
        */
       ret = SCSI_LoadUnload(INDEX_TAPECTL, pRequestSense, 1, 0);
-      
+
       /* < 0 == fatal */
-      if (ret < 0)
+      if (ret < 0) {
+       free(pRequestSense);
        return(-1);
-      
-      if ( ret > 0)
-       {
-       }
-      
+      }
+
       true = 1;
-      
-      
       while (true && cnt < 300)
        {
          ret = SCSI_TestUnitReady(INDEX_TAPECTL, pRequestSense);
@@ -2329,8 +2358,8 @@ int GenericEject(char *Device, int type)
                  break;
                case SENSE_ABORT:
                  DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericEject (TestUnitReady) SENSE_ABORT\n");
+                 free(pRequestSense);
                  return(-1);
-                 break;
                case SENSE_RETRY:
                  DebugPrint(DEBUG_INFO, SECTION_SCSI,"GenericEject (TestUnitReady) SENSE_RETRY\n");
                  break;
@@ -2341,8 +2370,8 @@ int GenericEject(char *Device, int type)
              break;
            case SCSI_ERROR:
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericEject (TestUnitReady) SCSI_ERROR\n");
+             free(pRequestSense);
              return(-1);
-             break;
            case SCSI_BUSY:
              DebugPrint(DEBUG_INFO, SECTION_SCSI,"GenericEject (TestUnitReady) SCSI_BUSY\n");
              break;
@@ -2352,23 +2381,21 @@ int GenericEject(char *Device, int type)
            default:
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericEject (TestUnitReady) unknown (%d)\n",ret);
              break;
-           }  
+           }
          cnt++;
          sleep(2);
        }
-      
-      free(pRequestSense);
-      
     } else {
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"GenericEject : Device can't understand SCSI try ioctl\n");
       Tape_Ioctl(INDEX_TAPECTL, IOCTL_EJECT);
     }
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"GenericEject : Ready after %d sec, true = %d\n", cnt * 2, true);
+  free(pRequestSense);
   return(0);
 }
 
 /*
- * Rewind the tape 
+ * Rewind the tape
  *
  * TODO:
  * Make the retry counter an config option,
@@ -2380,8 +2407,8 @@ int GenericEject(char *Device, int type)
 int GenericRewind(int DeviceFD)
 {
   CDB_T CDB;
-  extern OpenFiles_T *pDev; 
-  RequestSense_T *pRequestSense;
+  extern OpenFiles_T *pDev;
+  RequestSense_T *pRequestSense = NULL;
   char *errstr;                    /* Used by tape_rewind */
   int ret;
   int cnt = 0;
@@ -2404,7 +2431,7 @@ int GenericRewind(int DeviceFD)
       /*
        * Before doing the rewind check if the tape is ready to accept commands
        */
-      
+
       while (true == 1)
        {
          ret = SCSI_TestUnitReady(DeviceFD, (RequestSense_T *)pRequestSense );
@@ -2423,6 +2450,7 @@ int GenericRewind(int DeviceFD)
                  break;
                case SENSE_TAPE_NOT_ONLINE:
                  DebugPrint(DEBUG_INFO, SECTION_SCSI,"GenericRewind (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n");
+                 free(pRequestSense);
                  return(-1);
                  break;
                case SENSE_IGNORE:
@@ -2431,6 +2459,7 @@ int GenericRewind(int DeviceFD)
                  break;
                case SENSE_ABORT:
                  DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericRewind (TestUnitReady) SENSE_ABORT\n");
+                 free(pRequestSense);
                  return(-1);
                  break;
                case SENSE_RETRY:
@@ -2445,6 +2474,7 @@ int GenericRewind(int DeviceFD)
 
            case SCSI_ERROR:
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericRewind (TestUnitReady) SCSI_ERROR\n");
+             free(pRequestSense);
              return(-1);
              break;
            case SCSI_BUSY:
@@ -2457,36 +2487,37 @@ int GenericRewind(int DeviceFD)
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericRewind (TestUnitReady) unknown (%d)\n",ret);
              break;
            }
-         
+
          sleep(1);
          DebugPrint(DEBUG_INFO, SECTION_TAPE," Wait .... (%d)\n",cnt);
          if (cnt > 180)
            {
              DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP GenericRewind (-1)\n");
+             free(pRequestSense);
              return(-1);
            }
        } /* while true == 1 */
-      
+
       cnt = 0;
       true = 1;
-      
+
       CDB[0] = SC_COM_REWIND;
-      CDB[1] = 1;             
+      CDB[1] = 1;
       CDB[2] = 0;
       CDB[3] = 0;
       CDB[4] = 0;
       CDB[5] = 0;
-      
+
       while (true)
        {
          ret = SCSI_Run(DeviceFD, Input, CDB, 6,
-                        NULL, 0, 
+                        NULL, 0,
                         (char *) pRequestSense,
                         sizeof(RequestSense_T));
-         
+
          DecodeSense(pRequestSense, "GenericRewind : ", debug_file);
-         
-         if (ret > 0) 
+
+         if (ret > 0)
            {
              if (pRequestSense->SenseKey != UNIT_ATTENTION)
                {
@@ -2503,9 +2534,9 @@ int GenericRewind(int DeviceFD)
              true = 0;
            }
        }
-      
+
       true = 1;
-      
+
       while (true && cnt < 300)
        {
          ret = SCSI_TestUnitReady(DeviceFD, pRequestSense);
@@ -2524,6 +2555,7 @@ int GenericRewind(int DeviceFD)
                  break;
                case SENSE_TAPE_NOT_ONLINE:
                  DebugPrint(DEBUG_INFO, SECTION_SCSI,"GenericRewind (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n");
+                 free(pRequestSense);
                  return(-1);
                  break;
                case SENSE_IGNORE:
@@ -2532,6 +2564,7 @@ int GenericRewind(int DeviceFD)
                  break;
                case SENSE_ABORT:
                  DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericRewind (TestUnitReady) SENSE_ABORT\n");
+                 free(pRequestSense);
                  return(-1);
                  break;
                case SENSE_RETRY:
@@ -2545,8 +2578,9 @@ int GenericRewind(int DeviceFD)
              break;
            case SCSI_ERROR:
              DebugPrint(DEBUG_ERROR, SECTION_SCSI,"GenericRewind (TestUnitReady) SCSI_ERROR\n");
+             free(pRequestSense);
              return(-1);
-             break;     
+             break;
            case SCSI_BUSY:
              DebugPrint(DEBUG_INFO, SECTION_SCSI,"GenericRewind (TestUnitReady) SCSI_BUSY\n");
              break;
@@ -2561,47 +2595,32 @@ int GenericRewind(int DeviceFD)
          cnt++;
          sleep(2);
        }
-      
-      free(pRequestSense);
-      
+
+      amfree(pRequestSense);
+
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"GenericRewind : Ready after %d sec, true = %d\n", cnt * 2, true);
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP GenericRewind (0)\n");
     } else {
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"GenericRewind : use ioctl rewind\n");
-      if (pDev[DeviceFD].devopen == 1) 
+      if (pDev[DeviceFD].devopen == 1)
        {
          DebugPrint(DEBUG_INFO, SECTION_TAPE,"Close Device\n");
          SCSI_CloseDevice(DeviceFD);
        }
-      /*
-       * Hmm retry it if it fails ?
-       */
-      cnt = 0;
-      true = 1;
-      while (true) 
-       {
-         if ((errstr = tape_rewind(pDev[DeviceFD].dev)) == NULL)
-           {
-             true = 0;
-             DebugPrint(DEBUG_INFO, SECTION_TAPE,"Rewind OK, (after %d tries)\n", cnt);
-           } else {
-             DebugPrint(DEBUG_INFO, SECTION_TAPE,"Rewind failed %s\n",errstr);
-             /*
-              * DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP GenericRewind (-1)\n");
-              * return(-1);
-              */
-             cnt++;
-             sleep(1);
-             if (cnt > 60)
-               {
-                 DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP GenericRewind (-1), retry limit reached\n");
-                 return(-1);
-               }
-           }
-       }
+      /* We don't retry if it fails; that is left to the vtape driver. */
+      if ((errstr = tape_rewind(pDev[DeviceFD].dev)) == NULL) {
+          true = 0;
+          DebugPrint(DEBUG_INFO, SECTION_TAPE,"Rewind OK,\n", cnt);
+      } else {
+          DebugPrint(DEBUG_ERROR, SECTION_TAPE,"Rewind failed %s\n",errstr);
+          DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP GenericRewind (-1)\n");
+         amfree(pRequestSense);
+          return(-1);
+      }
       DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP GenericRewind (0)\n");
     }
 
+  amfree(pRequestSense);
   return(0);
 }
 
@@ -2630,7 +2649,7 @@ int GenericClean(char * Device)
    */
   if ( RequestSense(INDEX_TAPECTL, &ExtRequestSense, 1) == 0)
     {
-      
+
       DecodeExtSense(&ExtRequestSense, "GenericClean : ", debug_file);
       if(ExtRequestSense.CLN) {
        ret = 1;
@@ -2650,9 +2669,9 @@ int GenericResetStatus(int DeviceFD)
   RequestSense_T *pRequestSense;
   int ret = 0;
   int retry = 1;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_ELEMENT, "##### START GenericResetStatus\n");
-  
+
   if ((pRequestSense = (RequestSense_T *)malloc(sizeof(RequestSense_T))) == NULL)
       {
           DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, "GenericResetStatus : malloc failed\n");
@@ -2681,6 +2700,7 @@ int GenericResetStatus(int DeviceFD)
           /*        for (i = 1; i < sizeof(RequestSense_T); i++)                */
           /*          fprintf(stderr, " %02X", ((unsigned char *) &pRequestSense)[i]); */
           /*        fprintf(stderr, "\n");    */
+         free(pRequestSense);
           return(ret);
         }
       if ( ret > 0 )
@@ -2688,9 +2708,11 @@ int GenericResetStatus(int DeviceFD)
           switch (SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, (char *)pRequestSense))
             {
             case SENSE_IGNORE:
+             free(pRequestSense);
               return(0);
               break;
             case SENSE_ABORT:
+             free(pRequestSense);
               return(-1);
               break;
             case SENSE_RETRY:
@@ -2701,11 +2723,13 @@ int GenericResetStatus(int DeviceFD)
                   sleep(2);
                 } else {
                  DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, "GenericResetStatus : return (-1)\n");
+                 free(pRequestSense);
                   return(-1);
                 }
               break;
             default:
              DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, "GenericResetStatus :  (default) return (-1)\n");
+             free(pRequestSense);
               return(-1);
               break;
             }
@@ -2714,6 +2738,7 @@ int GenericResetStatus(int DeviceFD)
         retry = 0;
     }
   DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, "##### STOP GenericResetStatus (%d)\n",ret);
+  free(pRequestSense);
   return(ret);
 }
 
@@ -2722,7 +2747,7 @@ int GenericResetStatus(int DeviceFD)
  * pwork is an pointer to the structure OpenFiles_T, which is filled with information
  * about the device to which we talk. Information are for example
  * The vendor, the ident, which fd, etc. This strucure is filled when we open the
- * device 
+ * device
  * flag tells how to handle the information passed in the buffer,
  * 0 -> Sense Key available
  * 1 -> No Sense key available
@@ -2732,23 +2757,23 @@ int GenericResetStatus(int DeviceFD)
  * Limit recursion, may run in an infinite loop
  */
 int GenericSenseHandler(int ip, int flag, unsigned char SenseKey, unsigned char AdditionalSenseCode, unsigned char AdditionalSenseCodeQualifier, char *buffer)
-{ 
+{
   extern OpenFiles_T *pDev;
   RequestSense_T *pRequestSense = (RequestSense_T *)buffer;
   int ret = 0;
   unsigned char *info = NULL;
-  
+
   dbprintf(("##### START GenericSenseHandler\n"));
-  
+
   DecodeSense(pRequestSense, "GenericSenseHandler : ", debug_file);
-  
+
   ret = Sense2Action(pDev[ip].ident,
                     pDev[ip].inquiry->type,
                     flag, SenseKey,
                     AdditionalSenseCode,
                     AdditionalSenseCodeQualifier,
                     (char **)&info);
-  
+
   dbprintf(("##### STOP GenericSenseHandler\n"));
   return(ret);
 }
@@ -2762,7 +2787,7 @@ int GenericSenseHandler(int ip, int flag, unsigned char SenseKey, unsigned char
  * Return:
  *         == 0 -> success
  *         != 0 -> error either from the SCSI command or from
- *                 the element handling 
+ *                 the element handling
  * TODO:
 */
 int SDXMove(int DeviceFD, int from, int to)
@@ -2778,32 +2803,32 @@ int SDXMove(int DeviceFD, int from, int to)
   int SDX_DTE = -1;     /* AlignElements               */
 
   DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### START SDXMove\n");
-  
+
   DebugPrint(DEBUG_INFO, SECTION_MOVE,"%-20s : from = %d, to = %d\n", "SDXMove", from, to);
 
-  
+
   if ((pfrom = LookupElement(from)) == NULL)
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"SDXMove : ElementInfo for %d not found\n", from);
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### STOP SDXMove\n");
       return(-1);
     }
-  
+
   if ((pto = LookupElement(to)) == NULL)
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"SDXMove : ElementInfo for %d not found\n", to);
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### STOP SDXMove\n");
       return(-1);
     }
-  
-  if (pfrom->status == 'E') 
+
+  if (pfrom->status == 'E')
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"SDXMove : from %d is empty\n", from);
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### STOP SDXMove\n");
       return(-1);
     }
 
-  if (pto->status == 'F') 
+  if (pto->status == 'F')
     {
       switch (pto->status)
       {
@@ -2876,9 +2901,9 @@ int SDXMove(int DeviceFD, int from, int to)
     return(-1);
   }
 
-  /* 
-   * If from is a tape we must check if it is loaded 
-   * and if yes we have to eject it                  
+  /*
+   * If from is a tape we must check if it is loaded
+   * and if yes we have to eject it
   */
   if (pfrom->type == TAPETYPE)
   {
@@ -2886,7 +2911,7 @@ int SDXMove(int DeviceFD, int from, int to)
     if ( tapestat & TAPE_ONLINE)
     {
       if (pDev[INDEX_TAPECTL].SCSI == 1)
-      { 
+      {
         ret = eject_tape(pDev[INDEX_TAPECTL].dev,1);
       } else {
         ret = eject_tape(pDev[INDEX_TAPE].dev,2);
@@ -2912,7 +2937,7 @@ int SDXMove(int DeviceFD, int from, int to)
  * Return:
  *         == 0 -> success
  *         != 0 -> error either from the SCSI command or from
- *                 the element handling 
+ *                 the element handling
  * TODO:
 */
 int GenericMove(int DeviceFD, int from, int to)
@@ -2920,34 +2945,34 @@ int GenericMove(int DeviceFD, int from, int to)
   ElementInfo_T *pfrom;
   ElementInfo_T *pto;
   int ret = 0;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_MOVE, "##### START GenericMove\n");
-  
+
   DebugPrint(DEBUG_INFO, SECTION_MOVE, "%-20s : from = %d, to = %d\n", "GenericMove", from, to);
-  
-  
+
+
   if ((pfrom = LookupElement(from)) == NULL)
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE, "GenericMove : ElementInfo for %d not found\n", from);
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### STOP GenericMove\n");
       return(-1);
     }
-  
+
   if ((pto = LookupElement(to)) == NULL)
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE, "GenericMove : ElementInfo for %d not found\n", to);
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### STOP GenericMove\n");
       return(-1);
     }
-  
-  if (pfrom->status == 'E') 
+
+  if (pfrom->status == 'E')
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE, "GenericMove : from %d is empty\n", from);
       DebugPrint(DEBUG_INFO, SECTION_MOVE,"##### STOP GenericMove\n");
       return(-1);
     }
-  
-  if (pto->status == 'F') 
+
+  if (pto->status == 'F')
     {
       DebugPrint(DEBUG_INFO, SECTION_MOVE, "GenericMove : Destination Element %d Type %d is full\n",
                 pto->address, pto->type);
@@ -2965,7 +2990,7 @@ int GenericMove(int DeviceFD, int from, int to)
          return(-1);
         }
     }
-  
+
   if (CheckMove(pfrom, pto))
     {
       ret = SCSI_Move(DeviceFD, 0, from, to);
@@ -3148,14 +3173,14 @@ int CheckMove(ElementInfo_T *from, ElementInfo_T *to)
            */
            moveok=1;
          }
-       
+
        DebugPrint(DEBUG_INFO, SECTION_MOVE, "###### STOP CheckMove\n");
        return(moveok);
 }
 
 /*
  */
+
 int GetCurrentSlot(int fd, int drive)
 {
   extern OpenFiles_T *pDev;
@@ -3174,7 +3199,7 @@ int GetCurrentSlot(int fd, int drive)
         {
           return(-1);
         }
-    }   
+    }
 
   /* If the from address is the as the same as the tape address skip it */
   if (pDTE[drive].from >= 0 && pDTE[drive].from != pDTE[drive].address)
@@ -3248,7 +3273,7 @@ int GenericElementStatus(int DeviceFD, int InitStatus)
            }
         }
     }
-  
+
   if (GetElementStatus(DeviceFD) == 0 && loop > 0)
     {
       loop--;
@@ -3422,7 +3447,7 @@ int DLT448ElementStatus(int DeviceFD, int InitStatus)
            }
         }
     }
-  
+
   if (GetElementStatus(DeviceFD) == 0 && loop > 0)
     {
       loop--;
@@ -3552,7 +3577,7 @@ int DLT448ElementStatus(int DeviceFD, int InitStatus)
 }
 
 
-/* 
+/*
  * Much the same like GenericElementStatus but
  * it seemes that for the STE Elements ASC/ASCQ is not set
  * on an error, only the except bit is set
@@ -3719,7 +3744,7 @@ int SDXElementStatus(int DeviceFD, int InitStatus)
  * Only do the read, error handling is done by the calling function
  *
  * Return Values:
- * < 0   -> Error 
+ * < 0   -> Error
  * == 0  -> OK
  *
  * TODO:
@@ -3739,13 +3764,13 @@ int GetElementStatus(int DeviceFD)
   int length = 0;      /* Length of an Element */
   int barcode = 0;      /* To store the result of the BarCode function */
   int NoOfElements;
+
   DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"##### START GetElementStatus\n");
-  
+
   barcode = BarCode(DeviceFD);
 
-  /* 
-   * If the MODE_SENSE was successfull we use this Information to read the Elelement Info 
+  /*
+   * If the MODE_SENSE was successfull we use this Information to read the Elelement Info
    */
   if (pEAAPage != NULL)
     {
@@ -3753,19 +3778,17 @@ int GetElementStatus(int DeviceFD)
       /* First the Medim Transport*/
       if (V2(pEAAPage->NoMediumTransportElements)  > 0)
         {
+          free(pMTE);
           MTE = V2(pEAAPage->NoMediumTransportElements) ;
-          if (pMTE == NULL)
+          if ((pMTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * MTE)) == NULL)
             {
-              if ((pMTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * MTE)) == NULL)
-                {
-                  DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
-                  return(-1);
-                }
+               DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+               return(-1);
             }
           memset(pMTE, 0, sizeof(ElementInfo_T) * MTE);
-         
-          if (SCSI_ReadElementStatus(DeviceFD, 
-                                     CHANGER, 
+
+          if (SCSI_ReadElementStatus(DeviceFD,
+                                     CHANGER,
                                      0,
                                      barcode,
                                      V2(pEAAPage->MediumTransportElementAddress),
@@ -3773,52 +3796,50 @@ int GetElementStatus(int DeviceFD)
                                     sizeof(MediumTransportElementDescriptor_T),
                                      (char **)&DataBuffer) != 0)
             {
-              if (DataBuffer != 0)
-               {
-                 free(DataBuffer);
-               }
+             free(pMTE);
+             free(DataBuffer);
               ChgExit("genericElementStatus","Can't read MTE status", FATAL);
             }
           ElementStatusData = (ElementStatusData_T *)DataBuffer;
           offset = sizeof(ElementStatusData_T);
-          
+
           ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset];
           offset = offset + sizeof(ElementStatusPage_T);
          length = V2(ElementStatusPage->length);
           DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"MTE Length %d(%d)\n",length,sizeof(MediumTransportElementDescriptor_T));
-          
+
           for (x = 0; x < MTE; x++)
             {
               MediumTransportElementDescriptor = (MediumTransportElementDescriptor_T *)&DataBuffer[offset];
-             
+
               if (ElementStatusPage->pvoltag == 1)
                 {
-                  strncpy(pMTE[x].VolTag, 
-                          MediumTransportElementDescriptor->pvoltag,
+                  strncpy((char *)pMTE[x].VolTag,
+                          (char *)MediumTransportElementDescriptor->pvoltag,
                           TAG_SIZE);
                   TerminateString(pMTE[x].VolTag, TAG_SIZE+1);
                 }
-             
+
               pMTE[x].type = ElementStatusPage->type;
               pMTE[x].address = V2(MediumTransportElementDescriptor->address);
               pMTE[x].except = MediumTransportElementDescriptor->except;
               pMTE[x].status = (MediumTransportElementDescriptor->full > 0) ? 'F':'E';
               pMTE[x].full = MediumTransportElementDescriptor->full;
-             
+
              if (length >= 5)
                {
                  pMTE[x].ASC = MediumTransportElementDescriptor->asc;
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC MTE\n");
                }
-             
+
              if (length >= 6)
                {
                  pMTE[x].ASCQ = MediumTransportElementDescriptor->ascq;
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ MTE\n");
                }
-             
+
              if (length >= 0xa)
                {
                  if (MediumTransportElementDescriptor->svalid == 1)
@@ -3830,27 +3851,26 @@ int GetElementStatus(int DeviceFD)
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source MTE\n");
                }
-             offset = offset + length; 
+             offset = offset + length;
             }
         }
-      /* 
-       * Storage Elements 
+      /*
+       * Storage Elements
        */
       if ( V2(pEAAPage->NoStorageElements)  > 0)
         {
+          free(pSTE);
           STE = V2(pEAAPage->NoStorageElements);
-          if (pSTE == NULL)
+          if ((pSTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * STE)) == NULL)
             {
-              if ((pSTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * STE)) == NULL)
-                {
-                  DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
-                  return(-1);
-                }
+              DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+             free(pMTE);
+              return(-1);
             }
           memset(pSTE, 0, sizeof(ElementInfo_T) * STE);
-          
-          if (SCSI_ReadElementStatus(DeviceFD, 
-                                     STORAGE, 
+
+          if (SCSI_ReadElementStatus(DeviceFD,
+                                     STORAGE,
                                      0,
                                      barcode,
                                      V2(pEAAPage->FirstStorageElementAddress),
@@ -3858,53 +3878,50 @@ int GetElementStatus(int DeviceFD)
                                     sizeof(StorageElementDescriptor_T),
                                      (char **)&DataBuffer) != 0)
             {
-              if (DataBuffer != 0)
-               {
-                 free(DataBuffer);
-               }
+             free(DataBuffer);
               ChgExit("GetElementStatus", "Can't read STE status", FATAL);
             }
-          
+
           ElementStatusData = (ElementStatusData_T *)DataBuffer;
           offset = sizeof(ElementStatusData_T);
-          
+
           ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset];
           offset = offset + sizeof(ElementStatusPage_T);
          length = V2(ElementStatusPage->length);
           DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"STE Length %d\n",length);
-          
+
           for (x = 0; x < STE; x++)
             {
               StorageElementDescriptor = (StorageElementDescriptor_T *)&DataBuffer[offset];
               if (ElementStatusPage->pvoltag == 1)
                 {
-                  strncpy(pSTE[x].VolTag, 
-                          StorageElementDescriptor->pvoltag,
+                  strncpy(pSTE[x].VolTag,
+                          (char *)StorageElementDescriptor->pvoltag,
                           TAG_SIZE);
                   TerminateString(pSTE[x].VolTag, TAG_SIZE+1);
                 }
-              
-              
+
+
               pSTE[x].type = ElementStatusPage->type;
               pSTE[x].address = V2(StorageElementDescriptor->address);
               pSTE[x].except = StorageElementDescriptor->except;
               pSTE[x].status = (StorageElementDescriptor->full > 0) ? 'F':'E';
               pSTE[x].full = StorageElementDescriptor->full;
-             
+
              if (length >= 5)
                {
                  pSTE[x].ASC = StorageElementDescriptor->asc;
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC STE\n");
                }
-             
+
              if (length >= 6)
                {
                  pSTE[x].ASCQ = StorageElementDescriptor->ascq;
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ STE\n");
                }
-              
+
              if (length >= 0xa)
                {
                  if (StorageElementDescriptor->svalid == 1)
@@ -3912,32 +3929,32 @@ int GetElementStatus(int DeviceFD)
                      pSTE[x].from = V2(StorageElementDescriptor->source);
                    } else {
                      pSTE[x].from = -1;
-                   }              
+                   }
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source STE\n");
                }
-             
-              offset = offset + length; 
+
+              offset = offset + length;
             }
-          
+
         }
-      /* 
+      /*
        * Import/Export Elements
        */
       if ( V2(pEAAPage->NoImportExportElements) > 0)
         {
+          free(pIEE);
           IEE = V2(pEAAPage->NoImportExportElements);
-          if (pIEE == NULL)
+          if ((pIEE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * IEE)) == NULL)
             {
-              if ((pIEE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * IEE)) == NULL)
-                {
-                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
-                  return(-1);
-                }
+                DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+               free(DataBuffer);
+                return(-1);
             }
           memset(pIEE, 0, sizeof(ElementInfo_T) * IEE);
-          if (SCSI_ReadElementStatus(DeviceFD, 
-                                     IMPORT, 
+
+          if (SCSI_ReadElementStatus(DeviceFD,
+                                     IMPORT,
                                      0,
                                      barcode,
                                      V2(pEAAPage->FirstImportExportElementAddress),
@@ -3951,22 +3968,22 @@ int GetElementStatus(int DeviceFD)
                }
               ChgExit("GetElementStatus", "Can't read IEE status", FATAL);
             }
-          
+
           ElementStatusData = (ElementStatusData_T *)DataBuffer;
           offset = sizeof(ElementStatusData_T);
-          
+
           ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset];
           offset = offset + sizeof(ElementStatusPage_T);
          length = V2(ElementStatusPage->length);
           DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"IEE Length %d\n",length);
-          
+
           for (x = 0; x < IEE; x++)
             {
               ImportExportElementDescriptor = (ImportExportElementDescriptor_T *)&DataBuffer[offset];
               if (ElementStatusPage->pvoltag == 1)
                 {
-                  strncpy(pIEE[x].VolTag, 
-                          ImportExportElementDescriptor->pvoltag,
+                  strncpy(pIEE[x].VolTag,
+                          (char *)ImportExportElementDescriptor->pvoltag,
                           TAG_SIZE);
                   TerminateString(pIEE[x].VolTag, TAG_SIZE+1);
                 }
@@ -3975,21 +3992,21 @@ int GetElementStatus(int DeviceFD)
               pIEE[x].except = ImportExportElementDescriptor->except;
               pIEE[x].status = (ImportExportElementDescriptor->full > 0) ? 'F':'E';
               pIEE[x].full = ImportExportElementDescriptor->full;
-             
+
              if (length >= 5)
                {
                  pIEE[x].ASC = ImportExportElementDescriptor->asc;
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC IEE\n");
                }
-             
+
              if (length >= 6)
                {
                  pIEE[x].ASCQ = ImportExportElementDescriptor->ascq;
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ IEE\n");
                }
-              
+
              if (length >= 0xa)
                {
                  if (ImportExportElementDescriptor->svalid == 1)
@@ -3997,32 +4014,32 @@ int GetElementStatus(int DeviceFD)
                      pIEE[x].from = V2(ImportExportElementDescriptor->source);
                    } else {
                      pIEE[x].from = -1;
-                   }              
+                   }
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source IEE\n");
                }
-             
-              offset = offset + length; 
+
+              offset = offset + length;
             }
-          
+
         }
-      /* 
+      /*
        * Data Transfer Elements
        */
       if (V2(pEAAPage->NoDataTransferElements) >0)
         {
+         free(pDTE);
           DTE = V2(pEAAPage->NoDataTransferElements) ;
-          if (pDTE == NULL)
+          if ((pDTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * DTE)) == NULL)
             {
-              if ((pDTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * DTE)) == NULL)
-                {
-                  DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
-                  return(-1);
-                }
+              DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+             free(DataBuffer);
+              return(-1);
             }
           memset(pDTE, 0, sizeof(ElementInfo_T) * DTE);
-          if (SCSI_ReadElementStatus(DeviceFD, 
-                                     TAPETYPE, 
+
+          if (SCSI_ReadElementStatus(DeviceFD,
+                                     TAPETYPE,
                                      0,
                                      barcode,
                                      V2(pEAAPage->FirstDataTransferElementAddress),
@@ -4030,28 +4047,25 @@ int GetElementStatus(int DeviceFD)
                                     sizeof(DataTransferElementDescriptor_T),
                                      (char **)&DataBuffer) != 0)
             {
-              if (DataBuffer != 0)
-               {
-                 free(DataBuffer);
-               }
+             free(DataBuffer);
               ChgExit("GenericElementStatus", "Can't read DTE status", FATAL);
             }
-          
+
           ElementStatusData = (ElementStatusData_T *)DataBuffer;
           offset = sizeof(ElementStatusData_T);
-          
+
           ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset];
           offset = offset + sizeof(ElementStatusPage_T);
          length = V2(ElementStatusPage->length);
           DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"DTE Length %d\n",length);
-         
+
           for (x = 0; x < DTE; x++)
             {
               DataTransferElementDescriptor = (DataTransferElementDescriptor_T *)&DataBuffer[offset];
               if (ElementStatusPage->pvoltag == 1)
                 {
-                  strncpy(pDTE[x].VolTag, 
-                          DataTransferElementDescriptor->pvoltag,
+                  strncpy(pDTE[x].VolTag,
+                          (char *)DataTransferElementDescriptor->pvoltag,
                           TAG_SIZE);
                   TerminateString(pDTE[x].VolTag, TAG_SIZE+1);
                 }
@@ -4061,21 +4075,21 @@ int GetElementStatus(int DeviceFD)
               pDTE[x].scsi = DataTransferElementDescriptor->scsi;
               pDTE[x].status = (DataTransferElementDescriptor->full > 0) ? 'F':'E';
               pDTE[x].full = DataTransferElementDescriptor->full;
-              
+
              if (length >= 5)
              {
                pDTE[x].ASC = DataTransferElementDescriptor->asc;
              } else {
                DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC DTE\n");
              }
-             
+
              if (length >= 6)
                {
                  pDTE[x].ASCQ = DataTransferElementDescriptor->ascq;
              } else {
                DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ DTE\n");
              }
-             
+
              if (length >= 0xa)
                {
                  if (DataTransferElementDescriptor->svalid == 1)
@@ -4087,8 +4101,8 @@ int GetElementStatus(int DeviceFD)
                } else {
                  DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source STE\n");
                }
-             
-              offset = offset + length; 
+
+              offset = offset + length;
             }
         }
     } else {
@@ -4096,8 +4110,8 @@ int GetElementStatus(int DeviceFD)
        * And now the old way, when we get here the read mode sense page has failed ...
        */
       DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Reading Element Status the old way .... (max 255 elements)\n");
-      if (SCSI_ReadElementStatus(DeviceFD, 
-                                 0, 
+      if (SCSI_ReadElementStatus(DeviceFD,
+                                 0,
                                  0,
                                  barcode,
                                  0,
@@ -4111,42 +4125,46 @@ int GetElementStatus(int DeviceFD)
            }
           ChgExit("GenericElementStatus","Can't get ElementStatus", FATAL);
         }
-      
+
       ElementStatusData = (ElementStatusData_T *)DataBuffer;
       DataBufferLength = V3(ElementStatusData->count);
-      
+
       offset = sizeof(ElementStatusData_T);
-      
-      if (DataBufferLength <= 0) 
+
+      if (DataBufferLength <= 0)
         {
           DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"DataBufferLength %d\n",DataBufferLength);
+         free(DataBuffer);
           return(1);
         }
-      
-      while (offset < DataBufferLength) 
+
+      while (offset < DataBufferLength)
         {
           ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset];
           NoOfElements = V3(ElementStatusPage->count) / V2(ElementStatusPage->length);
           offset = offset + sizeof(ElementStatusPage_T);
          length = V2(ElementStatusPage->length);
-          
+
           switch (ElementStatusPage->type)
             {
             case CHANGER:
+             free(pMTE);
               MTE = NoOfElements;
               if ((pMTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * MTE)) == NULL)
                 {
                   DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+                 free(DataBuffer);
                   return(-1);
                 }
               memset(pMTE, 0, sizeof(ElementInfo_T) * MTE);
+
               for (x = 0; x < NoOfElements; x++)
-                {                  
+                {
                   MediumTransportElementDescriptor = (MediumTransportElementDescriptor_T *)&DataBuffer[offset];
                   if (ElementStatusPage->pvoltag == 1)
                     {
-                      strncpy(pMTE[x].VolTag, 
-                              MediumTransportElementDescriptor->pvoltag,
+                      strncpy(pMTE[x].VolTag,
+                              (char *)MediumTransportElementDescriptor->pvoltag,
                               TAG_SIZE);
                       TerminateString(pMTE[x].VolTag, TAG_SIZE+1);
                     }
@@ -4155,22 +4173,22 @@ int GetElementStatus(int DeviceFD)
                   pMTE[x].except = MediumTransportElementDescriptor->except;
                   pMTE[x].status = (MediumTransportElementDescriptor->full > 0) ? 'F':'E';
                   pMTE[x].full = MediumTransportElementDescriptor->full;
-                  
-                 
+
+
                  if (length >= 5)
                    {
                      pMTE[x].ASC = MediumTransportElementDescriptor->asc;
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC MTE\n");
                    }
-                 
+
                  if (length >= 6)
                    {
                      pMTE[x].ASCQ = MediumTransportElementDescriptor->ascq;
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ MTE\n");
                    }
-                 
+
                  if (length >= 0xa)
                    {
                      if (MediumTransportElementDescriptor->svalid == 1)
@@ -4178,33 +4196,36 @@ int GetElementStatus(int DeviceFD)
                          pMTE[x].from = V2(MediumTransportElementDescriptor->source);
                        } else {
                          pMTE[x].from = -1;
-                       }                  
+                       }
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source MTE\n");
                    }
 
-                 offset = offset + length; 
+                 offset = offset + length;
                }
               break;
             case STORAGE:
+             free(pSTE);
               STE = NoOfElements;
               if ((pSTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * STE)) == NULL)
                 {
                   DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+                 free(DataBuffer);
                   return(-1);
                 }
               memset(pSTE, 0, sizeof(ElementInfo_T) * STE);
+
               for (x = 0; x < NoOfElements; x++)
                 {
                  StorageElementDescriptor = (StorageElementDescriptor_T *)&DataBuffer[offset];
                   if (ElementStatusPage->pvoltag == 1)
                     {
-                      strncpy(pSTE[x].VolTag, 
-                              StorageElementDescriptor->pvoltag,
+                      strncpy(pSTE[x].VolTag,
+                              (char *)StorageElementDescriptor->pvoltag,
                               TAG_SIZE);
                       TerminateString(pSTE[x].VolTag, TAG_SIZE+1);
                     }
-                  
+
                   pSTE[x].type = ElementStatusPage->type;
                   pSTE[x].address = V2(StorageElementDescriptor->address);
                   pSTE[x].except = StorageElementDescriptor->except;
@@ -4217,14 +4238,14 @@ int GetElementStatus(int DeviceFD)
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC STE\n");
                    }
-                 
+
                  if (length >= 6)
                    {
                      pSTE[x].ASCQ = StorageElementDescriptor->ascq;
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ STE\n");
                    }
-                 
+
                  if (length >= 0xa)
                    {
                      if (StorageElementDescriptor->svalid == 1)
@@ -4232,30 +4253,32 @@ int GetElementStatus(int DeviceFD)
                          pSTE[x].from = V2(StorageElementDescriptor->source);
                        } else {
                          pSTE[x].from = -1;
-                       }              
+                       }
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source STE\n");
                    }
-                 
-                  offset = offset + length; 
+
+                  offset = offset + length;
                 }
               break;
             case IMPORT:
+             free(pIEE);
               IEE = NoOfElements;
               if ((pIEE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * IEE)) == NULL)
                 {
                   DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+                 free(DataBuffer);
                   return(-1);
                 }
               memset(pIEE, 0, sizeof(ElementInfo_T) * IEE);
-              
+
               for (x = 0; x < NoOfElements; x++)
                 {
                   ImportExportElementDescriptor = (ImportExportElementDescriptor_T *)&DataBuffer[offset];
                   if (ElementStatusPage->pvoltag == 1)
                     {
-                      strncpy(pIEE[x].VolTag, 
-                              ImportExportElementDescriptor->pvoltag,
+                      strncpy(pIEE[x].VolTag,
+                              (char *)ImportExportElementDescriptor->pvoltag,
                               TAG_SIZE);
                       TerminateString(pIEE[x].VolTag, TAG_SIZE+1);
                     }
@@ -4265,21 +4288,21 @@ int GetElementStatus(int DeviceFD)
                   pIEE[x].except = ImportExportElementDescriptor->except;
                   pIEE[x].status = (ImportExportElementDescriptor->full > 0) ? 'F':'E';
                   pIEE[x].full = ImportExportElementDescriptor->full;
-                 
+
                  if (length >= 5)
                    {
                      pIEE[x].ASC = ImportExportElementDescriptor->asc;
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC IEE\n");
                    }
-                 
+
                  if (length >= 6)
                    {
                      pIEE[x].ASCQ = ImportExportElementDescriptor->ascq;
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ IEE\n");
                    }
-                 
+
                  if (length >= 0xa)
                    {
                      if (ImportExportElementDescriptor->svalid == 1)
@@ -4287,30 +4310,32 @@ int GetElementStatus(int DeviceFD)
                          pIEE[x].from = V2(ImportExportElementDescriptor->source);
                        } else {
                          pIEE[x].from = -1;
-                       }              
+                       }
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source IEE\n");
                    }
-                 
-                 offset = offset + length; 
+
+                 offset = offset + length;
                }
              break;
             case TAPETYPE:
+             free(pDTE);
               DTE = NoOfElements;
               if ((pDTE = (ElementInfo_T *)malloc(sizeof(ElementInfo_T) * DTE)) == NULL)
                 {
                   DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GenericElementStatus : malloc failed\n");
+                 free(DataBuffer);
                   return(-1);
                 }
               memset(pDTE, 0, sizeof(ElementInfo_T) * DTE);
-             
+
               for (x = 0; x < NoOfElements; x++)
                 {
                  DataTransferElementDescriptor = (DataTransferElementDescriptor_T *)&DataBuffer[offset];
                   if (ElementStatusPage->pvoltag == 1)
                     {
-                      strncpy(pSTE[x].VolTag, 
-                              DataTransferElementDescriptor->pvoltag,
+                      strncpy(pSTE[x].VolTag,
+                              (char *)DataTransferElementDescriptor->pvoltag,
                               TAG_SIZE);
                       TerminateString(pSTE[x].VolTag, TAG_SIZE+1);
                     }
@@ -4327,14 +4352,14 @@ int GetElementStatus(int DeviceFD)
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASC DTE\n");
                    }
-                 
+
                  if (length >= 6)
                    {
                      pDTE[x].ASCQ = DataTransferElementDescriptor->ascq;
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip ASCQ DTE\n");
                    }
-                 
+
                  if (length >= 0xa)
                    {
                      if (DataTransferElementDescriptor->svalid == 1)
@@ -4346,12 +4371,12 @@ int GetElementStatus(int DeviceFD)
                    } else {
                      DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"Skip source STE\n");
                    }
-                 
-                 offset = offset + length; 
+
+                 offset = offset + length;
                 }
               break;
             default:
-              offset = offset + length; 
+              offset = offset + length;
               DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"GetElementStatus : UnGknown Type %d\n",ElementStatusPage->type);
               break;
             }
@@ -4373,7 +4398,7 @@ int GetElementStatus(int DeviceFD)
               pSTE[x].ASCQ, pSTE[x].type, pSTE[x].from, pSTE[x].VolTag);
 
   DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"\n\n\tData Transfer Elements (tape drives) :\n");
+
   for ( x = 0; x < DTE; x++)
     DebugPrint(DEBUG_INFO, SECTION_ELEMENT,"\t\tElement #%04d %c\n\t\t\tEXCEPT = %02X\n\t\t\tASC = %02X ASCQ = %02X\n\t\t\tType %d From = %04d\n\t\t\tTAG = %s\n\t\t\tSCSI ADDRESS = %d\n",
               pDTE[x].address, pDTE[x].status, pDTE[x].except, pDTE[x].ASC,
@@ -4403,37 +4428,37 @@ int RequestSense(int DeviceFD, ExtendedRequestSense_T *ExtendedRequestSense, int
 {
   CDB_T CDB;
   int ret;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### START RequestSense\n");
-  
-  CDB[0] = SC_COM_REQUEST_SENSE;               /* REQUEST SENSE */                       
-  CDB[1] = 0;                                  /* Logical Unit Number = 0, Reserved */ 
-  CDB[2] = 0;                                  /* Reserved */              
+
+  CDB[0] = SC_COM_REQUEST_SENSE;               /* REQUEST SENSE */
+  CDB[1] = 0;                                  /* Logical Unit Number = 0, Reserved */
+  CDB[2] = 0;                                  /* Reserved */
   CDB[3] = 0;                                  /* Reserved */
-  CDB[4] = sizeof(ExtendedRequestSense_T);     /* Allocation Length */                    
+  CDB[4] = sizeof(ExtendedRequestSense_T);     /* Allocation Length */
   CDB[5] = (ClearErrorCounters << 7) & 0x80;                 /*  */
-  
+
   memset(ExtendedRequestSense, 0, sizeof(ExtendedRequestSense_T));
-  
-  ret = SCSI_Run(DeviceFD, Input, CDB, 6,                      
+
+  ret = SCSI_Run(DeviceFD, Input, CDB, 6,
                 (char *) ExtendedRequestSense,
-                sizeof(ExtendedRequestSense_T),  
+                sizeof(ExtendedRequestSense_T),
                 (char *) ExtendedRequestSense, sizeof(ExtendedRequestSense_T));
-  
-  
+
+
   if (ret < 0)
     {
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP RequestSense (%d)\n",ret);
       return(ret);
     }
-  
+
   if ( ret > 0)
     {
       DecodeExtSense(ExtendedRequestSense, "RequestSense : ",debug_file);
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP RequestSense (%d)\n", ExtendedRequestSense->SenseKey);
       return(ExtendedRequestSense->SenseKey);
     }
-  
+
   dump_hex((char *)ExtendedRequestSense , sizeof(ExtendedRequestSense_T) , DEBUG_INFO, SECTION_SCSI);
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP RequestSense (0)\n");
   return(0);
@@ -4516,9 +4541,6 @@ int LogSense(DeviceFD)
   LogParameter_T *LogParameter;
   struct LogPageDecode *p;
   int found;
-  char *datestamp = NULL;
-  char *label = NULL;
-  char *result = NULL;
   extern char *tapestatfile;
   int i;
   int ParameterCode;
@@ -4532,22 +4554,23 @@ int LogSense(DeviceFD)
 
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### START LogSense\n");
 
-  if (tapestatfile != NULL && 
-      (StatFile = fopen(tapestatfile,"a")) != NULL && 
-      pDev[INDEX_TAPECTL].SCSI == 1) 
+  if ((tapestatfile != NULL) && (pDev[INDEX_TAPECTL].SCSI == 1) &&
+      ((StatFile = fopen(tapestatfile,"a")) != NULL))
     {
-      if ((pRequestSense  = (RequestSense_T *)malloc(sizeof(RequestSense_T))) == NULL)
+      if ((pRequestSense = (RequestSense_T *)malloc(sizeof(RequestSense_T))) == NULL)
         {
           DebugPrint(DEBUG_ERROR, SECTION_TAPE,"LogSense : malloc failed\n");
+             fclose(StatFile);
               return(-1);
         }
-      
-      if (GenericRewind(INDEX_TAPECTL) < 0) 
-        { 
+
+      if (GenericRewind(INDEX_TAPECTL) < 0)
+        {
           DebugPrint(DEBUG_INFO, SECTION_TAPE,"LogSense : Rewind failed\n");
           free(pRequestSense);
-          return(0); 
-        } 
+         fclose(StatFile);
+          return(0);
+        }
       /*
        * Try to read the tape label
        */
@@ -4557,25 +4580,27 @@ int LogSense(DeviceFD)
            {
              SCSI_CloseDevice(INDEX_TAPE);
            }
-         
-         if ((result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &datestamp, &label)) == NULL)
+
+         if ((chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label)) == NULL)
            {
-             fprintf(StatFile, "==== %s ==== %s ====\n", datestamp, label);
+             fprintf(StatFile, "==== %s ==== %s ====\n", chgscsi_datestamp, chgscsi_label);
            } else {
-             fprintf(StatFile, "%s\n", result);
+             fprintf(StatFile, "%s\n", chgscsi_result);
            }
        }
 
       if ((buffer = (char *)malloc(size)) == NULL)
         {
           DebugPrint(DEBUG_ERROR, SECTION_TAPE,"LogSense : malloc failed\n");
+          free(pRequestSense);
+         fclose(StatFile);
           return(-1);
         }
       memset(buffer, 0, size);
       /*
-       * Get the known log pages 
+       * Get the known log pages
        */
-      
+
       CDB[0] = SC_COM_LOG_SENSE;
       CDB[1] = 0;
       CDB[2] = 0x40;    /* 0x40 for current values */
@@ -4585,34 +4610,36 @@ int LogSense(DeviceFD)
       CDB[6] = 00;
       MSB2(&CDB[7], size);
       CDB[9] = 0;
-      
+
             if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10,
                               buffer,
-                              size, 
+                              size,
                               (char *)pRequestSense,
                               sizeof(RequestSense_T)) != 0)
         {
           DecodeSense(pRequestSense, "LogSense : ",debug_file);
-          free(buffer);
           free(pRequestSense);
+          free(buffer);
+         fclose(StatFile);
           return(0);
         }
-      
+
       LogSenseHeader = (LogSenseHeader_T *)buffer;
       nologpages = V2(LogSenseHeader->PageLength);
       if ((logpages = (char *)malloc(nologpages)) == NULL)
         {
           DebugPrint(DEBUG_ERROR, SECTION_TAPE,"LogSense : malloc failed\n");
+          free(pRequestSense);
+         free(buffer);
+         fclose(StatFile);
           return(-1);
         }
-      
+
       memcpy(logpages, buffer + sizeof(LogSenseHeader_T), nologpages);
-      
+
       for (count = 0; count < nologpages; count++) {
         if (logpages[count] != 0  ) {
           memset(buffer, 0, size);
-          
-          
           CDB[0] = SC_COM_LOG_SENSE;
           CDB[1] = 0;
           CDB[2] = 0x40 | logpages[count];    /* 0x40 for current values */
@@ -4622,16 +4649,18 @@ int LogSense(DeviceFD)
           CDB[6] = 00;
           MSB2(&CDB[7], size);
           CDB[9] = 0;
-      
+
           if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10,
                                   buffer,
-                                  size, 
+                                  size,
                                   (char *)pRequestSense,
                                   sizeof(RequestSense_T)) != 0)
-            { 
+            {
               DecodeSense(pRequestSense, "LogSense : ",debug_file);
-              free(buffer);
               free(pRequestSense);
+             free(logpages);
+              free(buffer);
+             fclose(StatFile);
               return(0);
             }
           LogSenseHeader = (LogSenseHeader_T *)buffer;
@@ -4655,14 +4684,9 @@ int LogSense(DeviceFD)
             p++;
           }
 
-         /*
-         *  Hack to disable the printing of unknown pages
-         */
-         found = 1;
-
           if (!found) {
             fprintf(StatFile, "Logpage No %d = %x\n", count ,logpages[count]);
-      
+
             while ((char *)LogParameter < (buffer + length)) {
               i = LogParameter->ParameterLength;
               ParameterCode = V2(LogParameter->ParameterCode);
@@ -4699,11 +4723,11 @@ int LogSense(DeviceFD)
 
       /*
        * Test only !!!!
-       * Reset the cumulative counters 
+       * Reset the cumulative counters
        */
       CDB[0] = SC_COM_LOG_SELECT;
       CDB[1] = 2;
-      CDB[2] = 0xc0;  
+      CDB[2] = 0xc0;
       CDB[3] = 0;
       CDB[4] = 0;
       CDB[5] = 0;
@@ -4711,24 +4735,27 @@ int LogSense(DeviceFD)
       CDB[7] = 0;
       CDB[8] = 0;
       CDB[9] = 0;
-      
+
             if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10,
                               buffer,
-                              size, 
+                              size,
                               (char *)pRequestSense,
                               sizeof(RequestSense_T)) != 0)
         {
           DecodeSense(pRequestSense, "LogSense : ",debug_file);
-          free(buffer);
           free(pRequestSense);
+         free(logpages);
+          free(buffer);
+         fclose(StatFile);
           return(0);
         }
 
       free(pRequestSense);
+      free(logpages);
       free(buffer);
+      fclose(StatFile);
     }
   DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP LogSense\n");
-  
   return(0);
 }
 
@@ -4775,7 +4802,7 @@ void WriteErrorCountersPage(LogParameter_T *buffer, int length)
                 value);
         break;
       default:
-        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n", 
+        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n",
                 ParameterCode,
                 value, i);
         break;
@@ -4829,7 +4856,7 @@ void ReadErrorCountersPage(LogParameter_T *buffer, int length)
                 value);
         break;
       default:
-        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n", 
+        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n",
                 ParameterCode,
                 value, i);
         break;
@@ -4858,7 +4885,7 @@ void C1553APage30(LogParameter_T *buffer, int length)
     if (Decode(LogParameter, &value) == 0) {
       switch (ParameterCode) {
       default:
-        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n", 
+        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n",
                 ParameterCode,
                 value, i);
         break;
@@ -4900,7 +4927,7 @@ void C1553APage37(LogParameter_T *buffer, int length)
                 value);
         break;
       default:
-        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n", 
+        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n",
                 ParameterCode,
                 value, i);
         break;
@@ -4937,13 +4964,13 @@ void EXB85058HEPage39(LogParameter_T *buffer, int length)
                 value);
         break;
       default:
-        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n", 
+        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n",
                 ParameterCode,
                 value, i);
         break;
       }
     }
-    LogParameter = (LogParameter_T *)((char *)LogParameter +  sizeof(LogParameter_T) + i); 
+    LogParameter = (LogParameter_T *)((char *)LogParameter +  sizeof(LogParameter_T) + i);
   }
 }
 
@@ -5004,13 +5031,13 @@ void EXB85058HEPage3c(LogParameter_T *buffer, int length)
       case 0x14:
         break;
       default:
-        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n", 
+        fprintf(StatFile, "Unknown ParameterCode %02X = %u(%d)\n",
                 ParameterCode,
                 value, i);
         break;
       }
     }
-    LogParameter = (LogParameter_T *)((char *)LogParameter +  sizeof(LogParameter_T) + i); 
+    LogParameter = (LogParameter_T *)((char *)LogParameter +  sizeof(LogParameter_T) + i);
   }
 }
 
@@ -5068,12 +5095,12 @@ void ChangerReplay(char *option)
     char buffer[1024];
     FILE *ip;
     int x = 0, bufferx;
-   
+
     if ((ip=fopen("/tmp/chg-scsi-trace", "r")) == NULL)
       {
        exit(1);
       }
-    
+
     while (fscanf(ip, "%2x", &bufferx) != EOF)
       {
        buffer[x] = bufferx;
@@ -5081,6 +5108,7 @@ void ChangerReplay(char *option)
       }
 
     DecodeModeSense(&buffer[0], 12, "DLT448ElementStatus :", 0, debug_file);
+    fclose(ip);
 }
 
 /*
@@ -5092,23 +5120,31 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
   int x;
   FILE *out;
   ExtendedRequestSense_T ExtRequestSense;
-  MBC_T *pbarcoderes = malloc(sizeof(MBC_T));
-  
+  MBC_T *pbarcoderes;
+
   ChangerCMD_T *p = (ChangerCMD_T *)&ChangerIO;
+  if ((pbarcoderes = malloc(sizeof(MBC_T))) == NULL)
+    {
+      printf("malloc failed \n");
+      return;
+    }
   memset(pbarcoderes, 0, sizeof(MBC_T));
 
-  if ((pModePage = (char *)malloc(0xff)) == NULL)
+  if ((pModePage == NULL) && ((pModePage = (char *)malloc(0xff)) == NULL))
     {
+      DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,"##### malloc failed (-1)\n");
       printf("malloc failed \n");
+      free(pbarcoderes);
       return;
     }
 
   if ((out = fdopen(1 , "w")) == NULL)
     {
       printf("Error fdopen stdout\n");
+      free(pbarcoderes);
       return;
     }
-  
+
   if (strcmp("types", option) == 0 || strcmp("all", option) == 0)
   {
     while(p->ident != NULL)
@@ -5126,6 +5162,8 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
             if (pDev[INDEX_CHANGER].functions->function_status(pDev[INDEX_CHANGER].fd, 1) != 0)
               {
                 printf("Can not initialize changer status\n");
+               free(pbarcoderes);
+               fclose(out);
                 return;
               }
           }
@@ -5137,8 +5175,8 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
                printf("Address Type Status From\n");
        }
         printf("-------------------------------------------\n");
-        
-        
+
+
         for ( x = 0; x < MTE; x++)
        if (HasBarCode)
        {
@@ -5150,9 +5188,9 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            {
              pbarcoderes->action = BARCODE_BARCODE;
              strcpy(pbarcoderes->data.barcode, pMTE[x].VolTag);
-             
+
              if (MapBarCode(labelfile, pbarcoderes) == 0 )
-               { 
+               {
                  printf("No mapping\n");
                } else {
                  printf("%s \n",pbarcoderes->data.voltag);
@@ -5165,12 +5203,12 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
                  (pMTE[x].full ? "Full " :"Empty"),
                  pMTE[x].from);
        }
-        
-        
+
+
         for ( x = 0; x < STE; x++)
        if (HasBarCode)
        {
-          printf("%07d STE  %s  %04d %s ",pSTE[x].address,  
+          printf("%07d STE  %s  %04d %s ",pSTE[x].address,
                  (pSTE[x].full ? "Full ":"Empty"),
                  pSTE[x].from, pSTE[x].VolTag);
 
@@ -5178,7 +5216,7 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            {
              pbarcoderes->action = BARCODE_BARCODE;
              strcpy(pbarcoderes->data.barcode, pSTE[x].VolTag);
-             
+
              if (MapBarCode(labelfile, pbarcoderes) == 0 )
                {
                  printf("No mapping\n");
@@ -5189,16 +5227,16 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
              printf("\n");
            }
        } else {
-          printf("%07d STE  %s  %04d %s\n",pSTE[x].address,  
+          printf("%07d STE  %s  %04d %s\n",pSTE[x].address,
                  (pSTE[x].full ? "Full ":"Empty"),
                  pSTE[x].from, pSTE[x].VolTag);
        }
-        
-        
+
+
         for ( x = 0; x < DTE; x++)
        if (HasBarCode)
        {
-          printf("%07d DTE  %s  %04d %s ",pDTE[x].address,  
+          printf("%07d DTE  %s  %04d %s ",pDTE[x].address,
                  (pDTE[x].full ? "Full " : "Empty"),
                  pDTE[x].from, pDTE[x].VolTag);
 
@@ -5206,7 +5244,7 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            {
              pbarcoderes->action = BARCODE_BARCODE;
              strcpy(pbarcoderes->data.barcode, pDTE[x].VolTag);
-             
+
              if (MapBarCode(labelfile, pbarcoderes) == 0 )
                {
                  printf("No mapping\n");
@@ -5218,15 +5256,15 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            }
 
        } else {
-          printf("%07d DTE  %s  %04d %s\n",pDTE[x].address,  
+          printf("%07d DTE  %s  %04d %s\n",pDTE[x].address,
                  (pDTE[x].full ? "Full " : "Empty"),
                  pDTE[x].from, pDTE[x].VolTag);
        }
-        
+
         for ( x = 0; x < IEE; x++)
        if (HasBarCode)
-       {       
-          printf("%07d IEE  %s  %04d %s ",pIEE[x].address,  
+       {
+          printf("%07d IEE  %s  %04d %s ",pIEE[x].address,
                  (pIEE[x].full ? "Full " : "Empty"),
                  pIEE[x].from, pIEE[x].VolTag);
 
@@ -5234,7 +5272,7 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            {
              pbarcoderes->action = BARCODE_BARCODE;
              strcpy(pbarcoderes->data.barcode, pIEE[x].VolTag);
-             
+
              if (MapBarCode(labelfile, pbarcoderes) == 0 )
                {
                  printf("No mapping\n");
@@ -5246,11 +5284,11 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            }
 
        } else {
-          printf("%07d IEE  %s  %04d %s\n",pIEE[x].address,  
+          printf("%07d IEE  %s  %04d %s\n",pIEE[x].address,
                  (pIEE[x].full ? "Full " : "Empty"),
                  pIEE[x].from, pIEE[x].VolTag);
        }
-        
+
       }
 
   if (strcmp("sense", option) == 0 || strcmp("all", option) == 0)
@@ -5261,12 +5299,12 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
            RequestSense(INDEX_CHANGER , &ExtRequestSense, 0);
            DecodeExtSense(&ExtRequestSense, "", out);
        }
-      
+
       if (pDev[INDEX_TAPE].SCSI == 1)
         {
           printf("\n");
           printf("Sense Status from tape (tapectl):\n");
-          RequestSense(INDEX_TAPE, &ExtRequestSense, 0); 
+          RequestSense(INDEX_TAPE, &ExtRequestSense, 0);
           DecodeExtSense(&ExtRequestSense, "", out);
         }
 
@@ -5274,7 +5312,7 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
         {
           printf("\n");
           printf("Sense Status from tape (tapectl):\n");
-          RequestSense(INDEX_TAPECTL, &ExtRequestSense, 0); 
+          RequestSense(INDEX_TAPECTL, &ExtRequestSense, 0);
           DecodeExtSense(&ExtRequestSense, "", out);
         }
     }
@@ -5284,10 +5322,10 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
         printf("\n");
         if (SCSI_ModeSense(INDEX_CHANGER, pModePage, 0xff, 0x08, 0x3f) == 0)
           {
-            DecodeModeSense(pModePage, 0, "Changer :" , 0, out); 
+            DecodeModeSense(pModePage, 0, "Changer :" , 0, out);
           }
       }
-  
+
     if (strcmp("ModeSenseTape", option) == 0 || strcmp("all", option) == 0)
       {
         if (pDev[INDEX_TAPECTL].SCSI == 1)
@@ -5295,7 +5333,7 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
           printf("\n");
           if (SCSI_ModeSense(INDEX_TAPECTL, pModePage, 0xff, 0x0, 0x3f) == 0)
             {
-              DecodeModeSense(pModePage, 0, "Tape :" , 1, out); 
+              DecodeModeSense(pModePage, 0, "Tape :" , 1, out);
             }
         }
       }
@@ -5311,7 +5349,10 @@ void ChangerStatus(char *option, char * labelfile, int HasBarCode, char *changer
     }
 
   if (GenericClean("") == 1)
-    printf("Tape needs cleaning\n");  
+    printf("Tape needs cleaning\n");
+
+  free(pbarcoderes);
+  fclose(out);
 }
 
 void dump_hex(char *p, int size, int level, int section)
@@ -5342,7 +5383,7 @@ void dump_hex(char *p, int size, int level, int section)
 void TerminateString(char *string, int length)
 {
   int x;
-  
+
   for (x = length; x >= 0 && !isalnum((int)string[x]); x--)
     string[x] = '\0';
 }
@@ -5351,7 +5392,7 @@ void ChgExit(char *where, char *reason, int level)
 {
    dbprintf(("ChgExit in %s, reason %s\n", where, reason));
    fprintf(stderr,"%s\n",reason);
-   exit(2); 
+   exit(2);
 }
 
 /* OK here starts a new set of functions.
@@ -5422,7 +5463,7 @@ int SCSI_Run(int DeviceFD,
        case SCSI_ERROR:
          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"SCSI_Run (TestUnitReady) SCSI_ERROR\n");
          return(-1);
-         break;     
+         break;
        case SCSI_BUSY:
          DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_Run (TestUnitReady) SCSI_BUSY\n");
          break;
@@ -5439,9 +5480,9 @@ int SCSI_Run(int DeviceFD,
         maxtries++;
       }
     }
-  
+
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_Run TestUnitReady after %d sec:\n",maxtries);
-  
+
   if (ok != 1)
     {
       DebugPrint(DEBUG_ERROR, SECTION_SCSI,"SCSI_Run Exit %d\n",ret);
@@ -5460,7 +5501,7 @@ int SCSI_Run(int DeviceFD,
                                DataBufferLength,
                                pRequestSense,
                                RequestSenseLength);
-      
+
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_Run Exit %d\n",ret);
       switch (ret)
        {
@@ -5512,7 +5553,7 @@ int SCSI_Run(int DeviceFD,
       maxtries++;
       sleep(1);
     }
-  
+
   if (ok == 1)
     {
       return(0);
@@ -5521,27 +5562,27 @@ int SCSI_Run(int DeviceFD,
     }
 }
 
-/*                                       
- * This a vendor specific command !!!!!! 
- * First seen at AIT :-)                 
- */                                       
+/*
+ * This a vendor specific command !!!!!!
+ * First seen at AIT :-)
+ */
 int SCSI_AlignElements(int DeviceFD, int AE_MTE, int AE_DTE, int AE_STE)
 {
   RequestSense_T *pRequestSense;
-  int retry = 1;
+  int retry;
   CDB_T CDB;
-  int ret;
+  int ret = -1;
   int i;
-  
+
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### START SCSI_AlignElements\n");
-  
+
   if ((pRequestSense = (RequestSense_T *)malloc(sizeof(RequestSense_T))) == NULL)
     {
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_AlignElements : malloc failed\n");
       return(-1);
     }
-  
-  while (retry > 0 && retry < MAX_RETRIES)
+
+  for (retry = 0; retry < MAX_RETRIES; retry++)
     {
       CDB[0]  = 0xE5;
       CDB[1]  = 0;
@@ -5552,20 +5593,20 @@ int SCSI_AlignElements(int DeviceFD, int AE_MTE, int AE_DTE, int AE_STE)
       CDB[9]  = 0;
       CDB[10] = 0;
       CDB[11] = 0;
-      
+
       ret = SCSI_Run(DeviceFD, Input, CDB, 12,
-                                NULL, 0, (char *)pRequestSense, sizeof(RequestSense_T)); 
+                                NULL, 0, (char *)pRequestSense, sizeof(RequestSense_T));
 
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_AlignElements : SCSI_Run = %d\n", ret);
       DecodeSense(pRequestSense, "SCSI_AlignElements :",debug_file);
 
       if (ret < 0)
         {
-          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"%s: Request Sense[Inquiry]: %02X", 
-                    "chs", ((unsigned char *) &pRequestSense)[0]); 
-          for (i = 1; i < sizeof(RequestSense_T); i++)                
-            DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((unsigned char *) &pRequestSense)[i]); 
-          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"\n");    
+          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"%s: Request Sense[Inquiry]: %02X",
+                    "chs", ((unsigned char *) &pRequestSense)[0]);
+          for (i = 1; i < sizeof(RequestSense_T); i++)
+            DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((unsigned char *) &pRequestSense)[i]);
+          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"\n");
           return(ret);
         }
       if ( ret > 0)
@@ -5597,18 +5638,20 @@ int SCSI_AlignElements(int DeviceFD, int AE_MTE, int AE_DTE, int AE_STE)
         {
           DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_AlignElements : end %d\n", ret);
           return(ret);
-        } 
+        }
     }
-  return(ret);
+  DebugPrint(DEBUG_ERROR, SECTION_SCSI,"SCSI_AlignElements :"
+            "Retries exceeded = %d\n", retry);
+  return(-1);
 }
 
 
 int SCSI_Move(int DeviceFD, unsigned char chm, int from, int to)
 {
   RequestSense_T *pRequestSense;
-  int retry = 1;
+  int retry;
   CDB_T CDB;
-  int ret;
+  int ret = -1;
   int i;
 
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### START SCSI_Move\n");
@@ -5619,7 +5662,7 @@ int SCSI_Move(int DeviceFD, unsigned char chm, int from, int to)
       return(-1);
     }
 
-  while (retry > 0 && retry < MAX_RETRIES)
+  for (retry = 0; (ret != 0) && (retry < MAX_RETRIES); retry++)
     {
       CDB[0]  = SC_MOVE_MEDIUM;
       CDB[1]  = 0;
@@ -5631,20 +5674,20 @@ int SCSI_Move(int DeviceFD, unsigned char chm, int from, int to)
       CDB[9]  = 0;
       CDB[10] = 0;
       CDB[11] = 0;
-      
+
       ret = SCSI_Run(DeviceFD, Input, CDB, 12,
-                                NULL, 0, (char *)pRequestSense, sizeof(RequestSense_T)); 
+                                NULL, 0, (char *)pRequestSense, sizeof(RequestSense_T));
 
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_Move : SCSI_Run = %d\n", ret);
       DecodeSense(pRequestSense, "SCSI_Move :",debug_file);
 
       if (ret < 0)
         {
-          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"%s: Request Sense[Inquiry]: %02X", 
-                    "chs", ((unsigned char *) &pRequestSense)[0]); 
-          for (i = 1; i < sizeof(RequestSense_T); i++)                
-            DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((unsigned char *) &pRequestSense)[i]); 
-          DebugPrint(DEBUG_INFO, SECTION_SCSI,"\n");    
+          DebugPrint(DEBUG_ERROR, SECTION_SCSI,"%s: Request Sense[Inquiry]: %02X",
+                    "chs", ((unsigned char *) &pRequestSense)[0]);
+          for (i = 1; i < sizeof(RequestSense_T); i++)
+            DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((unsigned char *) &pRequestSense)[i]);
+          DebugPrint(DEBUG_INFO, SECTION_SCSI,"\n");
           return(ret);
         }
       if ( ret > 0)
@@ -5672,12 +5715,8 @@ int SCSI_Move(int DeviceFD, unsigned char chm, int from, int to)
               break;
             }
         }
-      if (ret == 0)
-        {
-          dbprintf(("SCSI_Move : end %d\n", ret));
-          return(ret);
-        } 
     }
+  dbprintf(("SCSI_Move : end %d\n", ret));
   return(ret);
 }
 
@@ -5687,25 +5726,25 @@ int SCSI_LoadUnload(int DeviceFD, RequestSense_T *pRequestSense, unsigned char b
   int ret;
 
   dbprintf(("##### START SCSI_LoadUnload\n"));
-  
+
   CDB[0] = SC_COM_UNLOAD;
-  CDB[1] = byte1;             
+  CDB[1] = byte1;
   CDB[2] = 0;
   CDB[3] = 0;
   CDB[4] = load;
   CDB[5] = 0;
-  
+
+
   ret = SCSI_Run(DeviceFD, Input, CDB, 6,
-                            NULL, 0, 
+                            NULL, 0,
                             (char *) pRequestSense,
                             sizeof(RequestSense_T));
-    
+
   if (ret < 0)
     {
       dbprintf(("SCSI_Unload : failed %d\n", ret));
       return(-1);
-    } 
+    }
 
   return(ret);
 }
@@ -5725,12 +5764,12 @@ int SCSI_TestUnitReady(int DeviceFD, RequestSense_T *pRequestSense)
   CDB[5] = 0;
 
   ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB, 6,
-                      NULL, 0, 
+                      NULL, 0,
                       (char *) pRequestSense,
                       sizeof(RequestSense_T));
 
   /*
-   * We got an error, so let the calling function handle this 
+   * We got an error, so let the calling function handle this
    */
   if (ret > 0)
     {
@@ -5760,10 +5799,10 @@ int SCSI_ModeSelect(int DeviceFD, char *buffer, unsigned char length, unsigned c
 {
   CDB_T CDB;
   RequestSense_T *pRequestSense;
-  int ret;
+  int ret = -1;
   int retry = 1;
   char *sendbuf;
-  
+
   dbprintf(("##### START SCSI_ModeSelect\n"));
 
   dbprintf(("SCSI_ModeSelect start length = %d:\n", length));
@@ -5773,10 +5812,11 @@ int SCSI_ModeSelect(int DeviceFD, char *buffer, unsigned char length, unsigned c
           return(-1);
       }
 
-  
+
   if ((sendbuf = (char *)malloc(length + 4)) == NULL)
     {
       dbprintf(("SCSI_ModeSelect : malloc failed\n"));
+      free(pRequestSense);
       return(-1);
     }
 
@@ -5785,33 +5825,40 @@ int SCSI_ModeSelect(int DeviceFD, char *buffer, unsigned char length, unsigned c
   memcpy(&sendbuf[4], buffer, length);
   dump_hex(sendbuf, length+4, DEBUG_INFO, SECTION_SCSI);
 
-  while (retry > 0 && retry < MAX_RETRIES)
+  for (retry = 0; (ret != 0) && (retry < MAX_RETRIES); retry++)
     {
       memset(pRequestSense, 0, sizeof(RequestSense_T));
-      
+
       CDB[0] = SC_COM_MODE_SELECT;
       CDB[1] = ((lun << 5) & 0xF0) | ((mode << 4) & 0x10) | (save & 1);
       CDB[2] = 0;
       CDB[3] = 0;
       CDB[4] = length + 4;
       CDB[5] = 0;
-      ret = SCSI_Run(DeviceFD, Output, CDB, 6,                      
+      ret = SCSI_Run(DeviceFD, Output, CDB, 6,
                                 sendbuf,
-                                length + 4, 
+                                length + 4,
                                 (char *) pRequestSense,
                                 sizeof(RequestSense_T));
       if (ret < 0)
         {
           dbprintf(("SCSI_ModeSelect : ret %d\n", ret));
+         free(pRequestSense);
+         free(sendbuf);
           return(ret);
         }
-      
+
       if ( ret > 0)
         {
-          switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, (char *)pRequestSense))
+          switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey,
+                             pRequestSense->AdditionalSenseCode,
+                             pRequestSense->AdditionalSenseCodeQualifier,
+                             (char *)pRequestSense))
             {
             case SENSE_IGNORE:
               dbprintf(("SCSI_ModeSelect : SENSE_IGNORE\n"));
+             free(pRequestSense);
+             free(sendbuf);
               return(0);
               break;
             case SENSE_RETRY:
@@ -5819,18 +5866,16 @@ int SCSI_ModeSelect(int DeviceFD, char *buffer, unsigned char length, unsigned c
               break;
             default:
               dbprintf(("SCSI_ModeSelect : end %d\n", pRequestSense->SenseKey));
+             free(pRequestSense);
+             free(sendbuf);
               return(pRequestSense->SenseKey);
               break;
             }
         }
-      retry++;
-      if (ret == 0)
-        {
-          dbprintf(("SCSI_ModeSelect end: %d\n", ret));
-          return(ret);
-        }
     }
   dbprintf(("SCSI_ModeSelect end: %d\n", ret));
+  free(pRequestSense);
+  free(sendbuf);
   return(ret);
 }
 
@@ -5856,23 +5901,23 @@ int SCSI_ModeSense(int DeviceFD, char *buffer, u_char size, u_char byte1, u_char
     {
       memset(pRequestSense, 0, sizeof(RequestSense_T));
       memset(buffer, 0, size);
-      
+
       CDB[0] = SC_COM_MODE_SENSE;
       CDB[1] = byte1;
       CDB[2] = byte2;
       CDB[3] = 0;
       CDB[4] = size;
       CDB[5] = 0;
-      ret = SCSI_Run(DeviceFD, Input, CDB, 6,                      
+      ret = SCSI_Run(DeviceFD, Input, CDB, 6,
                                 buffer,
-                                size, 
+                                size,
                                 (char *) pRequestSense,
                                 sizeof(RequestSense_T));
       if (ret < 0)
         {
           return(ret);
         }
-      
+
       if ( ret > 0)
         {
           switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, (char *)pRequestSense))
@@ -5924,19 +5969,19 @@ int SCSI_Inquiry(int DeviceFD, SCSIInquiry_T *buffer, u_char size)
       CDB[3] = 0;
       CDB[4] = size;
       CDB[5] = 0;
-      
-      ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB, 6,                      
+
+      ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB, 6,
                                 buffer,
-                                size, 
+                                size,
                                 (char *) pRequestSense,
                             sizeof(RequestSense_T));
       if (ret < 0)
         {
           DebugPrint(DEBUG_ERROR, SECTION_SCSI,"%s: Request Sense[Inquiry]: %02X",
                     "chs", ((unsigned char *) pRequestSense)[0]);
-          for (i = 1; i < sizeof(RequestSense_T); i++)               
+          for (i = 1; i < sizeof(RequestSense_T); i++)
             DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((unsigned char *) pRequestSense)[i]);
-          DebugPrint(DEBUG_ERROR, SECTION_SCSI, "\n");   
+          DebugPrint(DEBUG_ERROR, SECTION_SCSI, "\n");
       DebugPrint(DEBUG_ERROR, SECTION_SCSI, "Inquiry end: %d\n", ret);
       return(ret);
         }
@@ -5965,24 +6010,24 @@ int SCSI_Inquiry(int DeviceFD, SCSIInquiry_T *buffer, u_char size)
           return(ret);
         }
     }
-  
+
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_Inquiry end: %d\n", ret);
   return(ret);
 }
 
 /*
- * Read the Element Status. If DescriptorSize  != 0 then 
+ * Read the Element Status. If DescriptorSize  != 0 then
  * allocate DescriptorSize * NoOfElements for the result from the
- * Read Element Status command. 
+ * Read Element Status command.
  * If DescriptorSize == 0 than try to figure out how much space is needed
- * by 
+ * by
  * 1. do an read with an allocation size of 8
  * 2. from the result take the 'Byte Count of Descriptor Available'
  * 3. do again an Read Element Status with the result from 2.
  *
  */
-int SCSI_ReadElementStatus(int DeviceFD, 
-                           unsigned char type, 
+int SCSI_ReadElementStatus(int DeviceFD,
+                           unsigned char type,
                            unsigned char lun,
                            unsigned char VolTag,
                            int StartAddress,
@@ -5995,8 +6040,8 @@ int SCSI_ReadElementStatus(int DeviceFD,
   ElementStatusData_T *ElementStatusData;
   RequestSense_T *pRequestSense;
   int retry = 1;
-  int ret = -1; 
+  int ret = -1;
+
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### START SCSI_ReadElementStatus\n");
 
   if ((pRequestSense = (RequestSense_T *)malloc(sizeof(RequestSense_T))) == NULL)
@@ -6004,7 +6049,7 @@ int SCSI_ReadElementStatus(int DeviceFD,
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_ReadElementStatus : malloc failed\n");
       ChgExit("SCSI_ReadElementStatus","malloc failed", FATAL);
     }
-  
+
   /*
    * How many elements, if <= 0 than exit with an fatal error
    */
@@ -6029,29 +6074,29 @@ int SCSI_ReadElementStatus(int DeviceFD,
        } else {
          *data = malloc(8);
        }
-      
+
       memset(*data, 0, 8);
-      
-      
-      
+
+
+
       while (retry > 0 && retry < MAX_RETRIES)
        {
          memset(pRequestSense, 0, sizeof(RequestSense_T) );
-         
+
          CDB[0] = SC_COM_RES;          /* READ ELEMENT STATUS */
          CDB[1] = VolTag | type | lun; /* Element Type Code , VolTag, LUN */
          MSB2(&CDB[2], StartAddress);  /* Starting Element Address */
          MSB2(&CDB[4], NoOfElements);  /* Number Of Element */
-         CDB[6] = 0;                             /* Reserved */                          
-         MSB3(&CDB[7],8);                   /* Allocation Length */    
-         CDB[10] = 0;                           /* Reserved */                           
-         CDB[11] = 0;                           /* Control */                             
-         
-         ret = SCSI_Run(DeviceFD, Input, CDB, 12,                      
-                        *data, 8, 
+         CDB[6] = 0;                             /* Reserved */
+         MSB3(&CDB[7],8);                   /* Allocation Length */
+         CDB[10] = 0;                           /* Reserved */
+         CDB[11] = 0;                           /* Control */
+
+         ret = SCSI_Run(DeviceFD, Input, CDB, 12,
+                        *data, 8,
                         (char *)pRequestSense, sizeof(RequestSense_T));
-         
-         
+
+
          DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_ReadElementStatus : (1) SCSI_Run %d\n", ret);
          if (ret < 0)
            {
@@ -6088,12 +6133,12 @@ int SCSI_ReadElementStatus(int DeviceFD,
          DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP SCSI_ReadElementStatus (%d)\n",ret);
          return(ret);
        }
+
       ElementStatusData = (ElementStatusData_T *)*data;
       DataBufferLength = V3(ElementStatusData->count);
 
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_ReadElementStatus: DataBufferLength %X, ret %d\n",DataBufferLength, ret);
-      
+
       dump_hex(*data, 8, DEBUG_INFO, SECTION_ELEMENT);
     } else { /* DescriptorSize != 0 */
       DataBufferLength = NoOfElements * DescriptorSize;
@@ -6107,21 +6152,21 @@ int SCSI_ReadElementStatus(int DeviceFD,
   while (retry > 0 && retry < MAX_RETRIES)
     {
       memset(pRequestSense, 0, sizeof(RequestSense_T) );
-      
+
       CDB[0] = SC_COM_RES;           /* READ ELEMENT STATUS */
       CDB[1] = VolTag | type | lun;  /* Element Type Code, VolTag, LUN */
       MSB2(&CDB[2], StartAddress);   /* Starting Element Address */
       MSB2(&CDB[4], NoOfElements);   /* Number Of Element */
-      CDB[6] = 0;                              /* Reserved */                      
-      MSB3(&CDB[7],DataBufferLength);  /* Allocation Length */    
-      CDB[10] = 0;                                 /* Reserved */                      
-      CDB[11] = 0;                                 /* Control */                       
-      
-      ret = SCSI_Run(DeviceFD, Input, CDB, 12,                      
-                                *data, DataBufferLength, 
+      CDB[6] = 0;                              /* Reserved */
+      MSB3(&CDB[7],DataBufferLength);  /* Allocation Length */
+      CDB[10] = 0;                                 /* Reserved */
+      CDB[11] = 0;                                 /* Control */
+
+      ret = SCSI_Run(DeviceFD, Input, CDB, 12,
+                                *data, DataBufferLength,
                                 (char *)pRequestSense, sizeof(RequestSense_T));
-      
-      
+
+
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_ReadElementStatus : (2) SCSI_Run %d\n", ret);
       if (ret < 0)
         {
@@ -6159,7 +6204,7 @@ int SCSI_ReadElementStatus(int DeviceFD,
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP SCSI_ReadElementStatus (%d)\n",ret);
       return(ret);
     }
+
   dump_hex(*data, DataBufferLength, DEBUG_INFO, SECTION_SCSI);
   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP SCSI_ReadElementStatus (%d)\n",ret);
   return(ret);
@@ -6197,6 +6242,5 @@ printf_arglist_function2(void DebugPrint, int, level, int, section, char *, fmt)
          }
        }
     }
-  arglist_end(argp);  
-
+  arglist_end(argp);
 }
index 8ac7ffa88c707ce2ccf341060a091f30e705e026..fd8d3ee524bb0a7527f3ee26a15ef8be32d597f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Id: scsi-chio.c,v 1.5.4.8 1999/06/17 18:33:19 th Exp $
+ *     $Id: scsi-chio.c,v 1.13 2000/06/25 18:48:11 ant Exp $
  *
  *     scsi-chio.c -- library routines to handle the changer
  *                     support for chio based systems
index d0f50f771369710d0457a5c6ed6e5e7abfb1acda..d7ae82fb24a53bb209ea8d333fe3d4cc2530d920 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- *     $Id: scsi-hpux.c,v 1.4.4.9.6.1 2002/08/22 17:41:10 martinea Exp $
+ * $Id: scsi-hpux.c,v 1.14 2001/02/08 19:19:08 ant Exp $
  *
  *     scsi-chio.c -- library routines to handle the changer
  *                     support for chio based systems
index 56d2976797bf7ed4c573fe5f331d12f25e58300e..c046734b8dc5f63e8a05f6a7078bc4e2b5fc3f07 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-hpux_new.c,v 1.1.2.12.4.1.2.4 2003/06/05 20:44:23 martinea Exp $
+ * $Id: scsi-hpux_new.c,v 1.18 2005/10/15 13:20:47 martinea Exp $
  *
  * Interface to execute SCSI commands on an HP-UX Workstation
  *
@@ -60,7 +60,7 @@
 void SCSI_OS_Version()
 {
 #ifndef lint
-    static char rcsid[] = "$Id: scsi-hpux_new.c,v 1.1.2.12.4.1.2.4 2003/06/05 20:44:23 martinea Exp $";
+    static char rcsid[] = "$Id: scsi-hpux_new.c,v 1.18 2005/10/15 13:20:47 martinea Exp $";
    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -74,7 +74,7 @@ int SCSI_OpenDevice(int ip)
   if (pDev[ip].inqdone == 0)
     {
       pDev[ip].inqdone = 1;
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
         {
           pDev[ip].avail = 1;
           pDev[ip].fd = DeviceFD;
@@ -120,7 +120,7 @@ int SCSI_OpenDevice(int ip)
           return(1);
         }
     } else {
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
         {
           pDev[ip].fd = DeviceFD;
           pDev[ip].devopen = 1;
@@ -185,7 +185,16 @@ int SCSI_ExecuteCommand(int DeviceFD,
   while (--Retries > 0) {
 
     if (pDev[DeviceFD].devopen == 0)
-      SCSI_OpenDevice(DeviceFD);
+      {
+        if (SCSI_OpenDevice(DeviceFD) == 0)
+          {
+            dbprintf(("SCSI_ExecuteCommand could not open %s: %s\n",
+                      pDev[DeviceFD].dev,
+                     strerror(errno)));
+            sleep(1); /* Give device a little time befor retry */
+            continue;
+          }
+      }
 
     DecodeSCSI(CDB, "SCSI_ExecuteCommand : ");
     Result = ioctl(pDev[DeviceFD].fd, SIOC_IO, &sctl_io);
@@ -224,9 +233,8 @@ int Tape_Ioctl( int DeviceFD, int command)
   int ret = 0;
 
   if (pDev[DeviceFD].devopen == 0)
-    {
-      SCSI_OpenDevice(DeviceFD);
-    }
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
 
   switch (command)
     {
@@ -258,7 +266,8 @@ int Tape_Status( int DeviceFD)
   int ret = 0;
 
   if (pDev[DeviceFD].devopen == 0)
-    SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
 
   if (ioctl(pDev[DeviceFD].fd, MTIOCGET, &mtget) != 0)
   {
index 1e635c9e46811a7053969a896b19c0a4e45ad6a9..b747884d54f7d6d26d8842f9be00505e2a9b91d3 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-irix.c,v 1.1.2.13.4.1.2.5 2003/01/26 19:20:57 martinea Exp $
+ * $Id: scsi-irix.c,v 1.22 2005/10/15 13:20:47 martinea Exp $
  *
  * Interface to execute SCSI commands on an SGI Workstation
  *
@@ -62,7 +62,7 @@
 void SCSI_OS_Version()
 {
 #ifndef lint
-   static char rcsid[] = "$Id: scsi-irix.c,v 1.1.2.13.4.1.2.5 2003/01/26 19:20:57 martinea Exp $";
+   static char rcsid[] = "$Id: scsi-irix.c,v 1.22 2005/10/15 13:20:47 martinea Exp $";
    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -78,7 +78,7 @@ int SCSI_OpenDevice(int ip)
   
   if (pDev[ip].inqdone == 0)
     {
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR | O_EXCL)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR | O_EXCL)) >= 0)
         {
           pDev[ip].inqdone = 1;          pDev[ip].SCSI = 0;
           pDev[ip].avail = 1;
@@ -135,7 +135,7 @@ int SCSI_OpenDevice(int ip)
           return(0);
         }
     } else {
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR | O_EXCL)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR | O_EXCL)) >= 0)
         {
           pDev[ip].fd = DeviceFD;
           pDev[ip].devopen = 1;
@@ -212,7 +212,14 @@ int SCSI_ExecuteCommand(int DeviceFD,
   while (--retries > 0) {
     if (pDev[DeviceFD].devopen == 0)
       {
-        SCSI_OpenDevice(DeviceFD);
+        if (SCSI_OpenDevice(DeviceFD) == 0)
+          {
+            dbprintf(("SCSI_ExecuteCommand could not open %s: %s\n",
+                      pDev[DeviceFD].dev,
+                     strerror(errno)));
+            sleep(1); /* Give device a little time befor retry */
+            continue;
+          }
       }
     Result = ioctl(pDev[DeviceFD].fd, DS_ENTER, &ds);
     SCSI_CloseDevice(DeviceFD);
@@ -273,7 +280,8 @@ int Tape_Ioctl ( int DeviceFD, int command)
   
   if (pDev[DeviceFD].devopen == 0)
     {
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
     }
   
   switch (command)
@@ -299,7 +307,8 @@ int Tape_Status( int DeviceFD)
 
   if (pDev[DeviceFD].devopen == 0)
     {
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
     }
 
   if (ioctl(pDev[DeviceFD].fd , MTIOCGET, &mtget) != 0)
@@ -343,7 +352,11 @@ int ScanBus(int print)
   extern int errno;
   int count = 0;
 
-  dir = opendir("/dev/scsi");
+  if ((dir = opendir("/dev/scsi")) == NULL)
+    {
+      dbprintf(("Can not read /dev/scsi: %s", strerror(errno)));
+      return 0;
+    }
 
   while ((dirent = readdir(dir)) != NULL)
     {
index 6557fbc68f72090fbe260354e0e412b377a25c38..750bd626cae3acee7fa1190903ac20afab224ccb 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-linux.c,v 1.1.2.18.4.1.2.5 2003/07/05 16:59:01 ant Exp $
+ * $Id: scsi-linux.c,v 1.28 2006/03/09 20:06:10 johnfranks Exp $
  *
  * Interface to execute SCSI commands on Linux
  *
@@ -82,7 +82,7 @@
 void SCSI_OS_Version()
 {
 #ifndef lint
-   static char rcsid[] = "$Id: scsi-linux.c,v 1.1.2.18.4.1.2.5 2003/07/05 16:59:01 ant Exp $";
+   static char rcsid[] = "$Id: scsi-linux.c,v 1.28 2006/03/09 20:06:10 johnfranks Exp $";
    DebugPrint(DEBUG_ERROR, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -118,8 +118,6 @@ int SCSI_OpenDevice(int ip)
   int DeviceFD;
   int i;
   int timeout;
-  int sg_info = 0;                /* Used to get some infos about the sg interface */
-  int ret = 0;                    /* To store return results from ioctl etc */
   struct stat pstat;
   char *buffer = NULL ;           /* Will contain the device name after checking */
   int openmode = O_RDONLY;
@@ -177,13 +175,14 @@ int SCSI_OpenDevice(int ip)
         }
       
       DebugPrint(DEBUG_INFO, SECTION_SCSI,"Try to open %s\n", buffer);
-      if ((DeviceFD = open(buffer, openmode)) > 0)
+      if ((DeviceFD = open(buffer, openmode)) >= 0)
         {
           pDev[ip].avail = 1;
           pDev[ip].devopen = 1;
           pDev[ip].fd = DeviceFD;
         } else {
           DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP SCSI_OpenDevice open failed\n");
+         amfree(buffer);
           return(0);
         }
       
@@ -193,23 +192,9 @@ int SCSI_OpenDevice(int ip)
           pDev[ip].SCSI = 1;
         }
       
-      pDev[ip].dev = stralloc(buffer);
+      pDev[ip].dev = buffer;
       if (pDev[ip].SCSI == 1)
         {
-          if ((ret = ioctl(DeviceFD, SG_GET_VERSION_NUM, &sg_info)) == 0)
-            {
-              DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_OpenDevice : SG_VERSION %d\n",sg_info);  
-            } else {
-              DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_OpenDevice : SG_VERSION ioctl returned %d\n", ret);
-            }
-
-          if ((ret = ioctl(DeviceFD, SG_GET_RESERVED_SIZE, &sg_info)) == 0)
-            {
-              DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_OpenDevice : SG_RESERVED_SIZE %d\n",sg_info);  
-            } else {
-              DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_OpenDevice : SG_RESERVED_SIZE ioctl returned %d\n", ret);
-            }
-
           DebugPrint(DEBUG_INFO, SECTION_SCSI,"SCSI_OpenDevice : use SG interface\n");
           if ((timeout = ioctl(pDev[ip].fd, SG_GET_TIMEOUT)) > 0) 
             {
@@ -248,7 +233,7 @@ int SCSI_OpenDevice(int ip)
                   return(1);
                 } else {
                   close(DeviceFD);
-                  free(pDev[ip].inquiry);
+                  amfree(pDev[ip].inquiry);
                   DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP SCSI_OpenDevice (0)\n");
                   return(0);
                 }
@@ -256,7 +241,7 @@ int SCSI_OpenDevice(int ip)
               pDev[ip].SCSI = 0;
               pDev[ip].devopen = 0;
               close(DeviceFD);
-              free(pDev[ip].inquiry);
+              amfree(pDev[ip].inquiry);
               pDev[ip].inquiry = NULL;
               DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### STOP SCSI_OpenDevice (1)\n");
               return(1);
@@ -276,7 +261,7 @@ int SCSI_OpenDevice(int ip)
         } else {
           openmode = O_RDONLY;
         }
-      if ((DeviceFD = open(pDev[ip].dev, openmode)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, openmode)) >= 0)
         {
           pDev[ip].devopen = 1;
           pDev[ip].fd = DeviceFD;
@@ -325,18 +310,22 @@ int SCSI_ExecuteCommand(int DeviceFD,
     }
 
   if (pDev[DeviceFD].devopen == 0)
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
+  
+  if (SCSI_OFF + CDB_Length + DataBufferLength > 4096) 
     {
-      SCSI_OpenDevice(DeviceFD);
+      SCSI_CloseDevice(DeviceFD);
+      return(-1);
     }
-  
-/*   if (SCSI_OFF + CDB_Length + DataBufferLength > 4096)  */
-/*     { */
-/*       SCSI_CloseDevice(DeviceFD); */
-/*       DebugPrint(DEBUG_ERROR, SECTION_SCSI,"##### SCSI_ExecuteCommand error, SCSI_OFF + CDB_Length + DataBufferLength > 4096\n"); */
-/*       return(-1); */
-/*     } */
 
   buffer = (char *)malloc(SCSI_OFF + CDB_Length + DataBufferLength);
+  if (buffer == NULL)
+    {
+      dbprintf(("SCSI_ExecuteCommand memory allocation failure.\n"));
+      SCSI_CloseDevice(DeviceFD);
+      return(-1);
+    }
   memset(buffer, 0, SCSI_OFF + CDB_Length + DataBufferLength);
   memcpy(buffer + SCSI_OFF, CDB, CDB_Length);
   
@@ -368,6 +357,7 @@ int SCSI_ExecuteCommand(int DeviceFD,
     {
       dbprintf(("SCSI_ExecuteCommand error send \n"));
       SCSI_CloseDevice(DeviceFD);
+      amfree(buffer);
       return(SCSI_ERROR);
     }
   
@@ -380,8 +370,9 @@ int SCSI_ExecuteCommand(int DeviceFD,
        psg_header->result ) 
     { 
       dbprintf(("SCSI_ExecuteCommand error read \n"));
-      dbprintf(("Status %d (%d) %2X\n", status, SCSI_OFF + DataBufferLength, psg_header->result ));
+      dbprintf(("Status %d (%d) %2X\n", status, SCSI_OFF + DataBufferLength,psg_header->result ));
       SCSI_CloseDevice(DeviceFD);
+      amfree(buffer);
       return(SCSI_ERROR);
     }
 
@@ -390,8 +381,8 @@ int SCSI_ExecuteCommand(int DeviceFD,
        memcpy(DataBuffer, buffer + SCSI_OFF, DataBufferLength);
     }
 
-  free(buffer);
   SCSI_CloseDevice(DeviceFD);
+  amfree(buffer);
   return(SCSI_OK);
 }
 
@@ -417,7 +408,7 @@ int SCSI_OpenDevice(int ip)
   if (pDev[ip].inqdone == 0)
     {
       pDev[ip].inqdone = 1;
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR)) >= 0)
         {
           pDev[ip].avail = 1;
           pDev[ip].fd = DeviceFD;
@@ -435,20 +426,20 @@ int SCSI_OpenDevice(int ip)
                   PrintInquiry(pDev[ip].inquiry);
                   return(1);
                 } else {
-                  free(pDev[ip].inquiry);
+                  amfree(pDev[ip].inquiry);
                   close(DeviceFD);
                   return(0);
                 }
             } else {
               close(DeviceFD);
-              free(pDev[ip].inquiry);
+              amfree(pDev[ip].inquiry);
               pDev[ip].inquiry = NULL;
               return(1);
             }
         }
       return(1); 
     } else {
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR)) >= 0)
         {
           pDev[ip].fd = DeviceFD;
           pDev[ip].devopen = 1;
@@ -480,7 +471,8 @@ int SCSI_ExecuteCommand(int DeviceFD,
 
   if (pDev[DeviceFD].devopen == 0)
     {
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
     }
 
   memset(pRequestSense, 0, RequestSenseLength);
@@ -510,7 +502,7 @@ int SCSI_ExecuteCommand(int DeviceFD,
     memcpy(pRequestSense, &Command[8], RequestSenseLength);
   else if (Direction == Input)
     memcpy(DataBuffer, &Command[8], DataBufferLength);
-  free(Command);
+  amfree(Command);
   SCSI_CloseDevice(DeviceFD);
 
   switch(Result)
@@ -537,7 +529,8 @@ int Tape_Ioctl( int DeviceFD, int command)
 
   if (pDev[DeviceFD].devopen == 0)
     {
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
     }
 
   switch (command)
@@ -569,7 +562,8 @@ int Tape_Status( int DeviceFD)
 
   if (pDev[DeviceFD].devopen == 0)
     {
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
     }
 
   if (ioctl(pDev[DeviceFD].fd , MTIOCGET, &mtget) != 0)
@@ -622,7 +616,11 @@ int ScanBus(int print)
   extern int errno;
   int count = 0;
 
-  dir = opendir("/dev/");
+  if ((dir = opendir("/dev/")) == NULL)
+    {
+      dbprintf(("/dev/ error: %s", strerror(errno)));
+      return 0;
+    }
 
   while ((dirent = readdir(dir)) != NULL)
     {
@@ -681,7 +679,7 @@ int ScanBus(int print)
             count++;
            printf("Count %d\n",count);
           } else {
-            free(pDev[count].dev);
+            amfree(pDev[count].dev);
             pDev[count].dev=NULL;
           }
       }
index 289d1afe42935af957c79f38caad3335b1df48f0..c20003fc733d153db79d1d097a5b05a675609796 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: scsi-solaris.c,v 1.1.2.18.4.1.2.5 2003/01/26 19:20:57 martinea Exp $
+ * $Id: scsi-solaris.c,v 1.25 2005/10/15 13:20:47 martinea Exp $
  *
  * Interface to execute SCSI commands on an Sun Workstation
  *
@@ -60,7 +60,7 @@
 void SCSI_OS_Version()
 {
 #ifndef lint
-   static char rcsid[] = "$Id: scsi-solaris.c,v 1.1.2.18.4.1.2.5 2003/01/26 19:20:57 martinea Exp $";
+   static char rcsid[] = "$Id: scsi-solaris.c,v 1.25 2005/10/15 13:20:47 martinea Exp $";
    DebugPrint(DEBUG_INFO, SECTION_INFO, "scsi-os-layer: %s\n",rcsid);
 #endif
 }
@@ -74,7 +74,7 @@ int SCSI_OpenDevice(int ip)
   if (pDev[ip].inqdone == 0)
     {
       pDev[ip].inqdone = 1;
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NONBLOCK)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NONBLOCK)) >= 0)
         {
           pDev[ip].avail = 1;
           pDev[ip].fd = DeviceFD;
@@ -122,7 +122,7 @@ int SCSI_OpenDevice(int ip)
           return(0);
         }
     } else {
-      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) > 0)
+      if ((DeviceFD = open(pDev[ip].dev, O_RDWR| O_NDELAY)) >= 0)
         {
           pDev[ip].fd = DeviceFD;
           pDev[ip].devopen = 1;
@@ -217,7 +217,11 @@ int SCSI_ExecuteCommand(int DeviceFD,
   while (retries > 0)
   {
     if (pDev[DeviceFD].devopen == 0)
-      SCSI_OpenDevice(DeviceFD);
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+        {
+         sleep(1);
+         continue;
+        }
 
     if ((ret = ioctl(pDev[DeviceFD].fd, USCSICMD, &Command)) >= 0)
     {
@@ -255,9 +259,8 @@ int Tape_Ioctl( int DeviceFD, int command)
   int ret = 0;
 
   if (pDev[DeviceFD].devopen == 0)
-    {
-      SCSI_OpenDevice(DeviceFD);
-    }
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
 
   switch (command)
     {
@@ -287,9 +290,8 @@ int Tape_Status( int DeviceFD)
   int ret = -1;
 
   if (pDev[DeviceFD].devopen == 0)
-    {
-      SCSI_OpenDevice(DeviceFD);
-    }
+      if (SCSI_OpenDevice(DeviceFD) == 0)
+          return(-1);
   
   if (ioctl(pDev[DeviceFD].fd , MTIOCGET, &mtget) != 0)
     {
index 37b9803b0fe23326772bedb840a2eb4b30f40b49..955084740e3c2616dc8927de1d38134008ed15cd 100644 (file)
@@ -768,14 +768,8 @@ int Sense2Action(char *ident,
                                                *text));        
                                        return(pwork->ret);
                                }                       
-                               pwork++;
-                               continue;
                        }
-                       
-                       pwork++;
-                       continue;
                }
-               
                pwork++;
        }
 
@@ -783,7 +777,7 @@ int Sense2Action(char *ident,
         * Ok no match found, so lets return the values from the generic table
         */
        dbprintf(("Sense2Action generic start :\n"));
-       while (generic->ident != NULL)
+       while ((generic != NULL) && generic->ident != NULL)
        {         
                if (generic->sense == -1)
                {
index 43508aa822060ea24a0ffa92189011241bfc2bf9..a7f5b9147675ddecddaf0c4bc6273b8c5306d631 100644 (file)
@@ -1,11 +1,12 @@
 # Makefile for Amanda client programs.
 
-INCLUDES =             -I$(top_srcdir)/common-src
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src
 
 lib_LTLIBRARIES =      libamclient.la
 LIB_EXTENSION = la
 
-libexec_PROGRAMS =     amandad calcsize killpgrp rundump runtar amqde selfcheck sendbackup sendsize versionsuffix
+libexec_PROGRAMS =     amandad noop calcsize killpgrp rundump runtar selfcheck sendbackup sendsize versionsuffix
 
 sbin_SCRIPTS =         @CLIENT_SCRIPTS_OPT@
 
@@ -33,8 +34,11 @@ libamclient_la_LDFLAGS = -release $(VERSION)
 ###
 
 LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
-       ../common-src/libamanda.$(LIB_EXTENSION)
+       libamclient.$(LIB_EXTENSION)
+if WANT_SERVER
+LDADD += ../tape-src/libamtape.$(LIB_EXTENSION)
+endif
+LDADD += ../common-src/libamanda.$(LIB_EXTENSION)
 
 SUFFIXES =             .sh .pl
 
@@ -52,21 +56,19 @@ TEST_PROGS = getfsent
 
 EXTRA_PROGRAMS =       $(TEST_PROGS)
 
-CLEANFILES = *.test.c
+CLEANFILES = *.test.c patch-system
 
 EXTRA_SCRIPTS =                amhpfixdevs             amsinixfixdevs
 
 DISTCLEANFILES =       $(EXTRA_SCRIPTS)
 
-EXTRA_DIST =           amhpfixdevs.sh          amsinixfixdevs.sh       \
-                       amandad-krb4.c          sendbackup-krb4.c       \
-                       sendbackup-krb4.h
+EXTRA_DIST =           amhpfixdevs.sh          amsinixfixdevs.sh
 
 sendbackup_SOURCES =   sendbackup.c            sendbackup.h    \
                        sendbackup-dump.c       sendbackup-gnutar.c
 
-noinst_HEADERS =       amandates.h     getfsent.h      findpass.h      \
-                       client_util.h
+noinst_HEADERS =       amandad.h       amandates.h     getfsent.h      \
+                       findpass.h      client_util.h
 
 install-exec-hook:
        @list="$(sbin_SCRIPTS)"; \
@@ -86,7 +88,7 @@ install-exec-hook:
                chgrp $(SETUID_GROUP) $$pa; \
        done
 if WANT_SETUID_CLIENT
-       @list="calcsize killpgrp rundump runtar amqde"; \
+       @list="calcsize killpgrp rundump runtar"; \
        for p in $$list; do \
                if echo "$(libexec_PROGRAMS)" | grep $$p >/dev/null 2>&1; then \
                        pa=$(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
index 366cc590d12b4eb0567254152d3fd6de699ef2d9..28788ad86ab14e006bf6e7614c0799d7f31b0633 100644 (file)
@@ -19,7 +19,7 @@
 
 
 
-SOURCES = $(libamclient_la_SOURCES) amandad.c amqde.c calcsize.c $(getfsent_SOURCES) killpgrp.c rundump.c runtar.c selfcheck.c $(sendbackup_SOURCES) sendsize.c versionsuffix.c
+SOURCES = $(libamclient_la_SOURCES) amandad.c calcsize.c $(getfsent_SOURCES) killpgrp.c noop.c rundump.c runtar.c selfcheck.c $(sendbackup_SOURCES) sendsize.c versionsuffix.c
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -44,10 +44,11 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-libexec_PROGRAMS = amandad$(EXEEXT) calcsize$(EXEEXT) \
+libexec_PROGRAMS = amandad$(EXEEXT) noop$(EXEEXT) calcsize$(EXEEXT) \
        killpgrp$(EXEEXT) rundump$(EXEEXT) runtar$(EXEEXT) \
-       amqde$(EXEEXT) selfcheck$(EXEEXT) sendbackup$(EXEEXT) \
-       sendsize$(EXEEXT) versionsuffix$(EXEEXT)
+       selfcheck$(EXEEXT) sendbackup$(EXEEXT) sendsize$(EXEEXT) \
+       versionsuffix$(EXEEXT)
+@WANT_SERVER_TRUE@am__append_1 = ../tape-src/libamtape.$(LIB_EXTENSION)
 EXTRA_PROGRAMS = $(am__EXEEXT_1)
 subdir = client-src
 DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
@@ -83,69 +84,71 @@ PROGRAMS = $(libexec_PROGRAMS)
 amandad_SOURCES = amandad.c
 amandad_OBJECTS = amandad.$(OBJEXT)
 amandad_LDADD = $(LDADD)
+@WANT_SERVER_TRUE@am__DEPENDENCIES_1 =  \
+@WANT_SERVER_TRUE@     ../tape-src/libamtape.$(LIB_EXTENSION)
 amandad_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
-       ../common-src/libamanda.$(LIB_EXTENSION)
-amqde_SOURCES = amqde.c
-amqde_OBJECTS = amqde.$(OBJEXT)
-amqde_LDADD = $(LDADD)
-amqde_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 calcsize_SOURCES = calcsize.c
 calcsize_OBJECTS = calcsize.$(OBJEXT)
 calcsize_LDADD = $(LDADD)
 calcsize_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_getfsent_OBJECTS = getfsent.test.$(OBJEXT)
 getfsent_OBJECTS = $(am_getfsent_OBJECTS)
 getfsent_LDADD = $(LDADD)
 getfsent_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 killpgrp_SOURCES = killpgrp.c
 killpgrp_OBJECTS = killpgrp.$(OBJEXT)
 killpgrp_LDADD = $(LDADD)
 killpgrp_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
+       ../common-src/libamanda.$(LIB_EXTENSION)
+noop_SOURCES = noop.c
+noop_OBJECTS = noop.$(OBJEXT)
+noop_LDADD = $(LDADD)
+noop_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 rundump_SOURCES = rundump.c
 rundump_OBJECTS = rundump.$(OBJEXT)
 rundump_LDADD = $(LDADD)
 rundump_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 runtar_SOURCES = runtar.c
 runtar_OBJECTS = runtar.$(OBJEXT)
 runtar_LDADD = $(LDADD)
 runtar_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 selfcheck_SOURCES = selfcheck.c
 selfcheck_OBJECTS = selfcheck.$(OBJEXT)
 selfcheck_LDADD = $(LDADD)
 selfcheck_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_sendbackup_OBJECTS = sendbackup.$(OBJEXT) sendbackup-dump.$(OBJEXT) \
        sendbackup-gnutar.$(OBJEXT)
 sendbackup_OBJECTS = $(am_sendbackup_OBJECTS)
 sendbackup_LDADD = $(LDADD)
 sendbackup_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 sendsize_SOURCES = sendsize.c
 sendsize_OBJECTS = sendsize.$(OBJEXT)
 sendsize_LDADD = $(LDADD)
 sendsize_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 versionsuffix_SOURCES = versionsuffix.c
 versionsuffix_OBJECTS = versionsuffix.$(OBJEXT)
 versionsuffix_LDADD = $(LDADD)
 versionsuffix_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__DEPENDENCIES_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 libexecSCRIPT_INSTALL = $(INSTALL_SCRIPT)
 sbinSCRIPT_INSTALL = $(INSTALL_SCRIPT)
@@ -161,11 +164,11 @@ LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
 CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
        $(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(libamclient_la_SOURCES) amandad.c amqde.c calcsize.c \
-       $(getfsent_SOURCES) killpgrp.c rundump.c runtar.c selfcheck.c \
-       $(sendbackup_SOURCES) sendsize.c versionsuffix.c
-DIST_SOURCES = $(am__libamclient_la_SOURCES_DIST) amandad.c amqde.c \
-       calcsize.c $(getfsent_SOURCES) killpgrp.c rundump.c runtar.c \
+SOURCES = $(libamclient_la_SOURCES) amandad.c calcsize.c \
+       $(getfsent_SOURCES) killpgrp.c noop.c rundump.c runtar.c \
+       selfcheck.c $(sendbackup_SOURCES) sendsize.c versionsuffix.c
+DIST_SOURCES = $(am__libamclient_la_SOURCES_DIST) amandad.c calcsize.c \
+       $(getfsent_SOURCES) killpgrp.c noop.c rundump.c runtar.c \
        selfcheck.c $(sendbackup_SOURCES) sendsize.c versionsuffix.c
 HEADERS = $(noinst_HEADERS)
 ETAGS = etags
@@ -218,7 +221,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -230,9 +235,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -245,6 +253,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -307,10 +316,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -361,7 +373,9 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-INCLUDES = -I$(top_srcdir)/common-src
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src
+
 lib_LTLIBRARIES = libamclient.la
 LIB_EXTENSION = la
 sbin_SCRIPTS = @CLIENT_SCRIPTS_OPT@
@@ -381,25 +395,21 @@ libamclient_la_LDFLAGS = -release $(VERSION)
 # routines, and second to pick up any references in the other libraries.
 ###
 LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-       libamclient.$(LIB_EXTENSION) \
+       libamclient.$(LIB_EXTENSION) $(am__append_1) \
        ../common-src/libamanda.$(LIB_EXTENSION)
-
 SUFFIXES = .sh .pl
 
 # these are used for testing only:
 TEST_PROGS = getfsent
-CLEANFILES = *.test.c
+CLEANFILES = *.test.c patch-system
 EXTRA_SCRIPTS = amhpfixdevs            amsinixfixdevs
 DISTCLEANFILES = $(EXTRA_SCRIPTS)
-EXTRA_DIST = amhpfixdevs.sh            amsinixfixdevs.sh       \
-                       amandad-krb4.c          sendbackup-krb4.c       \
-                       sendbackup-krb4.h
-
+EXTRA_DIST = amhpfixdevs.sh            amsinixfixdevs.sh
 sendbackup_SOURCES = sendbackup.c              sendbackup.h    \
                        sendbackup-dump.c       sendbackup-gnutar.c
 
-noinst_HEADERS = amandates.h   getfsent.h      findpass.h      \
-                       client_util.h
+noinst_HEADERS = amandad.h     amandates.h     getfsent.h      \
+                       findpass.h      client_util.h
 
 getfsent_SOURCES = getfsent.test.c
 all: all-am
@@ -497,9 +507,6 @@ clean-libexecPROGRAMS:
 amandad$(EXEEXT): $(amandad_OBJECTS) $(amandad_DEPENDENCIES) 
        @rm -f amandad$(EXEEXT)
        $(LINK) $(amandad_LDFLAGS) $(amandad_OBJECTS) $(amandad_LDADD) $(LIBS)
-amqde$(EXEEXT): $(amqde_OBJECTS) $(amqde_DEPENDENCIES) 
-       @rm -f amqde$(EXEEXT)
-       $(LINK) $(amqde_LDFLAGS) $(amqde_OBJECTS) $(amqde_LDADD) $(LIBS)
 calcsize$(EXEEXT): $(calcsize_OBJECTS) $(calcsize_DEPENDENCIES) 
        @rm -f calcsize$(EXEEXT)
        $(LINK) $(calcsize_LDFLAGS) $(calcsize_OBJECTS) $(calcsize_LDADD) $(LIBS)
@@ -509,6 +516,9 @@ getfsent$(EXEEXT): $(getfsent_OBJECTS) $(getfsent_DEPENDENCIES)
 killpgrp$(EXEEXT): $(killpgrp_OBJECTS) $(killpgrp_DEPENDENCIES) 
        @rm -f killpgrp$(EXEEXT)
        $(LINK) $(killpgrp_LDFLAGS) $(killpgrp_OBJECTS) $(killpgrp_LDADD) $(LIBS)
+noop$(EXEEXT): $(noop_OBJECTS) $(noop_DEPENDENCIES) 
+       @rm -f noop$(EXEEXT)
+       $(LINK) $(noop_LDFLAGS) $(noop_OBJECTS) $(noop_LDADD) $(LIBS)
 rundump$(EXEEXT): $(rundump_OBJECTS) $(rundump_DEPENDENCIES) 
        @rm -f rundump$(EXEEXT)
        $(LINK) $(rundump_LDFLAGS) $(rundump_OBJECTS) $(rundump_LDADD) $(LIBS)
@@ -574,13 +584,13 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amandad.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amandates.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amqde.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calcsize.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findpass.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getfsent.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getfsent.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/killpgrp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/noop.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rundump.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtar.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/selfcheck.Po@am__quote@
@@ -829,7 +839,7 @@ install-exec-hook:
                echo chgrp $(SETUID_GROUP) $$pa; \
                chgrp $(SETUID_GROUP) $$pa; \
        done
-@WANT_SETUID_CLIENT_TRUE@      @list="calcsize killpgrp rundump runtar amqde"; \
+@WANT_SETUID_CLIENT_TRUE@      @list="calcsize killpgrp rundump runtar"; \
 @WANT_SETUID_CLIENT_TRUE@      for p in $$list; do \
 @WANT_SETUID_CLIENT_TRUE@              if echo "$(libexec_PROGRAMS)" | grep $$p >/dev/null 2>&1; then \
 @WANT_SETUID_CLIENT_TRUE@                      pa=$(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
diff --git a/client-src/amandad-krb4.c b/client-src/amandad-krb4.c
deleted file mode 100644 (file)
index ac1c092..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991 University of Maryland
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
- */
-/*
- * amandad-krb4.c - The Kerberos4 support bits for amandad.c.
- */
-
-#include "krb4-security.h"
-
-void transfer_session_key P((void));
-void add_mutual_authenticator P((dgram_t *msg));
-int krb4_security_ok P((struct sockaddr_in *addr,
-                       char *str, unsigned long cksum, char **errstr));
-
-#define KEY_PIPE       3
-
-void transfer_session_key()
-{
-    int rc, key_pipe[2];
-    int l, n, s;
-    char *k;
-
-    if(pipe(key_pipe) == -1)
-       error("could not open key pipe: %s", strerror(errno));
-
-    k = (char *)session_key;
-    for(l = 0, n = sizeof(session_key); l < n; l += s) {
-       if ((s = write(key_pipe[1], k + l, n - l)) < 0) {
-           error("error writing to key pipe: %s", strerror(errno));
-       }
-    }
-
-    /* modification by BIS@BBN 4/25/2003:
-     * check that key_pipe[0] is not KEY_PIPE before doing dup2 and
-     * close; otherwise we may inadvertently close KEY_PIPE */
-    aclose(key_pipe[1]);
-    if (key_pipe[0] != KEY_PIPE) {
-       dup2(key_pipe[0], KEY_PIPE);
-       close(key_pipe[0]);
-    }
-}
-
-void add_mutual_authenticator(msg)
-dgram_t *msg;
-{
-    union {
-       char pad[8];            /* minimum size for encryption */
-       uint32_t i;             /* "long" on 32-bit machines */
-    } mutual;
-    int alen, blen;
-    char *s;
-
-    blen = sizeof(mutual);
-    memset(&mutual, 0, blen);
-    mutual.i = htonl(auth_cksum+1);
-
-    encrypt_data(&mutual, blen, session_key);
-
-    s = vstralloc("SECURITY MUTUAL-AUTH ",
-                 bin2astr((unsigned char *)mutual.pad, blen),
-                 "\n", NULL);
-    dgram_cat(msg, s);
-    amfree(s);
-}
index 2e1e052c18442f602c854396346cf946bdd324e1..7ba39a4e208c8f354ff4a2cdec1c361a14364170 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
  */
+
 /*
- * $Id: amandad.c,v 1.32.2.4.4.1.2.6.2.2 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amandad.c,v 1.62 2006/03/09 16:51:41 martinea Exp $
  *
  * handle client-host side of Amanda network communications, including
  * security checks, execution of the proper service, and acking the
  * master side
  */
 
+/*#define      AMANDAD_DEBUG*/
+
 #include "amanda.h"
+#include "amandad.h"
 #include "clock.h"
-#include "dgram.h"
+#include "event.h"
 #include "amfeatures.h"
+#include "packet.h"
 #include "version.h"
-#include "protocol.h"
+#include "queue.h"
+#include "security.h"
+#include "stream.h"
 #include "util.h"
 #include "client_util.h"
 
-#define RECV_TIMEOUT 30
-#define ACK_TIMEOUT  10                /* XXX should be configurable */
-#define MAX_RETRIES   5
+#define        REP_TIMEOUT     (6*60*60)       /* secs for service to reply */
+#define        ACK_TIMEOUT     10              /* XXX should be configurable */
+#define        MAX_REP_RETRIES 5
+
+/*
+ * These are the actions for entering the state machine
+ */
+typedef enum { A_START, A_RECVPKT, A_RECVREP, A_PENDING, A_FINISH, A_CONTINUE,
+    A_SENDNAK, A_TIMEOUT } action_t;
+
+/*
+ * This is a state in the state machine.  It is a function pointer to
+ * the function that actually implements the state.
+ */
+struct active_service;
+typedef action_t (*state_t) P((struct active_service *, action_t, pkt_t *));
+
+/*
+ * This structure describes an active running service.
+ *
+ * An active service is something running that we have received
+ * a request for.  This structure holds info on that service, including
+ * file descriptors for data, etc, as well as the security handle
+ * for communications with the amanda server.
+ */
+struct active_service {
+    char *cmd;                         /* name of command we ran */
+    char *arguments;                   /* arguments we sent it */
+    security_handle_t *security_handle;        /* remote server */
+    state_t state;                     /* how far this has progressed */
+    pid_t pid;                         /* pid of subprocess */
+    int send_partial_reply;            /* send PREP packet */
+    int reqfd;                         /* pipe to write requests */
+    int repfd;                         /* pipe to read replies */
+    event_handle_t *ev_repfd;          /* read event handle for repfd */
+    event_handle_t *ev_reptimeout;     /* timeout for rep data */
+    pkt_t rep_pkt;                     /* rep packet we're sending out */
+    char repbuf[MAX_PACKET];           /* buffer to read the rep into */
+    int repbufsize;                    /* length of repbuf */
+    int repretry;                      /* times we'll retry sending the rep */
+    /*
+     * General user streams to the process, and their equivalent
+     * network streams.
+     */
+    struct datafd_handle {
+       int fd;                         /* pipe to child process */
+       event_handle_t *ev_handle;      /* it's read event handle */
+       security_stream_t *netfd;       /* stream to amanda server */
+       struct active_service *as;      /* pointer back to our enclosure */
+    } data[DATA_FD_COUNT];
+    char databuf[NETWORK_BLOCK_BYTES]; /* buffer to relay netfd data in */
+    TAILQ_ENTRY(active_service) tq;    /* queue handle */
+};
 
 /* 
- * Here are the services that we understand.
+ * Here are the services that we allow.
  */
-struct service_s {
-    char *name;
-    int flags;
-#      define NONE             0
-#      define IS_INTERNAL      1       /* service is internal */
-#      define NEED_KEYPIPE     2       /* pass kerberos key in pipe */
-#      define NO_AUTH          4       /* doesn't need authentication */
-} service_table[] = {
-    { "noop",          IS_INTERNAL },
-    { "sendsize",      NONE },
-    { "sendbackup",    NEED_KEYPIPE },
-    { "sendfsinfo",    NONE },
-    { "selfcheck",     NONE },
-    { NULL, NONE }
+static const char *services[] = {
+    "noop",
+    "sendsize",
+    "sendbackup",
+    "selfcheck",
 };
+#define        NSERVICES       (sizeof(services) / sizeof(services[0]))
 
+/*
+ * Queue of outstanding requests that we are running.
+ */
+static struct {
+    TAILQ_HEAD(, active_service) tailq;
+    int qlength;
+} serviceq = {
+    TAILQ_HEAD_INITIALIZER(serviceq.tailq), 0
+};
+
+/*
+ * Data for dbmalloc to check for memory leaks
+ */
+#ifdef USE_DBMALLOC
+static struct {
+    struct {
+       unsigned long size, hist;
+    } start, end;
+} dbmalloc_info;
+#endif
 
-int max_retry_count = MAX_RETRIES;
 int ack_timeout     = ACK_TIMEOUT;
 
-#ifdef KRB4_SECURITY
-#  include "amandad-krb4.c"
+int main P((int argc, char **argv));
+
+static int allocstream P((struct active_service *, int));
+static void exit_check P((void *));
+static void protocol_accept P((security_handle_t *, pkt_t *));
+static void state_machine P((struct active_service *, action_t, pkt_t *));
+
+static action_t s_sendack P((struct active_service *, action_t, pkt_t *));
+static action_t s_repwait P((struct active_service *, action_t, pkt_t *));
+static action_t s_processrep P((struct active_service *, action_t, pkt_t *));
+static action_t s_sendrep P((struct active_service *, action_t, pkt_t *));
+static action_t s_ackwait P((struct active_service *, action_t, pkt_t *));
+
+static void repfd_recv P((void *));
+static void timeout_repfd P((void *));
+static void protocol_recv P((void *, pkt_t *, security_status_t));
+static void process_netfd P((void *));
+static struct active_service *service_new P((security_handle_t *,
+    const char *, const char *));
+static void service_delete P((struct active_service *));
+static int writebuf P((struct active_service *, const void *, size_t));
+static int do_sendpkt P((security_handle_t *handle, pkt_t *pkt));
+
+#ifdef AMANDAD_DEBUG
+static const char *state2str P((state_t));
+static const char *action2str P((action_t));
 #endif
 
-/* local functions */
-int main P((int argc, char **argv));
-void sendack P((pkt_t *hdr, pkt_t *msg));
-void sendnak P((pkt_t *hdr, pkt_t *msg, char *str));
-void setup_rep P((pkt_t *hdr, pkt_t *msg, int partial_rep));
-char *strlower P((char *str));
-
-int main(argc, argv)
-int argc;
-char **argv;
+int
+main(argc, argv)
+    int argc;
+    char **argv;
 {
-    int n;
-    char *errstr = NULL;
-    unsigned long malloc_hist_1, malloc_size_1;
-    unsigned long malloc_hist_2, malloc_size_2;
+    int i, in, out;
+    const security_driver_t *secdrv;
+    int no_exit = 0;
     char *pgm = "amandad";             /* in case argv[0] is not set */
 
-    /* in_msg: The first incoming request.
-       dup_msg: Any other incoming message.
-       out_msg: Standard, i.e. non-repeated, ACK and REP.
-       rej_msg: Any other outgoing message.
-     */
-    pkt_t in_msg, out_msg, out_pmsg, rej_msg, dup_msg;
-    char *cmd = NULL, *base = NULL;
-    char *noop_file = NULL;
-    char **vp;
-    char *s;
-    ssize_t s_len;
-    int retry_count, rc, reqlen;
-    int req_pipe[2], rep_pipe[2];
-    int dglen = 0;
-    char number[NUM_STR_SIZE];
-    am_feature_t *our_features = NULL;
-    char *our_feature_string = NULL;
-    int send_partial_reply = 0;
-
-    struct service_s *servp;
-    fd_set insock;
-
     safe_fd(-1, 0);
     safe_cd();
 
+    if(argv == NULL) {
+       error("argv == NULL\n");
+    }
+
     /*
      * When called via inetd, it is not uncommon to forget to put the
      * argv[0] value on the config line.  On some systems (e.g. Solaris)
@@ -130,41 +196,130 @@ char **argv;
 
     set_pname(pgm);
 
-    malloc_size_1 = malloc_inuse(&malloc_hist_1);
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+#ifdef USE_DBMALLOC
+    dbmalloc_info.start.size = malloc_inuse(&dbmalloc_info.start.hist);
+#endif
 
     erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
 
 #ifdef FORCE_USERID
-
     /* we'd rather not run as root */
-    if(geteuid() == 0) {
-#ifdef KRB4_SECURITY
-        if(client_uid == (uid_t) -1) {
+    if (geteuid() == 0) {
+       if(client_uid == (uid_t) -1) {
            error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN);
        }
-
-        /*
-        * if we're using kerberos security, we'll need to be root in
-        * order to get at the machine's srvtab entry, so we hang on to
-        * some root privledges for now.  We give them up entirely later.
-        */
-       setegid(client_gid);
-       seteuid(client_uid);
-#else
        initgroups(CLIENT_LOGIN, client_gid);
        setgid(client_gid);
-       setuid(client_uid);
-#endif  /* KRB4_SECURITY */
+       setegid(client_gid);
+       seteuid(client_uid);
     }
 #endif /* FORCE_USERID */
 
+    /*
+     * ad-hoc argument parsing
+     *
+     * We accept       -auth=[authentication type]
+     *                 -no-exit
+#ifdef AMANDAD_DEBUG
+     *                 -tcp=[port]
+     *                 -udp=[port]
+#endif
+     */
+    secdrv = NULL;
+    in = 0; out = 1;           /* default to stdin/stdout */
+    for (i = 1; i < argc; i++) {
+       /*
+        * accept -krb4 as an alias for -auth=krb4 (for compatibility)
+        */
+       if (strcmp(argv[i], "-krb4") == 0) {
+           argv[i] = "-auth=krb4";
+           /* FALLTHROUGH */
+       }
+
+       /*
+        * Get a driver for a security type specified after -auth=
+        */
+       if (strncmp(argv[i], "-auth=", strlen("-auth=")) == 0) {
+           argv[i] += strlen("-auth=");
+           secdrv = security_getdriver(argv[i]);
+           if (secdrv == NULL)
+               error("no driver for security type '%s'", argv[i]);
+           continue;
+       }
+
+       /*
+        * If -no-exit is specified, always run even after requests have
+        * been satisfied.
+        */
+       if (strcmp(argv[i], "-no-exit") == 0) {
+           no_exit = 1;
+           continue;
+       }
+
+#ifdef AMANDAD_DEBUG
+       /*
+        * Allow us to directly bind to a udp port for debugging.
+        * This may only apply to some security types.
+        */
+       if (strncmp(argv[i], "-udp=", strlen("-udp=")) == 0) {
+           struct sockaddr_in sin;
+
+           argv[i] += strlen("-udp=");
+           in = out = socket(AF_INET, SOCK_DGRAM, 0);
+           if (in < 0)
+               error("can't create dgram socket: %s\n", strerror(errno));
+           sin.sin_family = AF_INET;
+           sin.sin_addr.s_addr = INADDR_ANY;
+           sin.sin_port = htons(atoi(argv[i]));
+           if (bind(in, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+               error("can't bind to port %d: %s\n", atoi(argv[i]),
+                   strerror(errno));
+       }
+       /*
+        * Ditto for tcp ports.
+        */
+       if (strncmp(argv[i], "-tcp=", strlen("-tcp=")) == 0) {
+           struct sockaddr_in sin;
+           int sock, n;
+
+           argv[i] += strlen("-tcp=");
+           sock = socket(AF_INET, SOCK_STREAM, 0);
+           if (sock < 0)
+               error("can't create tcp socket: %s\n", strerror(errno));
+           n = 1;
+           setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&n, sizeof(n));
+           sin.sin_family = AF_INET;
+           sin.sin_addr.s_addr = INADDR_ANY;
+           sin.sin_port = htons(atoi(argv[i]));
+           if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+               error("can't bind to port %d: %s\n", atoi(argv[i]),
+                   strerror(errno));
+           listen(sock, 10);
+           n = sizeof(sin);
+           in = out = accept(sock, (struct sockaddr *)&sin, &n);
+       }
+#endif
+    }
+
+    /*
+     * If no security type specified, use BSD
+     */
+    if (secdrv == NULL) {
+       secdrv = security_getdriver("BSD");
+       if (secdrv == NULL)
+           error("no driver for default security type 'BSD'");
+    }
+
     /* initialize */
 
     dbopen();
     {
+       /* this lameness is for error() */
        int db_fd = dbfd();
        if(db_fd != -1) {
-           dup2(db_fd, 1);
            dup2(db_fd, 2);
        }
     }
@@ -172,521 +327,1063 @@ char **argv;
     startclock();
 
     dbprintf(("%s: version %s\n", get_pname(), version()));
-    for(vp = version_info; *vp != NULL; vp++)
-       dbprintf(("%s: %s", debug_prefix(NULL), *vp));
+    for (i = 0; version_info[i] != NULL; i++) {
+       dbprintf(("%s: %s", debug_prefix(NULL), version_info[i]));
+    }
 
     if (! (argc >= 1 && argv != NULL && argv[0] != NULL)) {
        dbprintf(("%s: WARNING: argv[0] not defined: check inetd.conf\n",
                  debug_prefix(NULL)));
     }
 
-    our_features = am_init_feature_set();
-    our_feature_string = am_feature_to_string(our_features);
+    /*
+     * Schedule to call protocol_accept() when new security handles
+     * are created on stdin.
+     */
+    security_accept(secdrv, in, out, protocol_accept);
+
+    /*
+     * Schedule an event that will try to exit every 30 seconds if there
+     * are no requests outstanding.
+     */
+    (void)event_register(30, EV_TIME, exit_check, &no_exit);
 
-    dgram_zero(&in_msg.dgram); 
-    dgram_socket(&in_msg.dgram, 0);
+    /*
+     * Call event_loop() with an arg of 0, telling it to block until all
+     * events are completed.
+     */
+    event_loop(0);
 
-    dgram_zero(&dup_msg.dgram);
-    dgram_socket(&dup_msg.dgram, 0);
+    /* NOTREACHED */
+    exit(1);   /* appease gcc/lint */
+}
 
-    dgram_zero(&out_msg.dgram);
-    dgram_socket(&out_msg.dgram, 0);
+/*
+ * This runs periodically and checks to see if we have any active services
+ * still running.  If we don't, then we quit.
+ */
+static void
+exit_check(cookie)
+    void *cookie;
+{
+    int no_exit;
 
-    dgram_zero(&out_pmsg.dgram);
-    dgram_socket(&out_pmsg.dgram, 0);
+    assert(cookie != NULL);
+    no_exit = *(int *)cookie;
 
-    dgram_zero(&rej_msg.dgram);
-    dgram_socket(&rej_msg.dgram, 0);
+    /*
+     * If things are still running, then don't exit.
+     */
+    if (serviceq.qlength > 0)
+       return;
 
-    dgram_zero(&rej_msg.dgram);
-    dgram_socket(&rej_msg.dgram, 0);
+    /*
+     * If the caller asked us to never exit, then we're done
+     */
+    if (no_exit)
+       return;
 
-    /* set up input and response pipes */
+#ifdef USE_DBMALLOC
+    dbmalloc_info.end.size = malloc_inuse(&dbmalloc_info.end.hist);
 
-#ifdef KRB4_SECURITY
-    if(argc >= 2 && strcmp(argv[1], "-krb4") == 0) {
-       krb4_auth = 1;
-       dbprintf(("%s: using krb4 security\n", debug_prefix(NULL)));
-    }
-    else {
-       dbprintf(("%s: using bsd security\n", debug_prefix(NULL)));
-       krb4_auth = 0;
+    if (dbmalloc_info.start.size != dbmalloc_info.end.size) {
+       malloc_list(dbfd(), dbmalloc_info.start.hist,
+           dbmalloc_info.end.hist);
     }
 #endif
 
-    /* get request packet and attempt to parse it */
+    dbclose();
+    exit(0);
+}
 
-    if((n = dgram_recv(&in_msg.dgram, RECV_TIMEOUT, &in_msg.peer)) <= 0) {
-       char *s;
+/*
+ * Handles new incoming protocol handles.  This is a callback for
+ * security_accept(), which gets called when new handles are detected.
+ */
+static void
+protocol_accept(handle, pkt)
+    security_handle_t *handle;
+    pkt_t *pkt;
+{
+    pkt_t pkt_out;
+    struct active_service *as;
+    char *pktbody, *tok, *service, *arguments;
+    int i;
 
-       if (n == 0) {
-           s = "timeout";
-       } else {
-           s = strerror(errno);
-       }
-       error("error receiving message: %s", s);
-    }
-
-    dbprintf(("%s: got packet:\n--------\n%s--------\n\n",
-             debug_prefix_time(NULL), in_msg.dgram.cur));
-
-    parse_pkt_header(&in_msg);
-    if(in_msg.type != P_REQ && in_msg.type != P_NAK && in_msg.type != P_ACK) {
-       /* XXX */
-       dbprintf(("%s: this is a %s packet, nak'ing it\n", 
-                 debug_prefix_time(NULL),
-                 in_msg.type == P_BOGUS? "bogus" : "unexpected"));
-       if(in_msg.type != P_BOGUS) {
-           parse_errmsg = newvstralloc(parse_errmsg,"unexpected ",
-               in_msg.type == P_ACK? "ack ":
-               in_msg.type == P_REP? "rep ": "",
-               "packet", NULL);
-       }
-       sendnak(&in_msg, &rej_msg, parse_errmsg);
-       dbclose();
-       return 1;
+    /*
+     * If pkt is NULL, then there was a problem with the new connection.
+     */
+    if (pkt == NULL) {
+       dbprintf(("%s: accept error: %s\n",
+           debug_prefix_time(NULL), security_geterror(handle)));
+       pkt_init(&pkt_out, P_NAK, "ERROR %s\n", security_geterror(handle));
+       do_sendpkt(handle, &pkt_out);
+       security_close(handle);
+       return;
     }
-    if(in_msg.type != P_REQ) {
-       dbprintf(("%s: strange, this is not a request packet\n",
-                 debug_prefix_time(NULL)));
-       dbclose();
-       return 1;
+
+    dbprintf(("%s: accept recv %s pkt:\n<<<<<\n%s>>>>>\n",
+       debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->body));
+
+    /*
+     * If this is not a REQ packet, just forget about it.
+     */
+    if (pkt->type != P_REQ) {
+       dbprintf(("%s: received unexpected %s packet:\n<<<<<\n%s>>>>>\n\n",
+           debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->body));
+       security_close(handle);
+       return;
     }
 
-    /* lookup service */
+    pktbody = service = arguments = NULL;
+    as = NULL;
+
+    /*
+     * Parse out the service and arguments
+     */
+
+    pktbody = stralloc(pkt->body);
 
-    for(servp = service_table; servp->name != NULL; servp++)
-       if(strcmp(servp->name, in_msg.service) == 0) break;
+    tok = strtok(pktbody, " ");
+    if (tok == NULL)
+       goto badreq;
+    if (strcmp(tok, "SERVICE") != 0)
+       goto badreq;
 
-    if(servp->name == NULL) {
-       errstr = newstralloc2(errstr, "unknown service: ", in_msg.service);
-       sendnak(&in_msg, &rej_msg, errstr);
-       dbclose();
-       return 1;
-    }
+    tok = strtok(NULL, " \n");
+    if (tok == NULL)
+       goto badreq;
+    service = stralloc(tok);
 
-    if((servp->flags & IS_INTERNAL) != 0) {
-       cmd = stralloc(servp->name);
-    } else {
-       base = newstralloc(base, servp->name);
-       cmd = newvstralloc(cmd, libexecdir, "/", base, versionsuffix(), NULL);
-
-       if(access(cmd, X_OK) == -1) {
-           dbprintf(("%s: execute access to \"%s\" denied\n",
-                     debug_prefix_time(NULL), cmd));
-           errstr = newvstralloc(errstr,
-                                 "service ", base, " unavailable",
-                                 NULL);
-           amfree(base);
-           sendnak(&in_msg, &rej_msg, errstr);
-           dbclose();
-           return 1;
-       }
-       amfree(base);
+    /* we call everything else 'arguments' */
+    tok = strtok(NULL, "");
+    if (tok == NULL)
+       goto badreq;
+    arguments = stralloc(tok);
+
+    /* see if it's one we allow */
+    for (i = 0; i < NSERVICES; i++)
+       if (strcmp(services[i], service) == 0)
+           break;
+    if (i == NSERVICES) {
+       dbprintf(("%s: %s: invalid service\n",
+           debug_prefix_time(NULL), service));
+       pkt_init(&pkt_out, P_NAK, "ERROR %s: invalid service\n", service);
+       goto send_pkt_out;
     }
 
-    /* everything looks ok initially, send ACK */
+    service = newvstralloc(service,
+                      libexecdir, "/", service, versionsuffix(),
+                      NULL);
+    if (access(service, X_OK) < 0) {
+       dbprintf(("%s: can't execute %s: %s\n",
+           debug_prefix_time(NULL), service, strerror(errno)));
+           pkt_init(&pkt_out, P_NAK, "ERROR execute access to \"%s\" denied\n",
+           service);
+       goto send_pkt_out;
+    }
 
-    sendack(&in_msg, &out_msg);
+    /* see if its already running */
+    for (as = TAILQ_FIRST(&serviceq.tailq); as != NULL;
+       as = TAILQ_NEXT(as, tq)) {
+           if (strcmp(as->cmd, service) == 0 &&
+               strcmp(as->arguments, arguments) == 0) {
+                   dbprintf(("%s: %s %s: already running, acking req\n",
+                       debug_prefix_time(NULL), service, arguments));
+                   pkt_init(&pkt_out, P_ACK, "");
+                   goto send_pkt_out;
+           }
+    }
 
-    /* 
-     * handle security check: this could take a long time, so it is 
-     * done after the initial ack.
+    /*
+     * create a new service instance, and send the arguments down
+     * the request pipe.
      */
+    dbprintf(("%s: creating new service: %s\n%s\n",
+       debug_prefix_time(NULL), service, arguments));
+    as = service_new(handle, service, arguments);
+    if (writebuf(as, arguments, strlen(arguments)) < 0) {
+       const char *errmsg = strerror(errno);
+       dbprintf(("%s: error sending arguments to %s: %s\n",
+           debug_prefix_time(NULL), service, errmsg));
+       pkt_init(&pkt_out, P_NAK, "ERROR error writing arguments to %s: %s\n",
+           service, errmsg);
+       goto send_pkt_out;
+    }
+    aclose(as->reqfd);
+
+    amfree(pktbody);
+    amfree(service);
+    amfree(arguments);
 
-#if defined(KRB4_SECURITY)
     /*
-     * we need to be root to access the srvtab file, but only if we started
-     * out that way.
+     * Move to the sendack state, and start up the state
+     * machine.
      */
-    setegid(getgid());
-    seteuid(getuid());
-#endif /* KRB4_SECURITY */
+    as->state = s_sendack;
+    state_machine(as, A_START, NULL);
+    return;
+
+badreq:
+    pkt_init(&pkt_out, P_NAK, "ERROR invalid REQ\n");
+    dbprintf(("%s: received invalid %s packet:\n<<<<<\n%s>>>>>\n\n",
+       debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->body));
+
+send_pkt_out:
+    amfree(pktbody);
+    amfree(service);
+    amfree(arguments);
+    if(as) service_delete(as);
+    do_sendpkt(handle, &pkt_out);
+    security_close(handle);
+}
+
+/*
+ * Handles incoming protocol packets.  Routes responses to the proper
+ * running service.
+ */
+static void
+state_machine(as, action, pkt)
+    struct active_service *as;
+    action_t action;
+    pkt_t *pkt;
+{
+    action_t retaction;
+    state_t curstate;
+    pkt_t nak;
+
+#ifdef AMANDAD_DEBUG
+    dbprintf(("%s: state_machine: %X entering\n",
+       debug_prefix_time(NULL), (unsigned int)as));
+#endif
+    for (;;) {
+       curstate = as->state;
+#ifdef AMANDAD_DEBUG
+       dbprintf(("%s: state_machine: %X curstate=%s action=%s\n",
+           debug_prefix_time(NULL), (unsigned int)as,
+           state2str(curstate), action2str(action)));
+#endif
+       retaction = (*curstate)(as, action, pkt);
+#ifdef AMANDAD_DEBUG
+       dbprintf(("%s: state_machine: %X curstate=%s returned %s (nextstate=%s)\n",
+           debug_prefix_time(NULL),
+           (unsigned int)as, state2str(curstate), action2str(retaction),
+           state2str(as->state)));
+#endif
+
+       switch (retaction) {
+       /*
+        * State has queued up and is now blocking on input.
+        */
+       case A_PENDING:
+#ifdef AMANDAD_DEBUG
+           dbprintf(("%s: state_machine: %X leaving (A_PENDING)\n",
+               debug_prefix_time(NULL), (unsigned int)as));
+#endif
+           return;
+
+       /*
+        * service has switched states.  Loop.
+        */
+       case A_CONTINUE:
+           break;
+
+       /*
+        * state has determined that the packet it received was bogus.
+        * Send a nak, and return.
+        */
+       case A_SENDNAK:
+           dbprintf(("%s: received unexpected %s packet\n",
+               debug_prefix_time(NULL), pkt_type2str(pkt->type)));
+           dbprintf(("<<<<<\n%s----\n\n", pkt->body));
+           pkt_init(&nak, P_NAK, "ERROR unexpected packet type %s\n",
+               pkt_type2str(pkt->type));
+           do_sendpkt(as->security_handle, &nak);
+#ifdef AMANDAD_DEBUG
+           dbprintf(("%s: state_machine: %X leaving (A_SENDNAK)\n",
+               debug_prefix_time(NULL), (unsigned int)as));
+#endif
+           return;
+
+       /*
+        * Service is done.  Remove it and finish.
+        */
+       case A_FINISH:
+           service_delete(as);
+#ifdef AMANDAD_DEBUG
+           dbprintf(("%s: state_machine: %X leaving (A_FINISH)\n",
+               debug_prefix_time(NULL), (unsigned int)as));
+#endif
+           return;
 
-    amfree(errstr);
-    if(!(servp->flags & NO_AUTH)
-       && !security_ok(&in_msg.peer, in_msg.security, in_msg.cksum, &errstr)) {
-       /* XXX log on authlog? */
-       setup_rep(&in_msg, &out_msg, 0);
-       ap_snprintf(out_msg.dgram.cur,
-                   sizeof(out_msg.dgram.data)-out_msg.dgram.len,
-                   "ERROR %s\n", errstr);
-       out_msg.dgram.len = strlen(out_msg.dgram.data);
-       goto send_response;
+       default:
+           assert(0);
+           break;
+       }
     }
+    /* NOTREACHED */
+}
+
+/*
+ * This state just sends an ack.  After that, we move to the repwait
+ * state to wait for REP data to arrive from the subprocess.
+ */
+static action_t
+s_sendack(as, action, pkt)
+    struct active_service *as;
+    action_t action;
+    pkt_t *pkt;
+{
+    pkt_t ack;
 
-#if defined(KRB4_SECURITY) && defined(FORCE_USERID)
+    pkt_init(&ack, P_ACK, "");
+    if (do_sendpkt(as->security_handle, &ack) < 0) {
+       dbprintf(("%s: error sending ACK: %s\n",
+           debug_prefix_time(NULL), security_geterror(as->security_handle)));
+       return (A_FINISH);
+    }
 
     /*
-     * we held on to a root uid earlier for accessing files; since we're
-     * done doing anything requiring root, we can completely give it up.
+     * move to the repwait state
+     * Setup a listener for data on the reply fd, but also
+     * listen for packets over the wire, as the server may
+     * poll us if we take a long time.
+     * Setup a timeout that will fire if it takes too long to
+     * receive rep data.
      */
+    as->state = s_repwait;
+    as->ev_repfd = event_register(as->repfd, EV_READFD, repfd_recv, as);
+    as->ev_reptimeout = event_register(REP_TIMEOUT, EV_TIME,
+       timeout_repfd, as);
+    security_recvpkt(as->security_handle, protocol_recv, as, -1);
+    return (A_PENDING);
+}
 
-    if(geteuid() == 0) {
-       if(client_uid == (uid_t) -1) {
-           error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN);
+/*
+ * This is the repwait state.  We have responded to the initial REQ with
+ * an ACK, and we are now waiting for the process we spawned to pass us 
+ * data to send in a REP.
+ */
+static action_t
+s_repwait(as, action, pkt)
+    struct active_service *as;
+    action_t action;
+    pkt_t *pkt;
+{
+    int n;
+
+    /*
+     * We normally shouldn't receive any packets while waiting
+     * for our REP data, but in some cases we do.
+     */
+    if (action == A_RECVPKT) {
+       assert(pkt != NULL);
+       /*
+        * Another req for something that's running.  Just send an ACK
+        * and go back and wait for more data.
+        */
+       if (pkt->type == P_REQ) {
+           dbprintf(("%s: received dup P_REQ packet, ACKing it\n",
+               debug_prefix_time(NULL)));
+           pkt_init(&as->rep_pkt, P_ACK, "");
+           do_sendpkt(as->security_handle, &as->rep_pkt);
+           return (A_PENDING);
        }
-       initgroups(CLIENT_LOGIN, client_gid);
-       setgid(client_gid);
-       setuid(client_uid);
+       /* something unexpected.  Nak it */
+       return (A_SENDNAK);
     }
 
-#endif  /* KRB4_SECURITY && FORCE_USERID */
+    if (action == A_TIMEOUT) {
+       pkt_init(&as->rep_pkt, P_NAK, "ERROR timeout on reply pipe\n");
+       dbprintf(("%s: %s timed out waiting for REP data\n",
+           debug_prefix_time(NULL), as->cmd));
+       do_sendpkt(as->security_handle, &as->rep_pkt);
+       return (A_FINISH);
+    }
 
-    dbprintf(("%s: running service \"%s\"\n", debug_prefix_time(NULL), cmd));
+    assert(action == A_RECVREP);
 
-    if(strcmp(servp->name, "noop") == 0) {
-       ap_snprintf(number, sizeof(number), "%ld", (long)getpid());
-       noop_file = vstralloc(AMANDA_TMPDIR,
-                             "/",
-                             get_pname(),
-                             ".noop.",
-                             number,
-                             NULL);
-       rep_pipe[0] = open(noop_file, O_RDWR|O_EXCL|O_CREAT);
-       if(rep_pipe[0] < 0) {
-           error("cannot open \"%s\": %s", noop_file, strerror(errno));
+    /*
+     * If the read fails, consider the process dead, and remove it.
+     * Always save room for nul termination.
+     */
+    if (as->repbufsize + 1 >= sizeof(as->repbuf)) {
+       dbprintf(("%s: more than %d bytes in reply\n",
+           debug_prefix_time(NULL), sizeof(as->repbuf)));
+       dbprintf(("%s: reply so far:\n%s\n", debug_prefix(NULL), as->repbuf));
+       pkt_init(&as->rep_pkt, P_NAK, "ERROR more than %d bytes in reply\n",
+           sizeof(as->repbuf));
+       do_sendpkt(as->security_handle, &as->rep_pkt);
+       return (A_FINISH);
+    }
+    do {
+       n = read(as->repfd, as->repbuf + as->repbufsize,
+                sizeof(as->repbuf) - as->repbufsize - 1);
+    } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
+    if (n < 0) {
+       const char *errstr = strerror(errno);
+       dbprintf(("%s: read error on reply pipe: %s\n",
+           debug_prefix_time(NULL), errstr));
+       pkt_init(&as->rep_pkt, P_NAK, "ERROR read error on reply pipe: %s\n",
+           errstr);
+       do_sendpkt(as->security_handle, &as->rep_pkt);
+       return (A_FINISH);
+    }
+    /*
+     * If we got some data, go back and wait for more, or EOF.  Nul terminate
+     * the buffer first.
+     */
+    as->repbuf[n + as->repbufsize] = '\0';
+    if (n > 0) {
+       as->repbufsize += n;
+       if(as->send_partial_reply) {
+           pkt_init(&as->rep_pkt, P_PREP, "%s", as->repbuf);
+           do_sendpkt(as->security_handle, &as->rep_pkt);
+           pkt_init(&as->rep_pkt, P_REP, "");
        }
-       (void)unlink(noop_file);
-       s = vstralloc("OPTIONS features=", our_feature_string, ";\n", NULL);
-       s_len = strlen(s);
-       if(fullwrite(rep_pipe[0], s, s_len) != s_len) {
-           error("cannot write %d bytes to %s", s_len, noop_file);
+       return (A_PENDING);
+    }
+
+    /*
+     * If we got 0, then we hit EOF.  Process the data and release
+     * the timeout.
+     */
+    assert(n == 0);
+
+    assert(as->ev_repfd != NULL);
+    event_release(as->ev_repfd);
+    as->ev_repfd = NULL;
+
+    assert(as->ev_reptimeout != NULL);
+    event_release(as->ev_reptimeout);
+    as->ev_reptimeout = NULL;
+
+    as->state = s_processrep;
+    aclose(as->repfd);
+    return (A_CONTINUE);
+}
+
+/*
+ * After we have read in all of the rep data, we process it and send
+ * it out as a REP packet.
+ */
+static action_t
+s_processrep(as, action, pkt)
+    struct active_service *as;
+    action_t action;
+    pkt_t *pkt;
+{
+    char *tok, *repbuf;
+
+    /*
+     * Copy the rep lines into the outgoing packet.
+     *
+     * If this line is a CONNECT, translate it
+     * Format is "CONNECT <tag> <handle> <tag> <handle> etc...
+     * Example:
+     *
+     *  CONNECT DATA 4 MESG 5 INDEX 6
+     *
+     * The tags are arbitrary.  The handles are in the DATA_FD pool.
+     * We need to map these to security streams and pass them back
+     * to the amanda server.  If the handle is -1, then we don't map.
+     */
+    repbuf = stralloc(as->repbuf);
+    pkt_init(&as->rep_pkt, P_REP, "");
+    tok = strtok(repbuf, " ");
+    if (tok == NULL)
+       goto error;
+    if (strcmp(tok, "CONNECT") == 0) {
+       char *line, *nextbuf;
+
+       /* Save the entire line */
+       line = strtok(NULL, "\n");
+       /* Save the buf following the line */
+       nextbuf = strtok(NULL, "");
+
+       if (line == NULL || nextbuf == NULL)
+           goto error;
+
+       pkt_cat(&as->rep_pkt, "CONNECT");
+
+       /* loop over the id/handle pairs */
+       for (;;) {
+           /* id */
+           tok = strtok(line, " ");
+           line = NULL;        /* keep working from line */
+           if (tok == NULL)
+               break;
+           pkt_cat(&as->rep_pkt, " %s", tok);
+
+           /* handle */
+           tok = strtok(NULL, " \n");
+           if (tok == NULL)
+               goto error;
+           /* convert the handle into something the server can process */
+           pkt_cat(&as->rep_pkt, " %d", allocstream(as, atoi(tok)));
        }
-       amfree(noop_file);
-       amfree(s);
-       (void)lseek(rep_pipe[0], (off_t)0, SEEK_SET);
+       pkt_cat(&as->rep_pkt, "\n%s", nextbuf);
     } else {
-       if(strcmp(servp->name, "sendsize") == 0) {
-           if(strncmp(in_msg.dgram.cur,"OPTIONS ",8) == 0) {
-               g_option_t *g_options;
-               char *option_str, *p;
-
-               option_str = stralloc(in_msg.dgram.cur+8);
-               p = strchr(option_str,'\n');
-               if(p) *p = '\0';
-
-               g_options = parse_g_options(option_str, 0);
-               if(am_has_feature(g_options->features, fe_partial_estimate)) {
-                   send_partial_reply = 1;
-               }
-               amfree(option_str);
-           }
-       }
-       if(pipe(req_pipe) == -1 || pipe(rep_pipe) == -1)
-           error("pipe: %s", strerror(errno));
+error:
+       pkt_cat(&as->rep_pkt, "%s", as->repbuf);
+    }
 
-       /* spawn first child to handle the request */
+    /*
+     * We've setup our REP packet in as->rep_pkt.  Now move to the transmission
+     * state.
+     */
+    as->state = s_sendrep;
+    as->repretry = MAX_REP_RETRIES;
+    amfree(repbuf);
+    return (A_CONTINUE);
+}
 
-       switch(fork()) {
-       case -1: error("could not fork for %s: %s", cmd, strerror(errno));
+/*
+ * This is the state where we send the REP we just collected from our child.
+ */
+static action_t
+s_sendrep(as, action, pkt)
+    struct active_service *as;
+    action_t action;
+    pkt_t *pkt;
+{
 
-       default:                /* parent */
+    /*
+     * Transmit it and move to the ack state.
+     */
+    do_sendpkt(as->security_handle, &as->rep_pkt);
+    security_recvpkt(as->security_handle, protocol_recv, as, ACK_TIMEOUT);
+    as->state = s_ackwait;
+    return (A_PENDING);
+}
 
-           break; 
+/*
+ * This is the state in which we wait for the server to ACK the REP
+ * we just sent it.
+ */
+static action_t
+s_ackwait(as, action, pkt)
+    struct active_service *as;
+    action_t action;
+    pkt_t *pkt;
+{
+    struct datafd_handle *dh;
+    int npipes;
 
-       case 0:         /* child */
+    /*
+     * If we got a timeout, try again, but eventually give up.
+     */
+    if (action == A_TIMEOUT) {
+       if (--as->repretry > 0) {
+           as->state = s_sendrep;
+           return (A_CONTINUE);
+       }
+       dbprintf(("%s: timeout waiting for ACK for our REP\n",
+           debug_prefix_time(NULL)));
+       return (A_FINISH);
+    }
+#ifdef AMANDAD_DEBUG
+    dbprintf(("%s: received ACK, now opening streams\n",
+       debug_prefix_time(NULL)));
+#endif
 
-            aclose(req_pipe[1]); 
-            aclose(rep_pipe[0]);
+    assert(action == A_RECVPKT);
+    if (pkt->type != P_ACK)
+       return (A_SENDNAK);
 
-            dup2(req_pipe[0], 0);
-            dup2(rep_pipe[1], 1);
+    /*
+     * Got the ack, now open the pipes
+     */
+    for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
+       if (dh->netfd == NULL)
+           continue;
+       if (security_stream_accept(dh->netfd) < 0) {
+           dbprintf(("%s: stream %d accept failed: %s\n",
+               debug_prefix_time(NULL),
+               dh - &as->data[0], security_geterror(as->security_handle)));
+           security_stream_close(dh->netfd);
+           dh->netfd = NULL;
+       }
+       /* setup an event for reads from it */
+       dh->ev_handle = event_register(dh->fd, EV_READFD, process_netfd, dh);
+    }
 
-           /* modification by BIS@BBN 4/25/2003:
-            * close these file descriptors BEFORE doing pipe magic
-            * for transferring session key; inside transfer_session_key
-            * is a dup2 to move a pipe to KEY_PIPE, which collided
-            * with req_pipe[0]; when req_pipe[0] was closed after the
-            * call to transfer_session_key, then KEY_PIPE ended up
-            * being closed. */
-            aclose(req_pipe[0]);
-            aclose(rep_pipe[1]);
+    /*
+     * Pipes are open, so auth them.  Count them at the same time.
+     */
+    for (npipes = 0, dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
+       if (dh->netfd == NULL)
+           continue;
+       if (security_stream_auth(dh->netfd) < 0) {
+           security_stream_close(dh->netfd);
+           dh->netfd = NULL;
+           event_release(dh->ev_handle);
+           dh->ev_handle = NULL;
+       } else {
+           npipes++;
+       }
+    }
 
-#ifdef  KRB4_SECURITY
-           transfer_session_key();
+    /*
+     * If no pipes are open, then we're done.  Otherwise, just start running.
+     * The event handlers on all of the pipes will take it from here.
+     */
+#ifdef AMANDAD_DEBUG
+    dbprintf(("%s: at end of s_ackwait, npipes is %d\n",
+       debug_prefix_time(NULL), npipes));
 #endif
+    if (npipes == 0)
+       return (A_FINISH);
+    else {
+       security_close(as->security_handle);
+       as->security_handle = NULL;
+       return (A_PENDING);
+    }
+}
 
-           /* run service */
+/*
+ * Called when a repfd has received data
+ */
+static void
+repfd_recv(cookie)
+    void *cookie;
+{
+    struct active_service *as = cookie;
 
-           execle(cmd, cmd, NULL, safe_env());
-           error("could not exec %s: %s", cmd, strerror(errno));
-        }
-        amfree(cmd);
+    assert(as != NULL);
+    assert(as->ev_repfd != NULL);
 
-        aclose(req_pipe[0]);
-        aclose(rep_pipe[1]);
+    state_machine(as, A_RECVREP, NULL);
+}
 
-        /* spawn second child to handle writing the packet to the first child */
+/*
+ * Called when a repfd has timed out
+ */
+static void
+timeout_repfd(cookie)
+    void *cookie;
+{
+    struct active_service *as = cookie;
 
-        switch(fork()) {
-        case -1: error("could not fork for %s: %s", cmd, strerror(errno));
+    assert(as != NULL);
+    assert(as->ev_reptimeout != NULL);
 
-        default:               /* parent */
+    state_machine(as, A_TIMEOUT, NULL);
+}
 
-           break;
+/*
+ * Called when a handle has received data
+ */
+static void
+protocol_recv(cookie, pkt, status)
+    void *cookie;
+    pkt_t *pkt;
+    security_status_t status;
+{
+    struct active_service *as = cookie;
+
+    assert(as != NULL);
+
+    switch (status) {
+    case S_OK:
+       dbprintf(("%s: received %s pkt:\n<<<<<\n%s>>>>>\n",
+           debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->body));
+       state_machine(as, A_RECVPKT, pkt);
+       break;
+    case S_TIMEOUT:
+       dbprintf(("%s: timeout\n", debug_prefix_time(NULL)));
+       state_machine(as, A_TIMEOUT, NULL);
+       break;
+    case S_ERROR:
+       dbprintf(("%s: receive error: %s\n",
+           debug_prefix_time(NULL), security_geterror(as->security_handle)));
+       break;
+    }
+}
 
-        case 0:                /* child */
+/*
+ * This is a generic relay function that just reads data from one of
+ * the process's pipes and passes it up the equivalent security_stream_t
+ */
+static void
+process_netfd(cookie)
+    void *cookie;
+{
+    pkt_t nak;
+    struct datafd_handle *dh = cookie;
+    struct active_service *as = dh->as;
+    int n;
 
-            aclose(rep_pipe[0]);
-            reqlen = strlen(in_msg.dgram.cur);
-           if((rc = fullwrite(req_pipe[1], in_msg.dgram.cur, reqlen)) != reqlen) {
-               if(rc < 0) {
-                   error("write to child pipe: %s", strerror(errno));
-               } else {
-                   error("write to child pipe: %d instead of %d", rc, reqlen);
-               }
-           }
-            aclose(req_pipe[1]);
-           exit(0);
-        }
+    do {
+       n = read(dh->fd, as->databuf, sizeof(as->databuf));
+    } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 
-        aclose(req_pipe[1]);
+    /*
+     * Process has died.
+     */
+    if (n < 0) {
+       pkt_init(&nak, P_NAK, "ERROR data descriptor %d broken: %s\n",
+           dh->fd, strerror(errno));
+       goto sendnak;
+    }
+    /*
+     * Process has closed the pipe.  Just remove this event handler.
+     * If all pipes are closed, shut down this service.
+     */
+    if (n == 0) {
+       event_release(dh->ev_handle);
+       dh->ev_handle = NULL;
+       security_stream_close(dh->netfd);
+       dh->netfd = NULL;
+       for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
+           if (dh->netfd != NULL)
+               return;
+       }
+       service_delete(as);
+       return;
+    }
+    if (security_stream_write(dh->netfd, as->databuf, n) < 0) {
+       /* stream has croaked */
+       pkt_init(&nak, P_NAK, "ERROR write error on stream %d: %s\n",
+           security_stream_id(dh->netfd),
+           security_stream_geterror(dh->netfd));
+       goto sendnak;
     }
+    return;
+
+sendnak:
+    do_sendpkt(as->security_handle, &nak);
+    service_delete(as);
+}
+
+
+/*
+ * Convert a local stream handle (DATA_FD...) into something that
+ * can be sent to the amanda server.
+ *
+ * Returns a number that should be sent to the server in the REP packet.
+ */
+static int
+allocstream(as, handle)
+    struct active_service *as;
+    int handle;
+{
+    struct datafd_handle *dh;
+
+    /* if the handle is -1, then we don't bother */
+    if (handle < 0)
+       return (-1);
+
+    /* make sure the handle's kosher */
+    if (handle < DATA_FD_OFFSET || handle >= DATA_FD_OFFSET + DATA_FD_COUNT)
+       return (-1);
+
+    /* get a pointer into our handle array */
+    dh = &as->data[handle - DATA_FD_OFFSET];
+
+    /* make sure we're not already using the net handle */
+    if (dh->netfd != NULL)
+       return (-1);
 
-    setup_rep(&in_msg, &out_msg, 0);
-    if(send_partial_reply) {
-       setup_rep(&in_msg, &out_pmsg, 1);
+    /* allocate a stream from the security layer and return */
+    dh->netfd = security_stream_server(as->security_handle);
+    if (dh->netfd == NULL) {
+       dbprintf(("%s: couldn't open stream to server: %s\n",
+           debug_prefix_time(NULL), security_geterror(as->security_handle)));
+       return (-1);
     }
-#ifdef KRB4_SECURITY
-    add_mutual_authenticator(&out_msg.dgram);
-    add_mutual_authenticator(&out_pmsg.dgram);
-#endif
 
-    while(1) {
+    /*
+     * convert the stream into a numeric id that can be sent to the
+     * remote end.
+     */
+    return (security_stream_id(dh->netfd));
+}
+
+/*
+ * Create a new service instance
+ */
+static struct active_service *
+service_new(security_handle, cmd, arguments)
+    security_handle_t *security_handle;
+    const char *cmd, *arguments;
+{
+    int data[DATA_FD_COUNT + 2][2], i;
+    struct active_service *as;
+    pid_t pid;
 
-       FD_ZERO(&insock);
-       FD_SET(rep_pipe[0], &insock);
+    assert(security_handle != NULL);
+    assert(cmd != NULL);
+    assert(arguments != NULL);
 
-       if((servp->flags & IS_INTERNAL) != 0) {
-           n = 0;
-       } else {
-           FD_SET(0, &insock);
-           n = select(rep_pipe[0] + 1,
-                      (SELECT_ARG_TYPE *)&insock,
-                      NULL,
-                      NULL,
-                      NULL);
-       }
-       if(n < 0) {
-           error("select failed: %s", strerror(errno));
-       }
+    /* a plethora of pipes */
+    for (i = 0; i < DATA_FD_COUNT + 2; i++)
+       if (pipe(data[i]) < 0)
+           error("pipe: %s", strerror(errno));
 
-       if(FD_ISSET(rep_pipe[0], &insock)) {
-           if(dglen >= MAX_DGRAM) {
-               error("more than %d bytes received from child", MAX_DGRAM);
-           }
-           rc = read(rep_pipe[0], out_msg.dgram.cur+dglen, MAX_DGRAM-dglen);
-           if(rc <= 0) {
-               if (rc < 0) {
-                   error("reading response pipe: %s", strerror(errno));
-               }
-               break;
-           }
-           else {
-               if(send_partial_reply) {
-                   strncpy(out_pmsg.dgram.cur+dglen, out_msg.dgram.cur+dglen, rc);
-                   out_pmsg.dgram.len += rc;
-                   out_pmsg.dgram.data[out_pmsg.dgram.len] = '\0';
-                   dbprintf(("%s: sending PREP packet:\n----\n%s----\n\n",
-                             debug_prefix_time(NULL), out_pmsg.dgram.data));
-                   dgram_send_addr(in_msg.peer, &out_pmsg.dgram);
-               }
-               dglen += rc;
+    switch(pid = fork()) {
+    case -1:
+       error("could not fork service %s: %s", cmd, strerror(errno));
+    default:
+       /*
+        * The parent.  Close the far ends of our pipes and return.
+        */
+       as = alloc(sizeof(*as));
+       as->cmd = stralloc(cmd);
+       as->arguments = stralloc(arguments);
+       as->security_handle = security_handle;
+       as->state = NULL;
+       as->pid = pid;
+       as->send_partial_reply = 0;
+       if(strcmp(cmd+(strlen(cmd)-8), "sendsize") == 0) {
+           g_option_t *g_options;
+           char *option_str, *p;
+
+           option_str = stralloc(as->arguments+8);
+           p = strchr(option_str,'\n');
+           if(p) *p = '\0';
+
+           g_options = parse_g_options(option_str, 1);
+           if(am_has_feature(g_options->features, fe_partial_estimate)) {
+               as->send_partial_reply = 1;
            }
+           amfree(g_options);
+           amfree(option_str);
        }
-       if(!FD_ISSET(0,&insock))
-           continue;
 
-       if((n = dgram_recv(&dup_msg.dgram, RECV_TIMEOUT, &dup_msg.peer)) <= 0) {
-           char *s;
+       /* write to the request pipe */
+       aclose(data[0][0]);
+       as->reqfd = data[0][1];
 
-           if (n == 0) {
-               s = "timeout";
-           } else {
-               s = strerror(errno);
-           }
-           error("error receiving message: %s", s);
+       /*
+        * read from the reply pipe
+        */
+       as->repfd = data[1][0];
+       aclose(data[1][1]);
+       as->ev_repfd = NULL;
+       as->repbufsize = 0;
+       as->repretry = 0;
+
+       /*
+        * read from the rest of the general-use pipes
+        * (netfds are opened as the client requests them)
+        */
+       for (i = 0; i < DATA_FD_COUNT; i++) {
+           aclose(data[i + 2][1]);
+           as->data[i].fd = data[i + 2][0];
+           as->data[i].ev_handle = NULL;
+           as->data[i].netfd = NULL;
+           as->data[i].as = as;
        }
 
-       /* 
-        * Under normal conditions, the master will resend the REQ packet
-        * to be sure we are still alive.  It expects an ACK back right away.
-        *
-        * XXX- Arguably we should parse and security check the new packet, 
-        * only sending an ACK if it passes and the request is identical to
-        * the original one.  However, that's too much work for now. :-) 
-        *
-        * It should suffice to ACK whenever the sender is identical.
+       /* add it to the service queue */
+       /* increment the active service count */
+       TAILQ_INSERT_TAIL(&serviceq.tailq, as, tq);
+       serviceq.qlength++;
+
+       return (as);
+    case 0:
+       /*
+        * The child.  Put our pipes in their advertised locations
+        * and start up.
         */
-       dbprintf(("%s: got packet:\n----\n%s----\n\n",
-                 debug_prefix_time(NULL), dup_msg.dgram.data));
-       parse_pkt_header(&dup_msg);
-       if(dup_msg.peer.sin_addr.s_addr == in_msg.peer.sin_addr.s_addr &&
-          dup_msg.peer.sin_port == in_msg.peer.sin_port) {
-           if(dup_msg.type == P_REQ) {
-               dbprintf(("%s: received dup P_REQ packet, ACKing it\n",
-                         debug_prefix_time(NULL)));
-               sendack(&in_msg, &rej_msg);
-           }
-           else {
-               dbprintf(("%s: it is not a P_REQ, ignoring it\n",
-                         debug_prefix_time(NULL)));
-           }
+#ifdef FORCE_USERID
+       seteuid((uid_t)0);
+       setuid(client_uid);
+#endif
+
+       /*
+        * The data stream is stdin in the new process
+        */
+        if (dup2(data[0][0], 0) < 0) {
+           error("dup %d to %d failed: %s\n", data[0][0], 0,
+               strerror(errno));
+       }
+       aclose(data[0][0]);
+       aclose(data[0][1]);
+
+       /*
+        * The reply stream is stdout
+        */
+        if (dup2(data[1][1], 1) < 0) {
+           error("dup %d to %d failed: %s\n", data[1][1], 1,
+               strerror(errno));
        }
-       else {
-           dbprintf(("%s: received other packet, NAKing it\n",
-                     debug_prefix_time(NULL)));
-           dbprintf(("  addr: peer %s dup %s, port: peer %d dup %d\n",
-                     inet_ntoa(in_msg.peer.sin_addr),
-                     inet_ntoa(dup_msg.peer.sin_addr),
-                     (int)ntohs(in_msg.peer.sin_port),
-                     (int)ntohs(dup_msg.peer.sin_port)));
-           /* XXX dup_msg filled in? */
-           sendnak(&dup_msg, &rej_msg, "amandad busy");
+        aclose(data[1][0]);
+        aclose(data[1][1]);
+
+       /*
+        * The rest start at the offset defined in amandad.h, and continue
+        * through the internal defined.
+        */
+       for (i = 0; i < DATA_FD_COUNT; i++) {
+           if (dup2(data[i + 2][1], i + DATA_FD_OFFSET) < 0) {
+               error("dup %d to %d failed: %s\n", data[i + 2][1],
+                   i + DATA_FD_OFFSET, strerror(errno));
+           }
+           aclose(data[i + 2][0]);
+           aclose(data[i + 2][1]);
        }
 
+       execle(cmd, cmd, NULL, safe_env());
+       error("could not exec service %s: %s", cmd, strerror(errno));
     }
+    /* NOTREACHED */
+    return NULL;
+}
 
-    /* XXX reap child?  log if non-zero status?  don't respond if non zero? */
-    /* setup header for out_msg */
+/*
+ * Unallocate a service instance
+ */
+static void
+service_delete(as)
+    struct active_service *as;
+{
+    int i;
+    struct datafd_handle *dh;
 
-    out_msg.dgram.len += dglen;
-    out_msg.dgram.data[out_msg.dgram.len] = '\0';
-    aclose(rep_pipe[0]);
+#ifdef AMANDAD_DEBUG
+       dbprintf(("%s: closing service: %s\n",
+           debug_prefix_time(NULL), (as->cmd)?as->cmd:"??UNKONWN??"));
+#endif
 
-send_response:
+    assert(as != NULL);
 
-    retry_count = 0;
+    assert(as->cmd != NULL);
+    amfree(as->cmd);
 
-    while(retry_count < max_retry_count) {
-       if(!retry_count)
-           dbprintf(("%s: sending REP packet:\n----\n%s----\n\n",
-                     debug_prefix_time(NULL), out_msg.dgram.data));
-       dgram_send_addr(in_msg.peer, &out_msg.dgram);
-       if((n = dgram_recv(&dup_msg.dgram, ack_timeout, &dup_msg.peer)) <= 0) {
-           char *s;
+    assert(as->arguments != NULL);
+    amfree(as->arguments);
 
-           if (n == 0) {
-               s = "timeout";
-           } else {
-               s = strerror(errno);
-           }
+    if (as->reqfd != -1)
+       aclose(as->reqfd);
+    if (as->repfd != -1)
+       aclose(as->repfd);
 
-           /* timed out or error, try again */
-           retry_count++;
+    if (as->ev_repfd != NULL)
+       event_release(as->ev_repfd);
+    if (as->ev_reptimeout != NULL)
+       event_release(as->ev_reptimeout);
 
-           dbprintf(("%s: waiting for ack: %s", debug_prefix_time(NULL), s));
-           if(retry_count < max_retry_count) 
-               dbprintf((", retrying\n"));
-           else 
-               dbprintf((", giving up!\n"));
+    for (i = 0; i < DATA_FD_COUNT; i++) {
+       dh = &as->data[i];
 
-           continue;
-       }
-       dbprintf(("%s: got packet:\n----\n%s----\n\n",
-                 debug_prefix_time(NULL), dup_msg.dgram.data));
-       parse_pkt_header(&dup_msg);
-
-       
-       if(dup_msg.peer.sin_addr.s_addr == in_msg.peer.sin_addr.s_addr &&
-          dup_msg.peer.sin_port == in_msg.peer.sin_port) {
-           if(dup_msg.type == P_ACK)
-               break;
-           else
-               dbprintf(("%s: it is not an ack\n", debug_prefix_time(NULL)));
-       }
-       else {
-           dbprintf(("%s: weird, it is not a proper ack\n",
-                     debug_prefix_time(NULL)));
-           dbprintf(("  addr: peer %s dup %s, port: peer %d dup %d\n",
-                     inet_ntoa(in_msg.peer.sin_addr),
-                     inet_ntoa(dup_msg.peer.sin_addr),
-                     (int)ntohs(in_msg.peer.sin_port),
-                     (int)ntohs(dup_msg.peer.sin_port)));
-       }               
-    }
-    /* XXX log if retry count exceeded */
-
-    amfree(cmd);
-    amfree(noop_file);
-    amfree(our_feature_string);
-    am_release_feature_set(our_features);
-    our_features = NULL;
-    malloc_size_2 = malloc_inuse(&malloc_hist_2);
-
-    if(malloc_size_1 != malloc_size_2) {
-#if defined(USE_DBMALLOC)
-       malloc_list(dbfd(), malloc_hist_1, malloc_hist_2);
-#endif
+       aclose(dh->fd);
+
+       if (dh->netfd != NULL)
+           security_stream_close(dh->netfd);
+
+       if (dh->ev_handle != NULL)
+           event_release(dh->ev_handle);
     }
 
-    dbclose();
-    return 0;
-}
+    if (as->security_handle != NULL)
+       security_close(as->security_handle);
 
+    assert(as->pid > 0);
+    kill(as->pid, SIGTERM);
+    waitpid(as->pid, NULL, WNOHANG);
 
-/* -------- */
+    TAILQ_REMOVE(&serviceq.tailq, as, tq);
+    assert(serviceq.qlength > 0);
+    serviceq.qlength--;
 
-void sendack(hdr, msg)
-pkt_t *hdr;
-pkt_t *msg;
-{
-    /* XXX this isn't very safe either: handle could be bogus */
-    ap_snprintf(msg->dgram.data, sizeof(msg->dgram.data),
-               "Amanda %d.%d ACK HANDLE %s SEQ %d\n",
-               VERSION_MAJOR, VERSION_MINOR,
-               hdr->handle ? hdr->handle : "",
-               hdr->sequence);
-    msg->dgram.len = strlen(msg->dgram.data);
-    dbprintf(("%s: sending ack:\n----\n%s----\n\n",
-             debug_prefix_time(NULL), msg->dgram.data));
-    dgram_send_addr(hdr->peer, &msg->dgram);
+    amfree(as);
 }
 
-void sendnak(hdr, msg, str)
-pkt_t *hdr;
-pkt_t *msg;
-char *str;
+/*
+ * Like 'fullwrite', but does the work in a child process so pipelines
+ * do not hang.
+ */
+static int
+writebuf(as, bufp, size)
+    struct active_service *as;
+    const void *bufp;
+    size_t size;
 {
-    /* XXX this isn't very safe either: handle could be bogus */
-    ap_snprintf(msg->dgram.data, sizeof(msg->dgram.data),
-               "Amanda %d.%d NAK HANDLE %s SEQ %d\nERROR %s\n",
-               VERSION_MAJOR, VERSION_MINOR,
-               hdr->handle ? hdr->handle : "",
-               hdr->sequence, str ? str : "UNKNOWN");
-
-    msg->dgram.len = strlen(msg->dgram.data);
-    dbprintf(("%s: sending nack:\n----\n%s----\n\n",
-             debug_prefix_time(NULL), msg->dgram.data));
-    dgram_send_addr(hdr->peer, &msg->dgram);
-}
+    int pid;
 
-void setup_rep(hdr, msg, partial_rep)
-pkt_t *hdr;
-pkt_t *msg;
-int partial_rep;
-{
-    /* XXX this isn't very safe either: handle could be bogus */
-    ap_snprintf(msg->dgram.data, sizeof(msg->dgram.data),
-               "Amanda %d.%d %s HANDLE %s SEQ %d\n",
-               VERSION_MAJOR, VERSION_MINOR,
-               partial_rep == 0 ? "REP" : "PREP", 
-               hdr->handle ? hdr->handle : "",
-               hdr->sequence);
+    switch (pid=fork()) {
+    case -1:
+       return -1;
 
-    msg->dgram.len = strlen(msg->dgram.data);
-    msg->dgram.cur = msg->dgram.data + msg->dgram.len;
+    default:
+       waitpid(pid, NULL, WNOHANG);
+       return 0;                       /* this is the parent */
 
+    case 0:
+       break;                          /* this is the child */
+    }
+    aclose (as->repfd);                        /* make sure we are not a reader */
+    exit (fullwrite(as->reqfd, bufp, size) != size);
 }
 
-/* -------- */
+static int
+do_sendpkt(handle, pkt)
+    security_handle_t *handle;
+    pkt_t *pkt;
+{
+    dbprintf(("%s: sending %s pkt:\n<<<<<\n%s>>>>>\n",
+       debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->body));
+    return security_sendpkt(handle, pkt);
+}
+
+#ifdef AMANDAD_DEBUG
+/*
+ * Convert a state into a string
+ */
+static const char *
+state2str(state)
+    state_t state;
+{
+    static const struct {
+       state_t state;
+       const char str[13];
+    } states[] = {
+#define        X(state)        { state, stringize(state) }
+       X(s_sendack),
+       X(s_repwait),
+       X(s_processrep),
+       X(s_sendrep),
+       X(s_ackwait),
+#undef X
+    };
+    int i;
+
+    for (i = 0; i < sizeof(states) / sizeof(states[0]); i++)
+       if (state == states[i].state)
+           return (states[i].str);
+    return ("INVALID STATE");
+}
 
-char *strlower(str)
-char *str;
+/*
+ * Convert an action into a string
+ */
+static const char *
+action2str(action)
+    action_t action;
 {
-    char *s;
-    for(s=str; *s; s++)
-       if(isupper((int)*s)) *s = tolower(*s);
-    return str;
+    static const struct {
+       action_t action;
+       const char str[12];
+    } actions[] = {
+#define        X(action)       { action, stringize(action) }
+       X(A_START),
+       X(A_RECVPKT),
+       X(A_RECVREP),
+       X(A_PENDING),
+       X(A_FINISH),
+       X(A_CONTINUE),
+       X(A_SENDNAK),
+       X(A_TIMEOUT),
+#undef X
+    };
+    int i;
+
+    for (i = 0; i < sizeof(actions) / sizeof(actions[0]); i++)
+       if (action == actions[i].action)
+           return (actions[i].str);
+    return ("UNKNOWN ACTION");
 }
+#endif /* AMANDAD_DEBUG */
diff --git a/client-src/amandad.h b/client-src/amandad.h
new file mode 100644 (file)
index 0000000..054f6bd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: amandad.h,v 1.2 1999/04/16 05:12:39 kashmir Exp $
+ */
+#ifndef        AMANDAD_H
+#define        AMANDAD_H
+
+/*
+ * General-use pipes inherited by sendbackup that are connected to the
+ * data, mesg, index, etc connections on the server.  amandad sets these
+ * up before calling sendbackup, and will relay data sent on them
+ * back to the server.
+ */
+#define        DATA_FD_COUNT   3               /* number of general-use pipes */
+#define        DATA_FD_OFFSET  50              /* fd at which they start */
+
+#endif /* AMANDAD_H */
index c8f019f0a2f7339324ec811a859757925f8272ed..3d055bbc162088294dc72ba4df9426b052734779 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amandates.c,v 1.15.8.1 2003/10/22 17:43:33 martinea Exp $
+ * $Id: amandates.c,v 1.16 2003/10/22 17:43:20 martinea Exp $
  *
  * manage amandates file, that mimics /var/lib/dumpdates, but stores
  * GNUTAR dates
diff --git a/client-src/amqde.c b/client-src/amqde.c
deleted file mode 100644 (file)
index a0ec139..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1999 University of Maryland at College Park
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors: the Amanda Development Team.  Its members are listed in a
- * file named AUTHORS, in the root directory of this distribution.
- */
-/*
- * $Id: amqde.c,v 1.1.2.1.2.1 2004/08/05 11:35:35 martinea Exp $
- *
- * the central header file included by all amanda sources
- */
-
-#include "amanda.h"
-
-/*
- * amanda's version of things.
- */
-#define emalloc alloc
-#define estrdup stralloc
-
-#ifdef USE_STRHASH
-hash_table *parse_exclude_path(char *, char *);
-int should_exclude(hash_table * hash, char *path);
-
-#endif
-
-typedef struct __dirtrax {
-       char *dirname;
-       struct __dirtrax *next;
-}         dirtrax_t;
-
-typedef struct __diretrax_track_ll {
-       dirtrax_t *first, *last;
-}                   dirtrax_ll_t;
-
-int
-main(argc, argv)
-       int argc;
-       char *argv[];
-{
-       extern char *optarg;
-       extern int optind;
-
-       int ch;
-       char buf[8192];
-       struct stat top, st;
-       char *path;
-       time_t since = 0;
-       DIR *d;
-       struct dirent *de;
-#ifdef HAVE_UNSIGNED_LONG_LONG
-       unsigned long long total = 0;
-#else
-       unsigned long total = 0;
-#endif
-       dirtrax_ll_t ll;
-       dirtrax_t *trax = NULL, *new, *c;
-       char *exclude_path = NULL;
-       int havesince = 0;
-
-#ifdef USE_STRHASH
-       hash_table *hash = NULL;
-
-#endif
-
-       while ((ch = getopt(argc, argv, "s:x:")) != EOF) {
-               switch (ch) {
-               case 's':
-                       since = atoi(optarg);
-                       havesince = 1;
-                       break;
-               case 'x':
-                       exit(0);
-                       exclude_path = (optarg);
-                       break;
-               default:
-                       fprintf(stderr, "unknown argument \'%c\'", ch);
-                       exit(1);
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       if (argc == 0) {
-               fprintf(stderr, "must specify a path to dump\n");
-               exit(1);
-       }
-       if (!havesince) {
-               fprintf(stderr, "must specify -s\n");
-               exit(1);
-       }
-       path = argv[0];
-
-#ifdef USE_STRHASH
-       if (exclude_path)
-               hash = parse_exclude_path(path, exclude_path);
-#endif
-
-       if (chdir(path) != 0) {
-               fprintf(stderr, "could not chdir to %s\n", path);
-               exit(1);
-       }
-       if (lstat(".", &top) != 0) {
-               fprintf(stderr, "could not stat %s\n", path);
-               exit(1);
-       }
-       trax = emalloc(sizeof(*trax));
-       trax->dirname = estrdup(".");
-       trax->next = NULL;
-
-       ll.first = ll.last = trax;
-
-       for (new = ll.first; new; new = ll.first) {
-               if (!(d = opendir(new->dirname))) {
-                       goto forcleanup;        /* basically continue; */
-               }
-               /*
-                * skip directories if we cross a device
-                */
-               if (lstat(new->dirname, &st) != 0)
-                       goto forwclosedircleanup;
-               if (top.st_dev != st.st_dev || top.st_rdev != st.st_rdev)
-                       goto forwclosedircleanup;
-
-               while ((de = readdir(d))) {
-                       total += 505;
-                       if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
-                               continue;
-
-                       ap_snprintf(buf, sizeof(buf) - 1, "%s/%s", new->dirname, de->d_name);
-
-#ifdef USE_STRHASH
-                       if (should_exclude(hash, buf))
-                               continue;
-#endif
-
-                       if (lstat(buf, &st) != 0)
-                               continue;
-
-                       if (S_ISDIR(st.st_mode)) {
-                               c = emalloc(sizeof(*c));
-                               c->dirname = estrdup(buf);
-                               c->next = NULL;
-                               ll.last->next = c;
-                               ll.last = c;
-                       } else {
-                               if (st.st_mtime < since && st.st_ctime < since)
-                                       continue;
-                               if ((st.st_blocks * 512) < st.st_size)
-                                       total += (st.st_blocks * 512);
-                               else
-                                       total += st.st_size;
-                               /*
-                                * add in some overhead, these are estimates
-                                * after all
-                                */
-                               total += 505;
-                       }
-               }
-forwclosedircleanup:
-               closedir(d);
-forcleanup:
-               ll.first = new->next;
-               free(new->dirname);
-               free(new);
-       }
-
-       /*
-        * This is dumped out in k so upstream utilies can handle it without
-        * having to handle unsigned long long.  The theory is that if you
-        * need to use these estimates, then you proably have a system that
-        * uses long long.
-        */
-
-#ifdef HAVE_UNSIGNED_LONG_LONG
-       fprintf(stderr, "amqde estimate: %llu kb\n", total/1024);
-#else
-       fprintf(stderr, "amqde estimate: %lu kb\n", total/1024);
-#endif
-       chdir("/");
-
-       return (0);
-}
-
-/*
- * at the moment, we don't actually parse the include file because it means
- * implementing globbing, which is a pain in the arse.
- *
- * This is quick and dirty, after all.
- */
-#ifdef USE_STRHASH
-hash_table *
-parse_exclude_path(rootpath, infile)
-       char *rootpath;
-       char *infile;
-{
-       FILE *f;
-       char buf[4096];
-       hash_table *hash;
-
-       return (NULL);
-}
-
-int
-should_exclude(hash, path)
-       hash_table *hash;
-       char *path;
-{
-       return (0);
-}
-
-#endif
index 5ca13fac43c094136d0aefc89eb24813bfbf43ed..d795f616d9df937397b75ba3b0515aa270a108ba 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: calcsize.c,v 1.24.2.3.6.1.2.5 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: calcsize.c,v 1.36 2006/03/09 16:51:41 martinea Exp $
  *
  * traverse directory tree to get backup size estimates
  */
@@ -113,6 +113,9 @@ char **argv;
 
     set_pname("calcsize");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     if (argc < 2) {
        fprintf(stderr,"Usage: %s file[s]\n",argv[0]);
        return 1;
@@ -295,8 +298,10 @@ char **argv;
  * =========================================================================
  */
 
-#ifndef HAVE_BASENAME
-char *basename(file)
+#if !defined(HAVE_BASENAME) && defined(BUILTIN_EXCLUDE_SUPPORT)
+static char *basename P((char *));
+
+static char *basename(file)
 char *file;
 {
     char *cp;
@@ -325,9 +330,11 @@ char *include;
     int parent_len;
     int has_exclude = !is_empty_sl(exclude_sl) && use_gtar_excl;
 
+    if(parent_dir == NULL || include == NULL) return;
+
     char *aparent = vstralloc(parent_dir, "/", include, NULL);
 
-    if(parent_dir && stat(parent_dir, &finfo) != -1)
+    if(stat(parent_dir, &finfo) != -1)
        parent_dev = finfo.st_dev;
 
     parent_len = strlen(parent_dir);
@@ -365,9 +372,8 @@ char *include;
                continue;
            }
 
-           if(finfo.st_dev != parent_dev) {
+           if(finfo.st_dev != parent_dev)
                continue;
-           }
 
 #ifdef S_IFLNK
            is_symlink = ((finfo.st_mode & S_IFMT) == S_IFLNK);
index fce4c7e0eeaf8f90f457c0dc3227a713f557d264..f766845f8a2e2001e22a4d7deddedc47ddf8738c 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: client_util.c,v 1.1.2.27.2.1 2005/10/11 14:50:00 martinea Exp $
+ * $Id: client_util.c,v 1.32 2006/03/09 16:51:41 martinea Exp $
  *
  */
 
@@ -64,7 +64,7 @@ int n;
     if(n == 0)
        number[0] = '\0';
     else
-       ap_snprintf(number, sizeof(number), "%03d", n - 1);
+       snprintf(number, sizeof(number), "%03d", n - 1);
        
     filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".",
                         exin, NULL);
@@ -212,6 +212,7 @@ int verbose;
                      debug_prefix(NULL), device));
                if(verbose)
                    printf("ERROR [Can't open disk '%s']\n", device);
+               amfree(regex);
                return 0;
            }
            else {
@@ -226,6 +227,7 @@ int verbose;
                }
                closedir(d);
            }
+           amfree(regex);
        }
     }
     return nb_exp;
@@ -274,8 +276,7 @@ int verbose;
                    else {
                        dbprintf(("%s: Can't open exclude file '%s': %s\n",
                                  debug_prefix(NULL),
-                                 exclname,
-                                 strerror(errno)));
+                                 exclname, strerror(errno)));
                        if(verbose && (options->exclude_optional == 0 ||
                                       errno != ENOENT))
                            printf("ERROR [Can't open exclude file '%s': %s]\n",
@@ -289,8 +290,7 @@ int verbose;
        else {
            dbprintf(("%s: Can't create exclude file '%s': %s\n",
                      debug_prefix(NULL),
-                     filename,
-                     strerror(errno)));
+                     filename, strerror(errno)));
            if(verbose)
                printf("ERROR [Can't create exclude file '%s': %s]\n", filename,
                        strerror(errno));
@@ -347,10 +347,9 @@ int verbose;
                    else {
                        dbprintf(("%s: Can't open include file '%s': %s\n",
                                  debug_prefix(NULL),
-                                 inclname,
-                                 strerror(errno)));
+                                 inclname, strerror(errno)));
                        if(verbose && (options->include_optional == 0 ||
-                                       errno != ENOENT))
+                                      errno != ENOENT))
                            printf("ERROR [Can't open include file '%s': %s]\n",
                                   inclname, strerror(errno));
                   }
@@ -362,8 +361,7 @@ int verbose;
        else {
            dbprintf(("%s: Can't create include file '%s': %s\n",
                      debug_prefix(NULL),
-                     filename,
-                     strerror(errno)));
+                     filename, strerror(errno)));
            if(verbose)
                printf("ERROR [Can't create include file '%s': %s]\n", filename,
                        strerror(errno));
@@ -385,13 +383,16 @@ option_t *options;
 {
     options->str = NULL;
     options->compress = NO_COMPR;
+    options->srvcompprog = NULL;
+    options->clntcompprog = NULL;
+    options->encrypt = ENCRYPT_NONE;
+    options->srv_encrypt = NULL;
+    options->clnt_encrypt = NULL;
+    options->srv_decrypt_opt = NULL;
+    options->clnt_decrypt_opt = NULL;
     options->no_record = 0;
-    options->bsd_auth = 0;
     options->createindex = 0;
-#ifdef KRB4_SECURITY
-    options->krb4_auth = 0;
-    options->kencrypt = 0;
-#endif
+    options->auth = NULL;
     options->exclude_file = NULL;
     options->exclude_list = NULL;
     options->include_file = NULL;
@@ -420,171 +421,189 @@ int verbose;
 
     while (tok != NULL) {
        if(am_has_feature(fs, fe_options_auth)
-          && strncmp(tok, "auth=", 5) == 0) {
-           if(options->bsd_auth
-#ifdef KRB4_SECURITY
-              + options->krb4_auth
-#endif
-              > 0) {
-               dbprintf(("%s: multiple auth option\n", 
-                         debug_prefix(NULL)));
+          && BSTRNCMP(tok,"auth=") == 0) {
+           if(options->auth != NULL) {
+               dbprintf(("%s: multiple auth option \"%s\"\n",
+                         debug_prefix(NULL), tok+5));
                if(verbose) {
-                   printf("ERROR [multiple auth option]\n");
+                   printf("ERROR [multiple auth option \"%s\"\n", tok+5);
                }
            }
-           if(strcasecmp(tok + 5, "bsd") == 0) {
-               options->bsd_auth = 1;
-           }
-#ifdef KRB4_SECURITY
-           else if(strcasecmp(tok + 5, "krb4") == 0) {
-               options->krb4_auth = 1;
+           options->auth = stralloc(&tok[5]);
+       }
+       else if(am_has_feature(fs, fe_options_bsd_auth)
+          && BSTRNCMP(tok, "bsd-auth") == 0) {
+           if(options->auth != NULL) {
+               dbprintf(("%s: multiple auth option \n",
+                         debug_prefix(NULL)));
+               if(verbose) {
+                   printf("ERROR [multiple auth option \n");
+               }
            }
-#endif
-           else {
-               dbprintf(("%s: unknown auth= value \"%s\"\n",
-                         debug_prefix(NULL), tok + 5));
+           options->auth = stralloc("bsd");
+       }
+       else if(am_has_feature(fs, fe_options_krb4_auth)
+          && BSTRNCMP(tok, "krb4-auth") == 0) {
+           if(options->auth != NULL) {
+               dbprintf(("%s: multiple auth option \n",
+                         debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [unknown auth= value \"%s\"]\n", tok + 5);
+                   printf("ERROR [multiple auth option \n");
                }
            }
+           options->auth = stralloc("krb4");
        }
-       else if(strcmp(tok, "compress-fast") == 0) {
+       else if(BSTRNCMP(tok, "compress-fast") == 0) {
            if(options->compress != NO_COMPR) {
-               dbprintf(("%s: multiple compress option\n", 
+               dbprintf(("%s: multiple compress option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple compress option]\n");
+                   printf("ERROR [multiple compress option \n");
                }
            }
            options->compress = COMPR_FAST;
        }
-       else if(strcmp(tok, "compress-best") == 0) {
+       else if(BSTRNCMP(tok, "compress-best") == 0) {
            if(options->compress != NO_COMPR) {
-               dbprintf(("%s: multiple compress option\n", 
+               dbprintf(("%s: multiple compress option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple compress option]\n");
+                   printf("ERROR [multiple compress option \n");
                }
            }
            options->compress = COMPR_BEST;
        }
-       else if(strcmp(tok, "srvcomp-fast") == 0) {
+       else if(BSTRNCMP(tok, "srvcomp-fast") == 0) {
            if(options->compress != NO_COMPR) {
-               dbprintf(("%s: multiple compress option\n", 
+               dbprintf(("%s: multiple compress option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple compress option]\n");
+                   printf("ERROR [multiple compress option \n");
                }
            }
            options->compress = COMPR_SERVER_FAST;
        }
-       else if(strcmp(tok, "srvcomp-best") == 0) {
+       else if(BSTRNCMP(tok, "srvcomp-best") == 0) {
            if(options->compress != NO_COMPR) {
-               dbprintf(("%s: multiple compress option\n", 
+               dbprintf(("%s: multiple compress option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple compress option]\n");
+                   printf("ERROR [multiple compress option \n");
                }
            }
            options->compress = COMPR_SERVER_BEST;
        }
-       else if(strcmp(tok, "no-record") == 0) {
-           if(options->no_record != 0) {
-               dbprintf(("%s: multiple no-record option\n", 
+       else if(BSTRNCMP(tok, "srvcomp-cust=") == 0) {
+           if(options->compress != NO_COMPR) {
+               dbprintf(("%s: multiple compress option\n", 
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple no-record option]\n");
+                   printf("ERROR [multiple compress option]\n");
                }
            }
-           options->no_record = 1;
+           options->srvcompprog = stralloc(tok + sizeof("srvcomp-cust=") -1);
+           options->compress = COMPR_SERVER_CUST;
        }
-       else if(strcmp(tok, "bsd-auth") == 0) {
-           if(options->bsd_auth
-#ifdef KRB4_SECURITY
-              + options->krb4_auth
-#endif
-              > 0) {
-               dbprintf(("%s: multiple auth option\n", 
+       else if(BSTRNCMP(tok, "comp-cust=") == 0) {
+           if(options->compress != NO_COMPR) {
+               dbprintf(("%s: multiple compress option\n", 
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple auth option]\n");
+                   printf("ERROR [multiple compress option]\n");
                }
            }
-           options->bsd_auth = 1;
-       }
-       else if(strcmp(tok, "index") == 0) {
-           if(options->createindex != 0) {
-               dbprintf(("%s: multiple index option\n", 
+           options->clntcompprog = stralloc(tok + sizeof("comp-cust=") -1);
+           options->compress = COMPR_CUST;
+           /* parse encryption options */
+       } 
+       else if(BSTRNCMP(tok, "encrypt-serv-cust=") == 0) {
+           if(options->encrypt != ENCRYPT_NONE) {
+               dbprintf(("%s: multiple encrypt option\n", 
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple index option]\n");
+                   printf("ERROR [multiple encrypt option]\n");
                }
            }
-           options->createindex = 1;
+           options->srv_encrypt = stralloc(tok + sizeof("encrypt-serv-cust=") -1);
+           options->encrypt = ENCRYPT_SERV_CUST;
+       } 
+       else if(BSTRNCMP(tok, "encrypt-cust=") == 0) {
+           if(options->encrypt != ENCRYPT_NONE) {
+               dbprintf(("%s: multiple encrypt option\n", 
+                         debug_prefix(NULL)));
+               if(verbose) {
+                   printf("ERROR [multiple encrypt option]\n");
+               }
+           }
+           options->clnt_encrypt= stralloc(tok + sizeof("encrypt-cust=") -1);
+           options->encrypt = ENCRYPT_CUST;
+       } 
+       else if(BSTRNCMP(tok, "server-decrypt-option=") == 0) {
+         options->srv_decrypt_opt = stralloc(tok + sizeof("server-decrypt-option=") -1);
        }
-#ifdef KRB4_SECURITY
-       else if(strcmp(tok, "krb4-auth") == 0) {
-           if(options->bsd_auth + options->krb4_auth > 0) {
-               dbprintf(("%s: multiple auth option\n", 
+       else if(BSTRNCMP(tok, "client-decrypt-option=") == 0) {
+         options->clnt_decrypt_opt = stralloc(tok + sizeof("client-decrypt-option=") -1);
+       }
+       else if(BSTRNCMP(tok, "no-record") == 0) {
+           if(options->no_record != 0) {
+               dbprintf(("%s: multiple no-record option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple auth option]\n");
+                   printf("ERROR [multiple no-record option \n");
                }
            }
-           options->krb4_auth = 1;
+           options->no_record = 1;
        }
-       else if(strcmp(tok, "kencrypt") == 0) {
-           if(options->kencrypt != 0) {
-               dbprintf(("%s: multiple kencrypt option\n", 
+       else if(BSTRNCMP(tok, "index") == 0) {
+           if(options->createindex != 0) {
+               dbprintf(("%s: multiple index option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple kencrypt option]\n");
+                   printf("ERROR [multiple index option \n");
                }
            }
-           options->kencrypt = 1;
+           options->createindex = 1;
        }
-#endif
-       else if(strcmp(tok, "exclude-optional") == 0) {
+       else if(BSTRNCMP(tok, "exclude-optional") == 0) {
            if(options->exclude_optional != 0) {
-               dbprintf(("%s: multiple exclude-optional option\n", 
+               dbprintf(("%s: multiple exclude-optional option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple exclude-optional option]\n");
+                   printf("ERROR [multiple exclude-optional option \n");
                }
            }
            options->exclude_optional = 1;
        }
        else if(strcmp(tok, "include-optional") == 0) {
            if(options->include_optional != 0) {
-               dbprintf(("%s: multiple include-optional option\n", 
+               dbprintf(("%s: multiple include-optional option \n",
                          debug_prefix(NULL)));
                if(verbose) {
-                   printf("ERROR [multiple include-optional option]\n");
+                   printf("ERROR [multiple include-optional option \n");
                }
            }
            options->include_optional = 1;
        }
-       else if(strncmp(tok,"exclude-file=", 13) == 0) {
+       else if(BSTRNCMP(tok,"exclude-file=") == 0) {
            exc = &tok[13];
            options->exclude_file = append_sl(options->exclude_file,exc);
        }
-       else if(strncmp(tok,"exclude-list=", 13) == 0) {
+       else if(BSTRNCMP(tok,"exclude-list=") == 0) {
            exc = &tok[13];
            options->exclude_list = append_sl(options->exclude_list, exc);
        }
-       else if(strncmp(tok,"include-file=", 13) == 0) {
+       else if(BSTRNCMP(tok,"include-file=") == 0) {
            exc = &tok[13];
            options->include_file = append_sl(options->include_file,exc);
        }
-       else if(strncmp(tok,"include-list=", 13) == 0) {
+       else if(BSTRNCMP(tok,"include-list=") == 0) {
            exc = &tok[13];
            options->include_list = append_sl(options->include_list, exc);
        }
        else if(strcmp(tok,"|") == 0) {
        }
        else {
-           dbprintf(("%s: unknown option \"%s\"\n",
-                                  debug_prefix(NULL), tok));
+           dbprintf(("%s: unknown option \"%s\"\n", debug_prefix(NULL), tok));
            if(verbose) {
                printf("ERROR [unknown option \"%s\"]\n", tok);
            }
index 559c957e1cd28d725f39aac925e2ff859163c5e5..ef8ef8e3f477a9e02b0585d5f83c48c801ba9ba1 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: client_util.h,v 1.1.2.10 2002/04/22 01:54:34 martinea Exp $
+ * $Id: client_util.h,v 1.12 2005/12/09 03:22:52 paddy_s Exp $
  *
  */
 
 #include "amanda.h"
 #include "amfeatures.h"
 #include "sl.h"
+#include "util.h"              /* for bstrncmp() */
 
 typedef struct option_s {
     char *str;
     int compress;
+    int encrypt;
+    char *srvcompprog;
+    char *clntcompprog;
+    char *srv_encrypt;
+    char *clnt_encrypt;
+    char *srv_decrypt_opt;
+    char *clnt_decrypt_opt;
     int no_record;
-    int bsd_auth;
     int createindex;
+    char *auth;
     sl_t *exclude_file;
     sl_t *exclude_list;
     sl_t *include_file;
     sl_t *include_list;
     int exclude_optional;
     int include_optional;
-#ifdef KRB4_SECURITY
-    int krb4_auth;
-    int kencrypt;
-#endif
 } option_t;
 
 typedef struct g_option_s {
@@ -65,6 +69,12 @@ typedef struct g_option_s {
 #define COMPR_BEST 2
 #define COMPR_SERVER_FAST 3
 #define COMPR_SERVER_BEST 4
+#define COMPR_SERVER_CUST 5    /* server-side custom compression */
+#define COMPR_CUST 6            /* client-side custom compression */
+
+#define ENCRYPT_NONE         0 /* no encryption  */
+#define ENCRYPT_CUST         1 /* client-side custom encryption */
+#define ENCRYPT_SERV_CUST    2 /* server-side custom encryption */
 
 char *build_exclude P((char *disk, char *device, option_t *options, int verbose));
 char *build_include P((char *disk, char *device, option_t *options, int verbose));
@@ -72,7 +82,7 @@ void init_options P((option_t *options));
 option_t *parse_options P((char *str,
                           char *disk,
                           char *device,
-                          am_feature_t *fs,
+                          am_feature_t *features,
                           int verbose));
 
 void init_g_options P((g_option_t *g_options));
index 290af67fabec5de85250e8e630e66a02b966ff6e..301c2c15cef37f2862bfb7c0a552801401b3219c 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: findpass.c,v 1.10.4.1.4.1 2001/08/01 22:36:24 jrjackson Exp $
+ * $Id: findpass.c,v 1.12 2001/08/01 22:37:32 jrjackson Exp $
  *
  * Support routines for Amanda SAMBA support
  */
index 50fd041ad1583c5d0313490b42ea3fa1c38aaa83..26966993b9935a2e0ff3e2424d9889b4d1be4789 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: findpass.h,v 1.5.8.1 2001/08/01 22:36:24 jrjackson Exp $
+ * $Id: findpass.h,v 1.6 2001/08/01 22:37:32 jrjackson Exp $
  *
  * interface to findpass module
  */
index f191fc14341b22311361f31d718af9a9bccd120f..516cf4eed228abafea1d7b3cabbd4e884c98bac5 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: getfsent.c,v 1.20.4.1.2.2.2.6.2.2 2005/09/30 19:13:36 martinea Exp $
+ * $Id: getfsent.c,v 1.34 2006/01/14 04:37:18 paddy_s Exp $
  *
  * generic version of code to read fstab
  */
@@ -40,6 +40,9 @@
 
 #include "getfsent.h"
 
+static char *dev2rdev P((char *));
+static int samefile P((struct stat[3], struct stat *));
+
 /*
  * You are in a twisty maze of passages, all alike.
  * Geesh.
@@ -395,7 +398,7 @@ generic_fsent_t *fsent;
  * Convert either a block or character device name to a character (raw)
  * device name.
  *
- * char *dev2rdev(char *name);
+ * static char *dev2rdev(const char *name);
  *
  * entry:      name - device name to convert
  * exit:       matching character device name if found,
@@ -620,6 +623,9 @@ int main(argc, argv)
 
     set_pname("getfsent");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     if(!open_fstab()) {
index 8bc76d87623c798c7a597bcd90d5b48d7a362980..a8b37b00c8d85783023e6d7a95ef0edf14ff05d8 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: getfsent.h,v 1.4.8.1.2.2 2002/10/27 22:58:47 martinea Exp $
+ * $Id: getfsent.h,v 1.7 2002/10/27 22:58:33 martinea Exp $
  *
  * interfaces for obtaining filesystem information
  */
index f21944f1fd6bb0cf5ff73383246e8b6738ace175..1837409f96461ab6502601f651ced7cf0977feb4 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: killpgrp.c,v 1.8.4.2.4.1.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: killpgrp.c,v 1.12 2005/09/20 21:32:25 jrjackson Exp $
  *
  * if it is the process group leader, it kills all processes in its
  * process group when it is killed itself.
@@ -66,13 +66,11 @@ char **argv;
     }
 
 #ifdef FORCE_USERID
-    if (getuid() != client_uid) {
+    if (getuid() != client_uid)
        error("error [must be invoked by %s]", CLIENT_LOGIN);
-    }
 
-    if (geteuid() != 0) {
+    if (geteuid() != 0)
        error("error [must be setuid root]");
-    }
 #endif /* FORCE_USERID */
 
 #if !defined (DONT_SUID_ROOT)
diff --git a/client-src/noop.c b/client-src/noop.c
new file mode 100644 (file)
index 0000000..3700852
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+
+/*
+ * $Id: noop.c,v 1.3 2006/01/14 04:37:18 paddy_s Exp $
+ *
+ * send back features.  This was pulled out to it's own program for
+ * consistancy and because it's a hell of a lot easier to code in
+ * a fork()-less environment.
+ */
+
+#include "amanda.h"
+#include "amfeatures.h"
+#include "util.h"
+
+int main P((int argc, char **argv));
+
+int
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    char ch;
+    am_feature_t *our_features = NULL;
+    char *our_feature_string = NULL;
+    char *options;
+    int n;
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    do {
+       /* soak up any stdin */
+       n = read(0, &ch, 1);
+    } while ((n > 0) || ((n < 0) && ((errno == EINTR) || (errno == EAGAIN))));
+    our_features = am_init_feature_set();
+    our_feature_string = am_feature_to_string(our_features);
+    options = vstralloc("OPTIONS features=",
+                       our_feature_string,
+                       ";\n",
+                       NULL);
+    amfree(our_feature_string);
+    am_release_feature_set(our_features);
+    our_features = NULL;
+    if (fullwrite(1, options, strlen(options)) < 0) {
+       error("error sending noop response: %s", strerror(errno));
+    }
+    amfree(options);
+    exit(0);
+}
index d25f2f3cf0d73123e5c28572d2e5a0af8d788c4c..347da0a356e4c27ea914b0125d91e2ef0b616abf 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: rundump.c,v 1.23.2.3.6.1.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: rundump.c,v 1.28 2006/01/14 04:37:18 paddy_s Exp $
  *
  * runs DUMP program as root
  */
@@ -34,6 +34,7 @@
 int main P((int argc, char **argv));
 
 #if defined(VDUMP) || defined(XFSDUMP)
+#  undef USE_RUNDUMP
 #  define USE_RUNDUMP
 #endif
 
@@ -62,6 +63,9 @@ char **argv;
 
     set_pname("rundump");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     dbopen();
     dbprintf(("%s: version %s\n", argv[0], version()));
 
@@ -79,13 +83,11 @@ char **argv;
     }
 
 #ifdef FORCE_USERID
-    if (getuid() != client_uid) {
+    if (getuid() != client_uid)
        error("error [must be invoked by %s]\n", CLIENT_LOGIN);
-    }
 
-    if (geteuid() != 0) {
+    if (geteuid() != 0)
        error("error [must be setuid root]\n");
-    }
 #endif /* FORCE_USERID */
 
 #if !defined (DONT_SUID_ROOT)
@@ -138,7 +140,7 @@ char **argv;
     execve(dump_program, argv, safe_env());
 
     e = strerror(errno);
-    dbprintf(("execve of %s failed (%s)\n", dump_program, e));
+    dbprintf(("failed (%s)\n", e));
     dbclose();
 
     fprintf(stderr, "rundump: could not exec %s: %s\n", dump_program, e);
index da6d9fc741c674dbdbc4072d8909bc48a0ffbcac..d24352bd907f7a31c1dc195f21f59e80e3ce8c39 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: runtar.c,v 1.11.4.2.6.1.2.3 2005/09/30 19:08:04 martinea Exp $
+ * $Id: runtar.c,v 1.17 2006/01/14 04:37:18 paddy_s Exp $
  *
  * runs GNUTAR program as root
  */
@@ -48,6 +48,9 @@ char **argv;
 
     set_pname("runtar");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     dbopen();
     dbprintf(("%s: version %s\n", argv[0], version()));
 
@@ -65,13 +68,11 @@ char **argv;
     }
 
 #ifdef FORCE_USERID
-    if (getuid() != client_uid) {
+    if (getuid() != client_uid)
        error("error [must be invoked by %s]\n", CLIENT_LOGIN);
-    }
 
-    if (geteuid() != 0) {
+    if (geteuid() != 0)
        error("error [must be setuid root]\n");
-    }
 #endif
 
 #if !defined (DONT_SUID_ROOT)
index b764e6c3d99868a85e9a340ad218f95f39beed1d..44584c90c0135ebd3245dc96ec96bb402e500b35 100644 (file)
  *                        University of Maryland at College Park
  */
 /* 
- * $Id: selfcheck.c,v 1.40.2.3.4.4.2.22.2.3 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: selfcheck.c,v 1.76 2006/01/14 04:37:18 paddy_s Exp $
  *
  * do self-check and send back any error messages
  */
 
 #include "amanda.h"
-#include "clock.h"
 #include "statfs.h"
 #include "version.h"
 #include "getfsent.h"
 #include "amandates.h"
+#include "clock.h"
 #include "util.h"
 #include "pipespawn.h"
 #include "amfeatures.h"
@@ -59,6 +59,7 @@ int need_runtar=0;
 int need_gnutar=0;
 int need_compress_path=0;
 int need_calcsize=0;
+int program_is_wrapper=0;
 
 static am_feature_t *our_features = NULL;
 static char *our_feature_string = NULL;
@@ -67,8 +68,8 @@ static g_option_t *g_options = NULL;
 /* local functions */
 int main P((int argc, char **argv));
 
-static void check_options P((char *program, char *calcprog, char *disk, char *device, option_t *options));
-static void check_disk P((char *program, char *calcprog, char *disk, char *amdevice, int level));
+static void check_options P((char *program, char *calcprog, char *disk, char *amdevice, option_t *options));
+static void check_disk P((char *program, char *calcprog, char *disk, char *amdevice, int level, char *optstr));
 static void check_overall P((void));
 static void check_access P((char *filename, int mode));
 static void check_file P((char *filename, int mode));
@@ -85,7 +86,7 @@ char **argv;
     char *program = NULL;
     char *calcprog = NULL;
     char *disk = NULL;
-    char *device = NULL;
+    char *amdevice = NULL;
     char *optstr = NULL;
     char *err_extra = NULL;
     char *s, *fp;
@@ -101,12 +102,15 @@ char **argv;
 
     set_pname("selfcheck");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
     dbopen();
     startclock();
-    dbprintf(("%s: version %s\n", argv[0], version()));
+    dbprintf(("%s: version %s\n", get_pname(), version()));
 
     our_features = am_init_feature_set();
     our_feature_string = am_feature_to_string(our_features);
@@ -147,6 +151,18 @@ char **argv;
        skip_non_whitespace(s, ch);
        s[-1] = '\0';                           /* terminate the program name */
 
+       program_is_wrapper = 0;
+       if(strcmp(program,"DUMPER")==0) {
+           program_is_wrapper = 1;
+           skip_whitespace(s, ch);             /* find dumper name */
+           if (ch == '\0') {
+               goto err;                       /* no program */
+           }
+           program = s - 1;
+           skip_non_whitespace(s, ch);
+           s[-1] = '\0';                       /* terminate the program name */
+       }
+
        if(strncmp(program, "CALCSIZE", 8) == 0) {
            skip_whitespace(s, ch);             /* find program name */
            if (ch == '\0') {
@@ -175,12 +191,12 @@ char **argv;
        if(!isdigit((int)s[-1])) {
            fp = s - 1;
            skip_non_whitespace(s, ch);
-           s[-1] = '\0';                       /* terminate the device */
-           device = stralloc(fp);
+            s[-1] = '\0';                      /* terminate the device */
+           amdevice = stralloc(fp);
            skip_whitespace(s, ch);             /* find level number */
        }
        else {
-           device = stralloc(disk);
+           amdevice = stralloc(disk);
        }
 
                                                /* find level number */
@@ -202,13 +218,14 @@ char **argv;
            optstr = s - 1;
            skip_non_whitespace(s, ch);
            s[-1] = '\0';                       /* terminate the options */
-           options = parse_options(optstr, disk, device, g_options->features, 1);
-           check_options(program, calcprog, disk, device, options);
-           check_disk(program, calcprog, disk, device, level);
+           options = parse_options(optstr, disk, amdevice, g_options->features, 1);
+           check_options(program, calcprog, disk, amdevice, options);
+           check_disk(program, calcprog, disk, amdevice, level, &optstr[2]);
            free_sl(options->exclude_file);
            free_sl(options->exclude_list);
            free_sl(options->include_file);
            free_sl(options->include_list);
+           amfree(options->auth);
            amfree(options->str);
            amfree(options);
        } else if (ch == '\0') {
@@ -227,11 +244,11 @@ char **argv;
            need_gnutar=1;
            need_compress_path=1;
            need_calcsize=1;
-           check_disk(program, calcprog, disk, device, level);
+           check_disk(program, calcprog, disk, amdevice, level, "");
        } else {
            goto err;                           /* bad syntax */
        }
-       amfree(device);
+       amfree(amdevice);
     }
 
     check_overall();
@@ -271,8 +288,8 @@ char **argv;
 
 
 static void
-check_options(program, calcprog, disk, device, options)
-    char *program, *calcprog, *disk, *device;
+check_options(program, calcprog, disk, amdevice, options)
+    char *program, *calcprog, *disk, *amdevice;
     option_t *options;
 {
     char *myprogram = program;
@@ -288,8 +305,8 @@ check_options(program, calcprog, disk, device, options)
        if(options->include_file) nb_include += options->include_file->nb_element;
        if(options->include_list) nb_include += options->include_list->nb_element;
 
-       if(nb_exclude > 0) file_exclude = build_exclude(disk, device, options, 1);
-       if(nb_include > 0) file_include = build_include(disk, device, options, 1);
+       if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 1);
+       if(nb_include > 0) file_include = build_include(disk, amdevice, options, 1);
 
        amfree(file_exclude);
        amfree(file_include);
@@ -300,7 +317,7 @@ check_options(program, calcprog, disk, device, options)
 
     if(strcmp(myprogram,"GNUTAR") == 0) {
        need_gnutar=1;
-        if(disk[0] == '/' && disk[1] == '/') {
+        if(amdevice[0] == '/' && amdevice[1] == '/') {
            if(options->exclude_file && options->exclude_file->nb_element > 1) {
                printf("ERROR [samba support only one exclude file]\n");
            }
@@ -328,8 +345,8 @@ check_options(program, calcprog, disk, device, options)
            if(options->include_file) nb_include += options->include_file->nb_element;
            if(options->include_list) nb_include += options->include_list->nb_element;
 
-           if(nb_exclude > 0) file_exclude = build_exclude(disk, device, options, 1);
-           if(nb_include > 0) file_include = build_include(disk, device, options, 1);
+           if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 1);
+           if(nb_include > 0) file_include = build_include(disk, amdevice, options, 1);
 
            amfree(file_exclude);
            amfree(file_include);
@@ -357,7 +374,7 @@ check_options(program, calcprog, disk, device, options)
 #ifndef AIX_BACKUP
 #ifdef VDUMP
 #ifdef DUMP
-       if (strcmp(amname_to_fstype(disk), "advfs") == 0)
+       if (strcmp(amname_to_fstype(amdevice), "advfs") == 0)
 #else
        if (1)
 #endif
@@ -371,7 +388,7 @@ check_options(program, calcprog, disk, device, options)
 #endif /* VDUMP */
 #ifdef XFSDUMP
 #ifdef DUMP
-       if (strcmp(amname_to_fstype(disk), "xfs") == 0)
+       if (strcmp(amname_to_fstype(amdevice), "xfs") == 0)
 #else
        if (1)
 #endif
@@ -385,7 +402,7 @@ check_options(program, calcprog, disk, device, options)
 #endif /* XFSDUMP */
 #ifdef VXDUMP
 #ifdef DUMP
-       if (strcmp(amname_to_fstype(disk), "vxfs") == 0)
+       if (strcmp(amname_to_fstype(amdevice), "vxfs") == 0)
 #else
        if (1)
 #endif
@@ -408,13 +425,16 @@ check_options(program, calcprog, disk, device, options)
            need_restore=1;
 #endif
     }
-    if(options->compress == COMPR_BEST || options->compress == COMPR_FAST) 
+    if(program_is_wrapper==1) {
+    }
+    if(options->compress == COMPR_BEST || options->compress == COMPR_FAST || options->compress == COMPR_CUST)
        need_compress_path=1;
 }
 
-static void check_disk(program, calcprog, disk, amdevice, level)
+static void check_disk(program, calcprog, disk, amdevice, level, optstr)
 char *program, *calcprog, *disk, *amdevice;
 int level;
+char *optstr;
 {
     char *device = NULL;
     char *err = NULL;
@@ -486,7 +506,11 @@ int level;
                goto common_exit;
            }
 
-           nullfd = open("/dev/null", O_RDWR);
+           if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+               err = stralloc2("Cannot access /dev/null : ", strerror(errno));
+               goto common_exit;
+           }
+
            if (pwtext_len > 0) {
                pw_fd_env = "PASSWD_FD";
            } else {
@@ -555,7 +579,7 @@ int level;
                    } else {
                        strappend(err, "returned ");
                    }
-                   ap_snprintf(number, sizeof(number), "%d", ret);
+                   snprintf(number, sizeof(number), "%d", ret);
                    strappend(err, number);
                }
            }
@@ -570,17 +594,17 @@ int level;
                amfree(extra_info);
            }
 #else
-           err = stralloc2("This client is not configured for samba: ", amdevice);
+           err = stralloc2("This client is not configured for samba: ", disk);
 #endif
            goto common_exit;
        }
        amode = F_OK;
        device = amname_to_dirname(amdevice);
-    } else {
+    } else if (strcmp(program, "DUMP") == 0) {
        if(amdevice[0] == '/' && amdevice[1] == '/') {
            err = vstralloc("The DUMP program cannot handle samba shares,",
                            " use GNUTAR: ",
-                           amdevice,
+                           disk,
                            NULL);
            goto common_exit;
        }
@@ -604,6 +628,33 @@ int level;
 #endif
        }
     }
+    else { /* program_is_wrapper==1 */
+       int pid_wrapper;
+       fflush(stdout);fflush(stdin);
+       switch (pid_wrapper = fork()) {
+       case -1: error("fork: %s", strerror(errno));
+       case 0: /* child */
+           {
+               char *argvchild[6];
+               char *cmd = vstralloc(DUMPER_DIR, "/", program, NULL);
+               argvchild[0] = program;
+               argvchild[1] = "selfcheck";
+               argvchild[2] = disk;
+               argvchild[3] = amdevice;
+               argvchild[4] = optstr;
+               argvchild[5] = NULL;
+               execve(cmd,argvchild,safe_env());
+               exit(127);
+           }
+       default: /* parent */
+           {
+               int status;
+               waitpid(pid_wrapper, &status, 0);
+           }
+       }
+       fflush(stdout);fflush(stdin);
+       return;
+    }
 
     dbprintf(("%s: device %s\n", debug_prefix_time(NULL), device));
 
@@ -795,9 +846,8 @@ static void check_overall()
        }
     }
 
-    if( need_compress_path ) {
+    if( need_compress_path )
        check_file(COMPRESS_PATH, X_OK);
-    }
 
     if( need_dump || need_xfsdump )
        check_file("/var/lib/dumpdates",
@@ -808,9 +858,8 @@ static void check_overall()
 #endif
                   );
 
-    if (need_vdump) {
+    if (need_vdump)
         check_file("/etc/vdumpdates", F_OK);
-    }
 
     check_access("/dev/null", R_OK|W_OK);
     check_space(AMANDA_TMPDIR, 64);    /* for amandad i/o */
index f6f232f41e03bf23752b817b3e7b57842bc4f3fb..9bda7ad1616989980f6fd98c859b1a2d2c64ce80 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup-dump.c,v 1.65.2.5.4.2.2.9.2.1 2005/09/20 18:13:08 jrjackson Exp $
+ * $Id: sendbackup-dump.c,v 1.88 2006/03/09 20:06:11 johnfranks Exp $
  *
  * send backup data using BSD dump
  */
 
 #include "sendbackup.h"
-#include "clock.h"
 #include "getfsent.h"
+#include "clock.h"
 #include "version.h"
 
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.h"
-#else                                  /* I'd tell you what this does */
-#define NAUGHTY_BITS                   /* but then I'd have to kill you */
-#endif
-
 #define LEAF_AND_DIRS "sed -e \'\ns/^leaf[ \t]*[0-9]*[ \t]*\\.//\nt\n/^dir[ \t]/ {\ns/^dir[ \t]*[0-9]*[ \t]*\\.//\ns%$%/%\nt\n}\nd\n\'"
 
 static regex_t re_table[] = {
@@ -56,7 +50,6 @@ static regex_t re_table[] = {
             1024),
   AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*KB\\) on [0-9][0-9]* volume",
             512),
-
   AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*\\.[0-9][0-9]*MB\\) on [0-9][0-9]* volume",
             512),
   AM_SIZE_RE("DUMP: [0-9][0-9]* blocks", 1024),
@@ -91,25 +84,25 @@ static regex_t re_table[] = {
 
   /* any blank or non-strange DUMP: lines are marked as normal */
   AM_NORMAL_RE("^ *DUMP:"),
-  AM_NORMAL_RE("^dump:"),                              /* OSF/1 */
-  AM_NORMAL_RE("^vdump:"),                             /* OSF/1 */
-  AM_NORMAL_RE("^ *vxdump:"),                          /* HPUX10 */
-  AM_NORMAL_RE("^ *vxfs *vxdump:"),                    /* Solaris */
-  AM_NORMAL_RE("^Dumping .* to stdout"),               /* Solaris vxdump */
-  AM_NORMAL_RE("^xfsdump:"),                           /* IRIX xfs */
-  AM_NORMAL_RE("^ *VXDUMP:"),                          /* Sinix */
-  AM_NORMAL_RE("^ *UFSDUMP:"),                         /* Sinix */
+  AM_NORMAL_RE("^dump:"),                                      /* OSF/1 */
+  AM_NORMAL_RE("^vdump:"),                                     /* OSF/1 */
+  AM_NORMAL_RE("^ *vxdump:"),                                  /* HPUX10 */
+  AM_NORMAL_RE("^ *vxfs *vxdump:"),                            /* Solaris */
+  AM_NORMAL_RE("^Dumping .* to stdout"),                       /* Sol vxdump */
+  AM_NORMAL_RE("^xfsdump:"),                                   /* IRIX xfs */
+  AM_NORMAL_RE("^ *VXDUMP:"),                                  /* Sinix */
+  AM_NORMAL_RE("^ *UFSDUMP:"),                                 /* Sinix */
 
 #ifdef VDUMP   /* this is for OSF/1 3.2's vdump for advfs */
-  AM_NORMAL_RE("^The -s option is ignored"),           /* OSF/1 */
-  AM_NORMAL_RE("^path"),                               /* OSF/1 */
-  AM_NORMAL_RE("^dev/fset"),                           /* OSF/1 */
-  AM_NORMAL_RE("^type"),                               /* OSF/1 */
-  AM_NORMAL_RE("^advfs id"),                           /* OSF/1 */
+  AM_NORMAL_RE("^The -s option is ignored"),                   /* OSF/1 */
+  AM_NORMAL_RE("^path"),                                       /* OSF/1 */
+  AM_NORMAL_RE("^dev/fset"),                                   /* OSF/1 */
+  AM_NORMAL_RE("^type"),                                       /* OSF/1 */
+  AM_NORMAL_RE("^advfs id"),                                   /* OSF/1 */
   AM_NORMAL_RE("^[A-Z][a-z][a-z] [A-Z][a-z][a-z] .[0-9] [0-9]"), /* OSF/1 */
 #endif
 
-  AM_NORMAL_RE("^backup:"),                            /* AIX */
+  AM_NORMAL_RE("^backup:"),                                    /* AIX */
   AM_NORMAL_RE("^        Use the umount command to unmount the filesystem"),
 
   AM_NORMAL_RE("^[ \t]*$"),
@@ -118,29 +111,48 @@ static regex_t re_table[] = {
   AM_STRANGE_RE(NULL)
 };
 
+/*
+ *  doing similar to $ dump | compression | encryption
+ */
+
 static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, indexf)
     char *host;
     char *disk, *amdevice;
     int level, dataf, mesgf, indexf;
     char *dumpdate;
 {
-    int dumpin, dumpout;
+    int dumpin, dumpout, compout;
     char *dumpkeys = NULL;
     char *device = NULL;
     char *fstype = NULL;
     char *cmd = NULL;
     char *indexcmd = NULL;
     char level_str[NUM_STR_SIZE];
+    char *compopt  = NULL;
+    char *encryptopt = skip_argument;
 
-    ap_snprintf(level_str, sizeof(level_str), "%d", level);
+
+    snprintf(level_str, sizeof(level_str), "%d", level);
 
     fprintf(stderr, "%s: start [%s:%s level %d]\n",
            get_pname(), host, disk, level);
 
-    NAUGHTY_BITS;
+      /*  apply client-side encryption here */
+      if ( options->encrypt == ENCRYPT_CUST ) {
+       encpid = pipespawn(options->clnt_encrypt, STDIN_PIPE,
+                       &compout, &dataf, &mesgf,
+                       options->clnt_encrypt, encryptopt, NULL);
+       dbprintf(("%s: pid %ld: %s\n",
+                 debug_prefix_time("-gnutar"), (long)encpid, options->clnt_encrypt));
+     } else {
+        compout = dataf;
+        encpid = -1;
+     }
+      /*  now do the client-side compression */
+
 
     if(options->compress == COMPR_FAST || options->compress == COMPR_BEST) {
-       char *compopt = skip_argument;
+       compopt = skip_argument;
 
 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
        if(options->compress == COMPR_BEST) {
@@ -150,7 +162,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        }
 #endif
        comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE,
-                           &dumpout, &dataf, &mesgf,
+                           &dumpout, &compout, &mesgf,
                            COMPRESS_PATH, compopt, NULL);
        dbprintf(("%s: pid %ld: %s",
                  debug_prefix_time("-dump"), (long)comppid, COMPRESS_PATH));
@@ -158,8 +170,19 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            dbprintf((" %s", compopt));
        }
        dbprintf(("\n"));
+     } else if (options->compress == COMPR_CUST) {
+        compopt = skip_argument;
+       comppid = pipespawn(options->clntcompprog, STDIN_PIPE,
+                           &dumpout, &compout, &mesgf,
+                           options->clntcompprog, compopt, NULL);
+       dbprintf(("%s: pid %ld: %s",
+                 debug_prefix_time("-gnutar-cust"), (long)comppid, options->clntcompprog));
+       if(compopt != skip_argument) {
+           dbprintf((" %s", compopt));
+       }
+       dbprintf(("\n"));
     } else {
-       dumpout = dataf;
+       dumpout = compout;
        comppid = -1;
     }
 
@@ -198,7 +221,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
                             " | sed",
                             " -e", " \'s/^/\\//\'",
                             NULL);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -243,7 +266,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
                             " | ",
                             LEAF_AND_DIRS,
                             NULL);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -284,7 +307,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
                             " | ",
                             "sed -e \'\n/^\\./ {\ns/^\\.//\ns/, [0-9]*$//\ns/^\\.//\ns/ @-> .*$//\nt\n}\nd\n\'",
                             NULL);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -321,7 +344,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
                             " | ",
                             LEAF_AND_DIRS,
                             NULL);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -352,7 +375,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
                         " | ",
                         LEAF_AND_DIRS,
                         NULL);
-    write_tapeheader();
+    info_tapeheader();
 
     start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -366,6 +389,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 #endif                                                 /* } */
 
     amfree(dumpkeys);
+    amfree(fstype);
     amfree(device);
     amfree(cmd);
     amfree(indexcmd);
@@ -374,6 +398,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 
     aclose(dumpin);
     aclose(dumpout);
+    aclose(compout);
     aclose(dataf);
     aclose(mesgf);
     if (options->createindex)
index 1f2ed0d864a26379ae88c0824cc395ec66c23e37..4b4a000b88fa6fb0ad963c5bf16b3d8ec769a54e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup-gnutar.c,v 1.56.2.15.4.4.2.11.2.2 2005/06/23 08:46:07 weichinger Exp $
+ * $Id: sendbackup-gnutar.c,v 1.92 2005/12/09 03:22:52 paddy_s Exp $
  *
  * send backup data using GNU tar
  */
 #include "findpass.h"
 #endif
 
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.h"
-#else                                  /* I'd tell you what this does */
-#define NAUGHTY_BITS                   /* but then I'd have to kill you */
-#endif
-
-
 static regex_t re_table[] = {
   /* tar prints the size in bytes */
   AM_SIZE_RE("^ *Total bytes written: [0-9][0-9]*", 1),
-
   AM_NORMAL_RE("^Elapsed time:"),
   AM_NORMAL_RE("^Throughput"),
 
@@ -125,6 +117,8 @@ static regex_t re_table[] = {
   AM_STRANGE_RE(NULL)
 };
 
+extern char *efile;
+
 int cur_level;
 char *cur_disk;
 time_t cur_dumptime;
@@ -132,14 +126,16 @@ time_t cur_dumptime;
 #ifdef GNUTAR_LISTED_INCREMENTAL_DIR
 static char *incrname = NULL;
 #endif
-
+/*
+ *  doing similar to $ gtar | compression | encryption 
+ */
 static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, indexf)
     char *host;
     char *disk, *amdevice;
     int level, dataf, mesgf, indexf;
     char *dumpdate;
 {
-    int dumpin, dumpout;
+    int dumpin, dumpout, compout;
     char *cmd = NULL;
     char *indexcmd = NULL;
     char *dirname = NULL;
@@ -149,17 +145,28 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
     amandates_t *amdates;
     time_t prev_dumptime;
     char *error_pn = NULL;
+    char *compopt  = NULL;
+    char *encryptopt = skip_argument;
 
     error_pn = stralloc2(get_pname(), "-smbclient");
 
+
     fprintf(stderr, "%s: start [%s:%s level %d]\n",
            get_pname(), host, disk, level);
-
-    NAUGHTY_BITS;
-
+     /*  apply client-side encryption here */
+     if ( options->encrypt == ENCRYPT_CUST ) {
+      encpid = pipespawn(options->clnt_encrypt, STDIN_PIPE,
+                       &compout, &dataf, &mesgf, 
+                       options->clnt_encrypt, encryptopt, NULL);
+      dbprintf(("%s: pid %ld: %s\n",
+                 debug_prefix_time("-gnutar"), (long)encpid, options->clnt_encrypt));
+    } else {
+       compout = dataf;
+       encpid = -1;
+    } 
+     /*  now do the client-side compression */
     if(options->compress == COMPR_FAST || options->compress == COMPR_BEST) {
-       char *compopt = skip_argument;
-
+          compopt = skip_argument;
 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
        if(options->compress == COMPR_BEST) {
            compopt = COMPRESS_BEST_OPT;
@@ -168,7 +175,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        }
 #endif
        comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE,
-                           &dumpout, &dataf, &mesgf,
+                           &dumpout, &compout, &mesgf,
                            COMPRESS_PATH, compopt, NULL);
        dbprintf(("%s: pid %ld: %s",
                  debug_prefix_time("-gnutar"), (long)comppid, COMPRESS_PATH));
@@ -176,8 +183,19 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            dbprintf((" %s", compopt));
        }
        dbprintf(("\n"));
+     } else if (options->compress == COMPR_CUST) {
+        compopt = skip_argument;
+       comppid = pipespawn(options->clntcompprog, STDIN_PIPE,
+                           &dumpout, &compout, &mesgf,
+                           options->clntcompprog, compopt, NULL);
+       dbprintf(("%s: pid %ld: %s",
+                 debug_prefix_time("-gnutar-cust"), (long)comppid, options->clntcompprog));
+       if(compopt != skip_argument) {
+           dbprintf((" %s", compopt));
+       }
+       dbprintf(("\n"));
     } else {
-       dumpout = dataf;
+       dumpout = compout;
        comppid = -1;
     }
 
@@ -212,7 +230,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
            if(ch == '/' || isspace(ch)) s[-1] = '_';
        }
 
-       ap_snprintf(number, sizeof(number), "%d", level);
+       snprintf(number, sizeof(number), "%d", level);
        incrname = vstralloc(basename, "_", number, ".new", NULL);
        unlink(incrname);
 
@@ -224,7 +242,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        baselevel = level;
        while (in == NULL) {
            if (--baselevel >= 0) {
-               ap_snprintf(number, sizeof(number), "%d", baselevel);
+               snprintf(number, sizeof(number), "%d", baselevel);
                inputname = newvstralloc(inputname,
                                         basename, "_", number, NULL);
            } else {
@@ -297,7 +315,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
     free_amandates();
 
     gmtm = gmtime(&prev_dumptime);
-    ap_snprintf(dumptimestr, sizeof(dumptimestr),
+    snprintf(dumptimestr, sizeof(dumptimestr),
                "%04d-%02d-%02d %2d:%02d:%02d GMT",
                gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
                gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
@@ -336,18 +354,18 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 
        parsesharename(amdevice, &share, &subdir);
        if (!share) {
-            amfree(share);
-            amfree(subdir);
-            set_pname(error_pn);
-            amfree(error_pn);
-            error("cannot parse disk entry '%s' for share/subdir", disk);
+           amfree(share);
+           amfree(subdir);
+           set_pname(error_pn);
+           amfree(error_pn);
+           error("cannot parse disk entry '%s' for share/subdir", disk);
        }
        if ((subdir) && (SAMBA_VERSION < 2)) {
-            amfree(share);
-            amfree(subdir);
-            set_pname(error_pn);
-            amfree(error_pn);
-            error("subdirectory specified for share '%s' but samba not v2 or better", disk);
+           amfree(share);
+           amfree(subdir);
+           set_pname(error_pn);
+           amfree(error_pn);
+           error("subdirectory specified for share '%s' but samba not v2 or better", disk);
        }
        if ((user_and_password = findpass(share, &domain)) == NULL) {
            if(domain) {
@@ -406,7 +424,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 
        program->backup_name = program->restore_name = SAMBA_CLIENT;
        cmd = stralloc(program->backup_name);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -457,8 +475,9 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        amfree(taropt);
        tarpid = dumppid;
     } else
-#endif                                                                 /* } */
+#endif                 /*end of samba */
     {
+
        int nb_exclude = 0;
        int nb_include = 0;
        char **my_argv;
@@ -477,7 +496,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        my_argv = alloc(sizeof(char *) * (17 + (nb_exclude*2)+(nb_include*2)));
 
        cmd = vstralloc(libexecdir, "/", "runtar", versionsuffix(), NULL);
-       write_tapeheader();
+       info_tapeheader();
 
        start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
 
@@ -495,7 +514,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
        my_argv[i++] = "--incremental";
        my_argv[i++] = "--newer";
        my_argv[i++] = dumptimestr;
-#endif 
+#endif
 #ifdef ENABLE_GNUTAR_ATIME_PRESERVE
        /* --atime-preserve causes gnutar to call
         * utime() after reading files in order to
@@ -542,6 +561,7 @@ static void start_backup(host, disk, amdevice, level, dumpdate, dataf, mesgf, in
 
     aclose(dumpin);
     aclose(dumpout);
+    aclose(compout);
     aclose(dataf);
     aclose(mesgf);
     if (options->createindex)
@@ -558,8 +578,8 @@ int goterror;
        
            nodotnew = stralloc(incrname);
            nodotnew[strlen(nodotnew)-4] = '\0';
-           if (rename(incrname, nodotnew) != 0) {
-               fprintf(stderr, "%s: warning [renaming %s to %s: %s]\n",
+           if (rename(incrname, nodotnew)) {
+               fprintf(stderr, "%s: warning [renaming %s to %s: %s]\n", 
                        get_pname(), incrname, nodotnew, strerror(errno));
            }
            amfree(nodotnew);
@@ -568,7 +588,7 @@ int goterror;
 #endif
 
         if(!start_amandates(1)) {
-           fprintf(stderr, "%s: warning [opening %s: %s]\n", get_pname(),
+           fprintf(stderr, "%s: warning [opening %s: %s]", get_pname(),
                    AMANDATES_FILE, strerror(errno));
        }
        else {
diff --git a/client-src/sendbackup-krb4.c b/client-src/sendbackup-krb4.c
deleted file mode 100644 (file)
index 25a6ec2..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991,1993 University of Maryland
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
- */
-/*
- * sendbackup-krb4.c - those bits of sendbackup code that deal with encrypting
- *                    data streams over the network.  Even though these just
- *                    call the underlying DES routines, the U.S. government
- *                    considers this a munition.  Go figure.
- */
-#include "krb4-security.h"
-#include "sendbackup-krb4.h"
-
-/*
- * NOTE:  This symbol must be the same as DATABUF_SIZE in
- * server-src/dumper-krb4.c
- * so that the encrypt/decrypt routines are working on the same sized buffers.
- * Really, this should be moved out of dumper.c so that both programs can use
- * the same symbol.  Hopefully that can be done later.  This is good enough
- * to get encryption working for now...
- *
- *                  - Chris Ross (cross@uu.net)  4-Jun-1998
- */
-#define        DATABUF_SIZE    DISK_BLOCK_BYTES
-
-void kencrypt_stream()
-{
-    char *bp, buffer[DATABUF_SIZE];
-    int rdsize, wrsize, left;
-    des_key_schedule sched;
-    int l, n;
-
-    des_key_sched(session_key, sched);
-
-    while(1) {
-       /* read a block, taking into account short reads */
-       left = DATABUF_SIZE;
-       bp = buffer;
-       while(left) {
-           if((rdsize = read(0, bp, left)) == -1)
-               error("kencrypt: read error: %s", strerror(errno));
-           if(rdsize == 0) break;
-           left -= rdsize;
-           bp += rdsize;
-       }
-       if(bp == buffer) break; /* end of file */
-
-       if(bp < buffer+DATABUF_SIZE)
-           memset(bp,0,left);
-
-       des_pcbc_encrypt(buffer, buffer, DATABUF_SIZE, sched, session_key,
-                        DES_ENCRYPT);
-
-       for(l = 0, n = DATABUF_SIZE; l < n; l += wrsize) {
-           if((wrsize = write(1, buffer + l, n - l)) < 0) {
-               error("kencrypt: write error: %s", strerror(errno));
-           }
-       }
-    }
-}
diff --git a/client-src/sendbackup-krb4.h b/client-src/sendbackup-krb4.h
deleted file mode 100644 (file)
index 6d7ca30..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991,1993 University of Maryland
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
- */
-/*
- * sendbackup-krb4.h - those bits of sendbackup defines that deal with 
- *                    encrypting data streams over the network.  Even
- *                    though these just call the underlying DES
- *                    routines, the U.S. government considers this a
- *                    munition.  Go figure.
- */
-
-#if !defined(SENDBACKUP_KRB4_H)
-#define        SENDBACKUP_KRB4_H
-
-#include "krb4-security.h"
-
-#define KEY_PIPE       3
-
-int encpid;
-
-void kencrypt_stream();
-
-    /* modification by BIS@BBN 4/25/2003:
-     * with the option processing changes in amanda 2.4.4, must change
-     * the conditional from kencrypt to options->kencrypt */
-#define NAUGHTY_BITS                                                         \
-    if(options->kencrypt) {                                                  \
-       int encinf;                                                           \
-       encpid = pipefork(kencrypt_stream,"kencrypt",&encinf,dataf,mesgf);    \
-       dataf = encinf;                                                       \
-    }                                                                        \
-    else                                                                     \
-       encpid = -1;
-
-#endif
index e8050448a6544d6b2f298187ac0d835b233fd17d..e824e1ef286555960ca682cfe184f06cb63392e9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup.c,v 1.44.2.9.4.4.2.16.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: sendbackup.c,v 1.77 2006/03/09 16:51:41 martinea Exp $
  *
  * common code for the sendbackup-* programs.
  */
@@ -34,7 +34,7 @@
 #include "clock.h"
 #include "pipespawn.h"
 #include "amfeatures.h"
-#include "stream.h"
+#include "amandad.h"
 #include "arglist.h"
 #include "getfsent.h"
 #include "version.h"
@@ -48,18 +48,12 @@ int encpid = -1;
 int indexpid = -1;
 char *errorstr = NULL;
 
-int data_socket, data_port, dataf;
-int mesg_socket, mesg_port, mesgf;
-int index_socket, index_port, indexf;
+int datafd;
+int mesgfd;
+int indexfd;
 
 option_t *options;
 
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.h"
-#else                                  /* I'd tell you what this does */
-#define NAUGHTY_BITS                   /* but then I'd have to kill you */
-#endif
-
 long dump_size = -1;
 
 backup_program_t *program = NULL;
@@ -78,36 +72,60 @@ int pipefork P((void (*func) P((void)), char *fname, int *stdinfd,
                int stdoutfd, int stderrfd));
 void parse_backup_messages P((int mesgin));
 static void process_dumpline P((char *str));
+static void save_fd P((int *, int));
 
-
-char *optionstr(option_t *options)
+char *optionstr(options)
+option_t *options;
 {
     static char *optstr = NULL;
-    char *compress_opt = "";
+    char *compress_opt;
+    char *encrypt_opt;
+    char *decrypt_opt;
     char *record_opt = "";
-    char *bsd_opt = "";
-    char *krb4_opt = "";
-    char *kencrypt_opt = "";
     char *index_opt = "";
+    char *auth_opt;
     char *exclude_file_opt;
     char *exclude_list_opt;
     char *exc = NULL;
     sle_t *excl;
 
     if(options->compress == COMPR_BEST)
-       compress_opt = "compress-best;";
+       compress_opt = stralloc("compress-best;");
     else if(options->compress == COMPR_FAST)
-       compress_opt = "compress-fast;";
+       compress_opt = stralloc("compress-fast;");
     else if(options->compress == COMPR_SERVER_BEST)
-       compress_opt = "srvcomp-best;";
+       compress_opt = stralloc("srvcomp-best;");
     else if(options->compress == COMPR_SERVER_FAST)
-       compress_opt = "srvcomp-fast;";
+       compress_opt = stralloc("srvcomp-fast;");
+    else if(options->compress == COMPR_SERVER_CUST)
+       compress_opt = vstralloc("srvcomp-cust=", options->srvcompprog, ";", NULL);
+    else if(options->compress == COMPR_CUST)
+       compress_opt = vstralloc("comp-cust=", options->clntcompprog, ";", NULL);
+    else
+       compress_opt = stralloc("");
+    
+    if(options->encrypt == ENCRYPT_CUST) {
+      encrypt_opt = vstralloc("encrypt-cust=", options->clnt_encrypt, ";", NULL);
+      if (options->clnt_decrypt_opt)
+       decrypt_opt = vstralloc("client-decrypt-option=", options->clnt_decrypt_opt, ";", NULL);
+      else
+       decrypt_opt = stralloc("");
+    }
+    else if(options->encrypt == ENCRYPT_SERV_CUST) {
+      encrypt_opt = vstralloc("encrypt-serv-cust=", options->srv_encrypt, ";", NULL);
+      if(options->srv_decrypt_opt)
+       decrypt_opt = vstralloc("server-decrypt-option=", options->srv_decrypt_opt, ";", NULL);
+      else
+       decrypt_opt = stralloc("");
+    }
+    else {
+       encrypt_opt = stralloc("");
+       decrypt_opt = stralloc("");
+    }
+
     if(options->no_record) record_opt = "no-record;";
-    if(options->bsd_auth) bsd_opt = "bsd-auth;";
-#ifdef KRB4_SECURITY
-    if(options->krb4_auth) krb4_opt = "krb4-auth;";
-    if(options->kencrypt) kencrypt_opt = "kencrypt;";
-#endif
+    if(options->auth) auth_opt = vstralloc("auth=", options->auth, ";", NULL);
+       else auth_opt = stralloc("");
     if(options->createindex) index_opt = "index;";
 
     exclude_file_opt = stralloc("");
@@ -126,14 +144,20 @@ char *optionstr(option_t *options)
     }
     optstr = newvstralloc(optstr,
                          compress_opt,
+                         encrypt_opt,
+                         decrypt_opt,
                          record_opt,
-                         bsd_opt,
-                         krb4_opt,
-                         kencrypt_opt,
                          index_opt,
+                         auth_opt,
                          exclude_file_opt,
                          exclude_list_opt,
                          NULL);
+    amfree(compress_opt);
+    amfree(encrypt_opt);
+    amfree(decrypt_opt);
+    amfree(auth_opt);
+    amfree(exclude_file_opt);
+    amfree(exclude_list_opt);
     return optstr;
 }
 
@@ -155,23 +179,21 @@ char **argv;
 
     /* initialize */
 
-#ifdef KRB4_SECURITY
-    safe_fd(KEY_PIPE, 1);              /* XXX interface needs to be fixed */
-#else
-    safe_fd(-1, 0);
-#endif
-
+    safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT);
     safe_cd();
 
     set_pname("sendbackup");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     interactive = (argc > 1 && strcmp(argv[1],"-t") == 0);
     erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
     dbopen();
     startclock();
-    dbprintf(("%s: version %s\n", argv[0], version()));
+    dbprintf(("%s: version %s\n", get_pname(), version()));
 
     our_features = am_init_feature_set();
     our_feature_string = am_feature_to_string(our_features);
@@ -193,8 +215,6 @@ char **argv;
     dumpdate = NULL;
     stroptions = NULL;
 
-    /* parse dump request */
-
     for(; (line = agets(stdin)) != NULL; free(line)) {
        if(interactive) {
            fprintf(stderr, "%s> ", get_pname());
@@ -307,7 +327,7 @@ char **argv;
     dbprintf(("                     since %s\n", dumpdate));
     dbprintf(("                     options `%s'\n", stroptions));
 
-    for(i = 0; programs[i] != NULL; i++) {
+    for(i = 0; programs[i]; i++) {
        if (strcmp(programs[i]->name, prog) == 0) {
            break;
        }
@@ -319,42 +339,16 @@ char **argv;
 
     options = parse_options(stroptions, disk, amdevice, g_options->features, 0);
 
-#ifdef KRB4_SECURITY
-    /* modification by BIS@BBN 4/25/2003:
-     * with the option processing changes in amanda 2.4.4, must change
-     * the conditional from krb4_auth to options->krb4_auth */
-    if(options->krb4_auth) {
-       if(read(KEY_PIPE, session_key, sizeof session_key) 
-          != sizeof session_key) {
-         error("ERROR [%s: could not read session key]", get_pname());
-       }
-    }
-#endif
-
     if(!interactive) {
-      data_socket = stream_server(&data_port, STREAM_BUFSIZE, -1);
-      if(data_socket < 0) {
-       error("ERROR [%s: could not create data socket: %s]",
-             get_pname(), strerror(errno));
-      }
-      mesg_socket = stream_server(&mesg_port, -1, -1);
-      if(mesg_socket < 0) {
-       error("ERROR [%s: could not create mesg socket: %s]",
-             get_pname(), strerror(errno));
-      }
-    }
-    if (!interactive && options->createindex) {
-      index_socket = stream_server(&index_port, -1, -1);
-      if(index_socket < 0) {
-       error("ERROR [%s: could not create index socket: %s]",
-             get_pname(), strerror(errno));
-      }
-    } else {
-      index_port = -1;
+       datafd = DATA_FD_OFFSET + 0;
+       mesgfd = DATA_FD_OFFSET + 1;
+       indexfd = DATA_FD_OFFSET + 2;
     }
+    if (!options->createindex)
+       indexfd = -1;
 
     printf("CONNECT DATA %d MESG %d INDEX %d\n",
-          data_port, mesg_port, index_port);
+          datafd, mesgfd, indexfd);
     printf("OPTIONS ");
     if(am_has_feature(g_options->features, fe_rep_options_features)) {
        printf("features=%s;", our_feature_string);
@@ -367,91 +361,34 @@ char **argv;
     }
     printf("\n");
     fflush(stdout);
-    freopen("/dev/null", "w", stdout);
-
-    if (options->createindex)
-      dbprintf(("%s: waiting for connect on %d, then %d, then %d\n",
-               debug_prefix_time(NULL), data_port, mesg_port, index_port));
-    else
-      dbprintf(("%s: waiting for connect on %d, then %d\n",
-               debug_prefix_time(NULL), data_port, mesg_port));
-
-    if(interactive) {
-      if((dataf = open("/dev/null", O_RDWR)) < 0) {
-       error("ERROR [%s: open of /dev/null for debug data stream: %s]",
-             get_pname(), strerror(errno));
-      }
-      mesgf = 2;
-    } else {
-      dataf = stream_accept(data_socket, TIMEOUT, -1, -1);
-      if(dataf == -1) {
-       dbprintf(("%s: timeout on data port %d\n",
-                 debug_prefix_time(NULL), data_port));
-      }
-      mesgf = stream_accept(mesg_socket, TIMEOUT, -1, -1);
-      if(mesgf == -1) {
-        dbprintf(("%s: timeout on mesg port %d\n",
-                 debug_prefix_time(NULL), mesg_port));
-      }
+    if (freopen("/dev/null", "w", stdout) == NULL) {
+       dbprintf(("%s: error redirecting stdout to /dev/null: %s\n",
+           debug_prefix_time(NULL), mesgfd, strerror(errno)));
+        exit(1);
     }
+
     if(interactive) {
-      indexf = 1;
-    } else if (options->createindex) {
-      indexf = stream_accept(index_socket, TIMEOUT, -1, -1);
-      if (indexf == -1) {
-       dbprintf(("%s: timeout on index port %d\n",
-                 debug_prefix_time(NULL), index_port));
+      if((datafd = open("/dev/null", O_RDWR)) < 0) {
+       s = strerror(errno);
+       error("ERROR [%s: open of /dev/null for debug data stream: %s]\n",
+                 get_pname(), s);
       }
+      mesgfd = 2;
+      indexfd = 1;
     }
 
     if(!interactive) {
-      if(dataf == -1 || mesgf == -1 || (options->createindex && indexf == -1)) {
+      if(datafd == -1 || mesgfd == -1 || (options->createindex && indexfd == -1)) {
         dbclose();
         exit(1);
       }
     }
 
-    dbprintf(("%s: got all connections\n", debug_prefix_time(NULL)));
-
-#ifdef KRB4_SECURITY
-    if(!interactive) {
-      /* modification by BIS@BBN 4/25/2003:
-       * with the option processing changes in amanda 2.4.4, must change
-       * the conditional from krb4_auth to options->krb4_auth */
-      if (options->krb4_auth) {
-        if(kerberos_handshake(dataf, session_key) == 0) {
-           dbprintf(("%s: kerberos_handshake on data socket failed\n",
-                     debug_prefix_time(NULL)));
-           dbclose();
-           exit(1);
-        } else {
-           dbprintf(("%s: kerberos_handshake on data socket succeeded\n",
-                     debug_prefix_time(NULL)));
-
-       }
-
-        if(kerberos_handshake(mesgf, session_key) == 0) {
-           dbprintf(("%s: kerberos_handshake on mesg socket failed\n",
-                     debug_prefix_time(NULL)));
-           dbclose();
-           exit(1);
-        } else {
-           dbprintf(("%s: kerberos_handshake on mesg socket succeeded\n",
-                     debug_prefix_time(NULL)));
-
-       }
-
-        dbprintf(("%s: kerberos handshakes succeeded!\n",
-                 debug_prefix_time(NULL)));
-      }
-    }
-#endif
-
     if(!interactive) {
       /* redirect stderr */
-      if(dup2(mesgf, 2) == -1) {
-         dbprintf(("%s: error redirecting stderr: %s\n",
-                   debug_prefix(NULL), strerror(errno)));
+      if(dup2(mesgfd, 2) == -1) {
+         dbprintf(("%s: error redirecting stderr to fd %d: %s\n",
+             debug_prefix_time(NULL), mesgfd, strerror(errno)));
          dbclose();
          exit(1);
       }
@@ -461,9 +398,11 @@ char **argv;
       error("error [opening mesg pipe: %s]", strerror(errno));
     }
 
-    program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate,
-                         dataf, mesgpipe[1], indexf);
+    program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate, datafd, mesgpipe[1],
+                         indexfd);
+    dbprintf(("%s: started backup\n", debug_prefix_time(NULL)));
     parse_backup_messages(mesgpipe[0]);
+    dbprintf(("%s: parsed backup messages\n", debug_prefix_time(NULL)));
 
     amfree(prog);
     amfree(disk);
@@ -508,7 +447,7 @@ int pid;
 {
     if(pid == dumppid) return program->backup_name;
     if(pid == comppid) return "compress";
-    if(pid == encpid)  return "kencrypt";
+    if(pid == encpid) return "encrypt";
     if(pid == indexpid) return "index";
     return "unknown";
 }
@@ -588,10 +527,10 @@ amwait_t w;
     }
 
     if(ret == 0) {
-       ap_snprintf(number, sizeof(number), "%d", sig);
+       snprintf(number, sizeof(number), "%d", sig);
        thiserr = vstralloc(str, " got signal ", number, NULL);
     } else {
-       ap_snprintf(number, sizeof(number), "%d", ret);
+       snprintf(number, sizeof(number), "%d", ret);
        thiserr = vstralloc(str, " returned ", number, NULL);
     }
 
@@ -609,7 +548,7 @@ amwait_t w;
 
 /* Send header info to the message file.
 */
-void write_tapeheader()
+void info_tapeheader()
 {
     fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name);
 
@@ -641,7 +580,7 @@ int stdoutfd, stderrfd;
     int pid, inpipe[2];
 
     dbprintf(("%s: forking function %s in pipeline\n",
-             debug_prefix_time(NULL), fname));
+       debug_prefix_time(NULL), fname));
 
     if(pipe(inpipe) == -1) {
        error("error [open pipe to %s: %s]", fname, strerror(errno));
@@ -658,13 +597,16 @@ int stdoutfd, stderrfd;
        aclose(inpipe[1]);      /* close output side of pipe */
 
        if(dup2(inpipe[0], 0) == -1) {
-           error("error [dup2 0 %s: dup2 in: %s]", fname, strerror(errno));
+           error("error [fork %s: dup2(%d, in): %s]",
+                 fname, inpipe[0], strerror(errno));
        }
        if(dup2(stdoutfd, 1) == -1) {
-           error("error [dup2 1 %s: dup2 out: %s]", fname, strerror(errno));
+           error("error [fork %s: dup2(%d, out): %s]",
+                 fname, stdoutfd, strerror(errno));
        }
        if(dup2(stderrfd, 2) == -1) {
-           error("error [dup2 2 %s: dup2 err: %s]", fname, strerror(errno));
+           error("error [fork %s: dup2(%d, err): %s]",
+                 fname, stderrfd, strerror(errno));
        }
 
        func();
@@ -731,6 +673,7 @@ char *str;
     return d;
 }
 
+
 static void process_dumpline(str)
 char *str;
 {
@@ -803,13 +746,7 @@ char *str;
 
 static volatile int index_finished = 0;
 
-static void index_closed(sig)
-int sig;
-{
-  index_finished = 1;
-}
-
-void save_fd(fd, min)
+static void save_fd(fd, min)
 int *fd, min;
 {
   int origfd = *fd;
@@ -818,19 +755,18 @@ int *fd, min;
     int newfd = dup(*fd);
     if (newfd == -1)
       dbprintf(("%s: unable to save file descriptor [%s]\n",
-               debug_prefix(NULL), strerror(errno)));
+       debug_prefix_time(NULL), strerror(errno)));
     *fd = newfd;
   }
   if (origfd != *fd)
     dbprintf(("%s: dupped file descriptor %i to %i\n",
-             debug_prefix(NULL), origfd, *fd));
+      debug_prefix_time(NULL), origfd, *fd));
 }
 
 void start_index(createindex, input, mesg, index, cmd)
 int createindex, input, mesg, index;
 char *cmd;
 {
-  struct sigaction act, oact;
   int pipefd[2];
   FILE *pipe_fp;
   int exitcode;
@@ -873,31 +809,21 @@ char *cmd;
     }
   }
 
-  /* set up a signal handler for SIGPIPE for when the pipe is finished
-     creating the index file */
-  /* at that point we obviously want to stop writing to it */
-  act.sa_handler = index_closed;
-  sigemptyset(&act.sa_mask);
-  act.sa_flags = 0;
-  if (sigaction(SIGPIPE, &act, &oact) != 0) {
-    error("couldn't set index SIGPIPE handler [%s]", strerror(errno));
-  }
-
   if ((pipe_fp = popen(cmd, "w")) == NULL) {
     error("couldn't start index creator [%s]", strerror(errno));
   }
 
   dbprintf(("%s: started index creator: \"%s\"\n",
-           debug_prefix_time(NULL), cmd));
+    debug_prefix_time(NULL), cmd));
   while(1) {
     char buffer[BUFSIZ], *ptr;
     int bytes_read;
     int bytes_written;
     int just_written;
 
-    bytes_read = read(0, buffer, sizeof(buffer));
-    if ((bytes_read < 0) && (errno == EINTR))
-      continue;
+    do {
+       bytes_read = read(0, buffer, sizeof(buffer));
+    } while ((bytes_read < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 
     if (bytes_read < 0) {
       error("index tee cannot read [%s]", strerror(errno));
@@ -909,36 +835,31 @@ char *cmd;
     /* write the stuff to the subprocess */
     ptr = buffer;
     bytes_written = 0;
-    while (bytes_read > bytes_written && !index_finished) {
-      just_written = write(fileno(pipe_fp), ptr, bytes_read - bytes_written);
-      if (just_written < 0) {
-         /* the signal handler may have assigned to index_finished
-          * just as we waited for write() to complete. */
-         if (!index_finished) {
-             dbprintf(("%s: index tee cannot write to index creator [%s]\n",
-                       debug_prefix_time(NULL), strerror(errno)));
-             index_finished = 1;
+    just_written = fullwrite(fileno(pipe_fp), ptr, bytes_read);
+    if (just_written < 0) {
+       /* the signal handler may have assigned to index_finished
+        * just as we waited for write() to complete.
+        */
+       if (errno != EPIPE) {
+           dbprintf(("%s: index tee cannot write to index creator [%s]\n",
+                           debug_prefix_time(NULL), strerror(errno)));
        }
-      } else {
+    } else {
        bytes_written += just_written;
        ptr += just_written;
-      }
     }
 
     /* write the stuff to stdout, ensuring none lost when interrupt
        occurs */
     ptr = buffer;
     bytes_written = 0;
-    while (bytes_read > bytes_written) {
-      just_written = write(3, ptr, bytes_read - bytes_written);
-      if ((just_written < 0) && (errno == EINTR))
-       continue;
-      if (just_written < 0) {
+    just_written = fullwrite(3, ptr, bytes_read);
+    if (just_written < 0) {
        error("index tee cannot write [%s]", strerror(errno));
-      } else {
+       /* NOTREACHED */
+    } else {
        bytes_written += just_written;
        ptr += just_written;
-      }
     }
   }
 
@@ -948,7 +869,7 @@ char *cmd;
   /* check the exit code of the pipe and moan if not 0 */
   if ((exitcode = pclose(pipe_fp)) != 0) {
     dbprintf(("%s: index pipe returned %d\n",
-             debug_prefix_time(NULL), exitcode));
+      debug_prefix_time(NULL), exitcode));
   } else {
     dbprintf(("%s: index created successfully\n", debug_prefix_time(NULL)));
   }
@@ -962,7 +883,3 @@ extern backup_program_t dump_program, gnutar_program;
 backup_program_t *programs[] = {
   &dump_program, &gnutar_program, NULL
 };
-
-#ifdef KRB4_SECURITY
-#include "sendbackup-krb4.c"
-#endif
index e20ca0d41f58cedaff60538c33e3fcf52312cb1e..ee2a836a0af3b97008ed93a3c00e6179ddf800f5 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendbackup.h,v 1.11.4.1.6.3 2002/03/31 21:01:32 jrjackson Exp $
+ * $Id: sendbackup.h,v 1.18 2005/12/09 03:22:52 paddy_s Exp $
  *
  * a few common decls for the sendbackup-* sources
  */
@@ -32,8 +32,7 @@
 #include "pipespawn.h"
 #include "client_util.h"
 
-void write_tapeheader P((void));
-
+void info_tapeheader P((void));
 void start_index P((int createindex, int input, int mesg, 
                    int index, char *cmd));
 
@@ -69,7 +68,7 @@ typedef struct regex_s {
 #define AM_SIZE_RE(re,s)       {(re), __LINE__, (s), DMP_SIZE}
 #define AM_ERROR_RE(re)                {(re), __LINE__, 0, DMP_ERROR}
 
-extern int  comppid, dumppid, tarpid;
+extern int  comppid, dumppid, encpid, tarpid;
 extern int indexpid;
 extern option_t *options;
 
index 63020e5267782a6fc8482b64db2397a3eb7041cb..184409cd380132ec4098e3310c0af6760b521bd0 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendsize.c,v 1.97.2.13.4.6.2.23.2.5 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: sendsize.c,v 1.152 2006/03/09 16:51:41 martinea Exp $
  *
  * send estimated backup sizes using dump
  */
@@ -80,6 +80,7 @@ typedef struct disk_estimates_s {
     char *dirname;
     char *program;
     char *calcprog;
+    int program_is_wrapper;
     int spindle;
     pid_t child;
     int done;
@@ -95,13 +96,15 @@ static g_option_t *g_options = NULL;
 
 /* local functions */
 int main P((int argc, char **argv));
-void add_diskest P((char *disk, char *amdevice, int level, int spindle,
-                   char *prog, char *calcprog, option_t *options));
+void add_diskest P((char *disk, char *amdevice, int level, int spindle, 
+                   int program_is_wrapper, char *prog, char *calcprog,
+                   option_t *options));
 void calc_estimates P((disk_estimates_t *est));
 void free_estimates P((disk_estimates_t *est));
 void dump_calc_estimates P((disk_estimates_t *));
 void smbtar_calc_estimates P((disk_estimates_t *));
 void gnutar_calc_estimates P((disk_estimates_t *));
+void wrapper_calc_estimates P((disk_estimates_t *));
 void generic_calc_estimates P((disk_estimates_t *));
 
 
@@ -112,6 +115,7 @@ char **argv;
     int level, spindle;
     char *prog, *calcprog, *disk, *amdevice, *dumpdate;
     option_t *options = NULL;
+    int program_is_wrapper;
     disk_estimates_t *est;
     disk_estimates_t *est1;
     disk_estimates_t *est_prev;
@@ -133,6 +137,9 @@ char **argv;
 
     set_pname("sendsize");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
@@ -187,6 +194,18 @@ char **argv;
        skip_non_whitespace(s, ch);
        s[-1] = '\0';
 
+       program_is_wrapper=0;
+       if(strcmp(prog,"DUMPER")==0) {
+           program_is_wrapper=1;
+           skip_whitespace(s, ch);             /* find dumper name */
+           if (ch == '\0') {
+               goto err;                       /* no program */
+           }
+           prog = s - 1;
+           skip_non_whitespace(s, ch);
+           s[-1] = '\0';
+       }
+
        if(strncmp(prog, "CALCSIZE", 8) == 0) {
            skip_whitespace(s, ch);             /* find the program name */
            if(ch == '\0') {
@@ -286,7 +305,7 @@ char **argv;
            }
        }
 
-       add_diskest(disk, amdevice, level, spindle, prog, calcprog, options);
+       add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options);
        amfree(amdevice);
     }
     amfree(line);
@@ -417,8 +436,8 @@ char **argv;
     our_features = NULL;
     am_release_feature_set(g_options->features);
     g_options->features = NULL;
-    amfree(g_options->str);
     amfree(g_options->hostname);
+    amfree(g_options->str);
     amfree(g_options);
 
     malloc_size_2 = malloc_inuse(&malloc_hist_2);
@@ -442,9 +461,9 @@ char **argv;
 }
 
 
-void add_diskest(disk, amdevice, level, spindle, prog, calcprog, options)
+void add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options)
 char *disk, *amdevice, *prog, *calcprog;
-int level, spindle;
+int level, spindle, program_is_wrapper;
 option_t *options;
 {
     disk_estimates_t *newp, *curp;
@@ -461,6 +480,7 @@ option_t *options;
                free_sl(options->exclude_list);
                free_sl(options->include_file);
                free_sl(options->include_list);
+               amfree(options->auth);
                amfree(options->str);
                amfree(options);
            }
@@ -480,6 +500,7 @@ option_t *options;
        newp->calcprog = stralloc(calcprog);
     else
        newp->calcprog = NULL;
+    newp->program_is_wrapper = program_is_wrapper;
     newp->spindle = spindle;
     newp->est[level].needestimate = 1;
     newp->options = options;
@@ -512,6 +533,7 @@ disk_estimates_t *est;
        free_sl(est->options->include_file);
        free_sl(est->options->include_list);
        amfree(est->options->str);
+       amfree(est->options->auth);
        amfree(est->options);
     }
 }
@@ -528,6 +550,9 @@ disk_estimates_t *est;
              debug_prefix_time(NULL),
              est->amname, est->dirname, est->spindle));
 
+    if(est->program_is_wrapper ==  1)
+       wrapper_calc_estimates(est);
+    else
 #ifndef USE_GENERIC_CALCSIZE
     if(strcmp(est->program, "DUMP") == 0)
        dump_calc_estimates(est);
@@ -558,6 +583,47 @@ disk_estimates_t *est;
              est->amname, est->dirname, est->spindle));
 }
 
+/*
+ * ------------------------------------------------------------------------
+ *
+ */
+
+/* local functions */
+long getsize_dump P((char *disk, char *amdevice, int level, option_t *options));
+long getsize_smbtar P((char *disk, char *amdevice, int level, option_t *options));
+long getsize_gnutar P((char *disk, char *amdevice, int level,
+                      option_t *options, time_t dumpsince));
+long getsize_wrapper P((char *program, char *disk, char *amdevice, int level,
+                       option_t *options, time_t dumpsince));
+long handle_dumpline P((char *str));
+double first_num P((char *str));
+
+void wrapper_calc_estimates(est)
+disk_estimates_t *est;
+{
+  int level;
+  long size;
+
+  for(level = 0; level < DUMP_LEVELS; level++) {
+      if (est->est[level].needestimate) {
+         dbprintf(("%s: getting size via wrapper for %s level %d\n",
+                   debug_prefix_time(NULL), est->amname, level));
+         size = getsize_wrapper(est->program, est->amname, est->amdevice, level, est->options,
+                                est->est[level].dumpsince);
+
+         amflock(1, "size");
+
+         fseek(stdout, (off_t)0, SEEK_SET);
+
+         printf("%s %d SIZE %ld\n", est->amname, level, size);
+         fflush(stdout);
+
+         amfunlock(1, "size");
+      }
+  }
+}
+
+
 void generic_calc_estimates(est)
 disk_estimates_t *est;
 {
@@ -609,7 +675,6 @@ disk_estimates_t *est;
        my_argv[my_argc++] = stralloc("-I");
        my_argv[my_argc++] = file_include;
     }
-
     start_time = curclock();
 
     dbprintf(("%s: running cmd: %s", debug_prefix_time(NULL), my_argv[0]));
@@ -618,10 +683,10 @@ disk_estimates_t *est;
 
     for(level = 0; level < DUMP_LEVELS; level++) {
        if(est->est[level].needestimate) {
-           ap_snprintf(number, sizeof(number), "%d", level);
+           snprintf(number, sizeof(number), "%d", level);
            my_argv[my_argc++] = stralloc(number); 
            dbprintf((" %s", number));
-           ap_snprintf(number, sizeof(number),
+           snprintf(number, sizeof(number),
                        "%ld", (long)est->est[level].dumpsince);
            my_argv[my_argc++] = stralloc(number); 
            dbprintf((" %s", number));
@@ -632,7 +697,11 @@ disk_estimates_t *est;
 
     fflush(stderr); fflush(stdout);
 
-    nullfd = open("/dev/null", O_RDWR);
+    if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+       dbprintf(("Cannot access /dev/null : %s\n", strerror(errno)));
+       goto common_exit;
+    }
+
     calcpid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv);
     amfree(cmd);
 
@@ -662,6 +731,7 @@ disk_estimates_t *est;
              est->amname,
              walltime_str(timessub(curclock(), start_time))));
 
+common_exit:
     for(i = 0; i < my_argc; i++) {
        amfree(my_argv[i]);
     }
@@ -669,20 +739,6 @@ disk_estimates_t *est;
 }
 
 
-/*
- * ------------------------------------------------------------------------
- *
- */
-
-/* local functions */
-void dump_calc_estimates P((disk_estimates_t *est));
-long getsize_dump P((char *disk, char *amdevice, int level, option_t *options));
-long getsize_smbtar P((char *disk, char *amdevice, int level, option_t *options));
-long getsize_gnutar P((char *disk, char *amdevice, int level,
-                      option_t *options, time_t dumpsince));
-long handle_dumpline P((char *str));
-double first_num P((char *str));
-
 void dump_calc_estimates(est)
 disk_estimates_t *est;
 {
@@ -805,10 +861,6 @@ regex_t re_size[] = {
     {"xfsdump: estimated dump size: [0-9][0-9]* bytes", 1},  /* Irix 6.2 xfs */
 #endif
 
-#ifdef USE_QUICK_AND_DIRTY_ESTIMATES
-    {"amqde estimate: [0-9][0-9]* kb", 1024},                      /* amqde */
-#endif
-    
 #ifdef GNUTAR
     {"Total bytes written: [0-9][0-9]*", 1},               /* Gnutar client */
 #endif
@@ -847,7 +899,7 @@ long getsize_dump(disk, amdevice, level, options)
     int s;
     times_t start_time;
 
-    ap_snprintf(level_str, sizeof(level_str), "%d", level);
+    snprintf(level_str, sizeof(level_str), "%d", level);
 
     device = amname_to_devname(amdevice);
     fstype = amname_to_fstype(amdevice);
@@ -858,7 +910,15 @@ long getsize_dump(disk, amdevice, level, options)
     cmd = vstralloc(libexecdir, "/rundump", versionsuffix(), NULL);
     rundump_cmd = stralloc(cmd);
 
-    stdoutfd = nullfd = open("/dev/null", O_RDWR);
+    if ((stdoutfd = nullfd = open("/dev/null", O_RDWR)) == -1) {
+       dbprintf(("getsize_dump could not open /dev/null: %s\n",
+                 strerror(errno)));
+       amfree(cmd);
+       amfree(rundump_cmd);
+       amfree(fstype);
+       amfree(device);
+       return(-1);
+    }
     pipefd[0] = pipefd[1] = killctl[0] = killctl[1] = -1;
     pipe(pipefd);
 
@@ -968,6 +1028,7 @@ long getsize_dump(disk, amdevice, level, options)
        amfree(rundump_cmd);
        amfree(device);
        amfree(name);
+       amfree(fstype);
        return -1;
     default:
        break; 
@@ -1095,16 +1156,19 @@ long getsize_dump(disk, amdevice, level, options)
        dbprintf(("%s: no size line match in %s%s output for \"%s\"\n",
                  debug_prefix(NULL), cmd, name, disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
+       dbprintf(("%s: Run %s%s manually to check for errors\n",
+                   debug_prefix(NULL), cmd, name));
     } else if(size == 0 && level == 0) {
        dbprintf(("%s: possible %s%s problem -- is \"%s\" really empty?\n",
                  debug_prefix(NULL), cmd, name, disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
-    }
-    dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
+    } else {
+           dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
              debug_prefix(NULL),
              disk,
              level,
              size));
+    }
 
     if (killctl[1] != -1) {
        dbprintf(("%s: asking killpgrp to terminate\n",
@@ -1238,7 +1302,19 @@ long getsize_smbtar(disk, amdevice, level, optionns)
        amfree(error_pn);
        error("cannot make share name of %s", share);
     }
-    nullfd = open("/dev/null", O_RDWR);
+    if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+       memset(user_and_password, '\0', lpass);
+       amfree(user_and_password);
+       if(domain) {
+           memset(domain, '\0', strlen(domain));
+           amfree(domain);
+       }
+       set_pname(error_pn);
+       amfree(error_pn);
+       amfree(sharename);
+       error("could not open /dev/null: %s\n",
+             strerror(errno));
+    }
 
 #if SAMBA_VERSION >= 2
     if (level == 0)
@@ -1411,7 +1487,7 @@ time_t dumpsince;
            if(ch == '/' || isspace(ch)) s[-1] = '_';
        }
 
-       ap_snprintf(number, sizeof(number), "%d", level);
+       snprintf(number, sizeof(number), "%d", level);
        incrname = vstralloc(basename, "_", number, ".new", NULL);
        unlink(incrname);
 
@@ -1423,7 +1499,7 @@ time_t dumpsince;
        baselevel = level;
        while (in == NULL) {
            if (--baselevel >= 0) {
-               ap_snprintf(number, sizeof(number), "%d", baselevel);
+               snprintf(number, sizeof(number), "%d", baselevel);
                inputname = newvstralloc(inputname,
                                         basename, "_", number, NULL);
            } else {
@@ -1484,7 +1560,7 @@ time_t dumpsince;
 #endif
 
     gmtm = gmtime(&dumpsince);
-    ap_snprintf(dumptimestr, sizeof(dumptimestr),
+    snprintf(dumptimestr, sizeof(dumptimestr),
                "%04d-%02d-%02d %2d:%02d:%02d GMT",
                gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
                gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
@@ -1493,22 +1569,6 @@ time_t dumpsince;
 
 
 
-#ifdef USE_QUICK_AND_DIRTY_ESTIMATES
-    ap_snprintf(dumptimestr, sizeof(dumptimestr), "%ld", dumpsince);
-
-    cmd = vstralloc(libexecdir, "/", "amqde", versionsuffix(), NULL);
-
-    my_argv[i++] = vstralloc(libexecdir, "/", "amqde", versionsuffix(), NULL);
-    my_argv[i++] = "-s";
-    my_argv[i++] = dumptimestr;
-    if(file_exclude) { /* at present, this is not used... */
-       my_argv[i++] = "-x";
-       my_argv[i++] = file_exclude;
-    }
-    /* [XXX] need to also consider implementation of --files-from */
-    my_argv[i++] = dirname;
-    my_argv[i++] = NULL;
-#else
 #ifdef GNUTAR
     cmd = vstralloc(libexecdir, "/", "runtar", versionsuffix(), NULL);
 
@@ -1555,7 +1615,6 @@ time_t dumpsince;
     else {
        my_argv[i++] = ".";
     }
-#endif /* USE_QUICK_AND_DIRTY_ESTIMATES */
     my_argv[i++] = NULL;
 
     start_time = curclock();
@@ -1630,6 +1689,134 @@ common_exit:
 }
 #endif
 
+long getsize_wrapper(program, disk, amdevice, level, options, dumpsince)
+char *program, *disk, *amdevice;
+int level;
+option_t *options;
+time_t dumpsince;
+{
+    int pipefd[2], nullfd, dumppid;
+    long size;
+    FILE *dumpout;
+    char *line = NULL;
+    char *cmd = NULL;
+    char dumptimestr[80];
+    struct tm *gmtm;
+    int  i, j;
+    char *argvchild[10];
+    char *newoptstr = NULL;
+    long size1, size2;
+    times_t start_time;
+
+    gmtm = gmtime(&dumpsince);
+    snprintf(dumptimestr, sizeof(dumptimestr),
+               "%04d-%02d-%02d %2d:%02d:%02d GMT",
+               gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
+               gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
+
+    cmd = vstralloc(DUMPER_DIR, "/", program, NULL);
+
+    i=0;
+    argvchild[i++] = program;
+    argvchild[i++] = "estimate";
+    if(level == 0)
+       argvchild[i++] = "full";
+    else {
+       char levelstr[NUM_STR_SIZE];
+       snprintf(levelstr,sizeof(levelstr),"%d",level);
+       argvchild[i++] = "level";
+       argvchild[i++] = levelstr;
+    }
+    argvchild[i++] = amdevice;
+    newoptstr = vstralloc(options->str,"estimate-direct;", NULL);
+    argvchild[i++] = newoptstr;
+    argvchild[i] = NULL;
+
+    dbprintf(("%s: running %s", debug_prefix_time(NULL), cmd));
+    for(j = 1; j < i; j++) {
+       dbprintf((" %s", argvchild[j]));
+    }
+    dbprintf(("\n"));
+    nullfd = open("/dev/null", O_RDWR);
+    pipe(pipefd);
+
+    start_time = curclock();
+
+    switch(dumppid = fork()) {
+    case -1:
+      size = -1;
+      goto common_exit;
+    default:
+      break; /* parent */
+    case 0:
+      dup2(nullfd, 0);
+      dup2(nullfd, 2);
+      dup2(pipefd[1], 1);
+      aclose(pipefd[0]);
+
+      execve(cmd, argvchild, safe_env());
+      error("exec %s failed: %s", cmd, strerror(errno));
+    }
+    amfree(newoptstr);
+
+    aclose(pipefd[1]);
+    dumpout = fdopen(pipefd[0],"r");
+
+    for(size = -1; (line = agets(dumpout)) != NULL; free(line)) {
+       dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
+       i = sscanf(line,"%ld %ld",&size1, &size2);
+       if(i == 2) {
+           size = size1 * size2;
+       }
+       if(size > -1) {
+           amfree(line);
+           if((line = agets(dumpout)) != NULL) {
+               dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
+           }
+           break;
+       }
+    }
+    amfree(line);
+
+    dbprintf(("%s: .....\n", debug_prefix_time(NULL)));
+    dbprintf(("%s: estimate time for %s level %d: %s\n",
+             debug_prefix(NULL),
+             amdevice,
+             level,
+             walltime_str(timessub(curclock(), start_time))));
+    if(size == -1) {
+       dbprintf(("%s: no size line match in %s output for \"%s\"\n",
+                 debug_prefix(NULL), cmd, disk));
+       dbprintf(("%s: .....\n", debug_prefix(NULL)));
+    } else if(size == 0 && level == 0) {
+       dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n",
+                 debug_prefix(NULL), cmd, disk));
+       dbprintf(("%s: .....\n", debug_prefix(NULL)));
+    }
+    dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
+             debug_prefix(NULL),
+             amdevice,
+             level,
+             size));
+
+    kill(-dumppid, SIGTERM);
+
+    dbprintf(("%s: waiting for %s \"%s\" child\n",
+             debug_prefix_time(NULL), cmd, disk));
+    wait(NULL);
+    dbprintf(("%s: after %s \"%s\" wait\n",
+             debug_prefix_time(NULL), cmd, disk));
+
+    aclose(nullfd);
+    afclose(dumpout);
+
+common_exit:
+
+    amfree(cmd);
+    amfree(newoptstr);
+    return size;
+}
+
 
 double first_num(str)
 char *str;
index 4d60148e17d3f86cbd4ec0c72397797571c91f48..d0ed70f744b5d93eff0b0645c9770cf4c46d20b4 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: versionsuffix.c,v 1.6.12.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: versionsuffix.c,v 1.8 2005/09/20 21:32:25 jrjackson Exp $
  *
  * prints the (possibly empty) suffix appended to amanda program names
  */
 #include "amanda.h"
 #include "version.h"
 
+int main P((void));
+
 int main()
 {
        safe_fd(-1, 0);
index 87e12e9b5efcc510d5279bc0bda96a47eb06b90e..1d237ead48c7a89a7e5873650aada6b3155972ba 100644 (file)
@@ -8,36 +8,41 @@ REGsrcdir = $(srcdir)/$(REGDIR)
 INCLUDES = -I$(REGsrcdir)
 
 libamanda_la_SOURCES = \
-       alloc.c         amflock.c       clock.c         debug.c         \
-       dgram.c         error.c         file.c          fileheader.c    \
-       amfeatures.c    match.c                                         \
-       protocol.c      regcomp.c       regerror.c      regexec.c       \
-       regfree.c       security.c      statfs.c        stream.c        \
-       token.c         util.c          versuff.c       version.c       \
-        pipespawn.c    sl.c
+       alloc.c         amflock.c       \
+       bsd-security.c  \
+       clock.c         \
+       debug.c         dgram.c         \
+       event.c         error.c         \
+       amfeatures.c    \
+       file.c          fileheader.c    \
+       krb4-security.c krb5-security.c \
+       match.c         \
+       packet.c        pipespawn.c     protocol.c      \
+       regcomp.c       regerror.c      regexec.c       regfree.c       \
+       rsh-security.c  \
+       security.c      sl.c            ssh-security.c  statfs.c        \
+       stream.c        tapelist.c      \
+       token.c         \
+       util.c          \
+       versuff.c       version.c
 
 libamanda_la_LIBADD =  @LTLIBOBJS@ @LTALLOCA@
 libamanda_la_LDFLAGS =  -release $(VERSION)
 
-noinst_HEADERS =       amanda.h        arglist.h       \
-                       clock.h         dgram.h         \
-                       amfeatures.h    protocol.h      \
-                       statfs.h        stream.h        \
-                       token.h         version.h       \
-                       amregex.h       fileheader.h    \
-                       util.h          pipespawn.h     \
-                       sl.h
-
-STANDARD_COMMON_STUFF_NOT_FILE = \
-       alloc.$(OBJEXT) \
-       clock.$(OBJEXT) \
-       debug.$(OBJEXT) \
-       error.$(OBJEXT) \
-       util.$(OBJEXT)
-
-STANDARD_COMMON_STUFF = \
-       $(STANDARD_COMMON_STUFF_NOT_FILE) \
-       file.$(OBJEXT)
+noinst_HEADERS =       amanda.h        amregex.h       arglist.h       \
+                       clock.h         \
+                       dgram.h         \
+                       event.h         \
+                       amfeatures.h    \
+                       packet.h        pipespawn.h     protocol.h      \
+                       queue.h         \
+                       sl.h            security.h      statfs.h        \
+                       stream.h        \
+                       tapelist.h      \
+                       token.h         \
+                       util.h          \
+                       version.h       \
+                       fileheader.h
 
 .sh:
        cat $< > $@
@@ -45,12 +50,10 @@ STANDARD_COMMON_STUFF = \
 
 EXTRA_PROGRAMS = genversion $(TEST_PROGS)
 
-EXTRA_DIST = krb4-security.c   krb4-security.h
-
 genversion_SOURCES = genversion.c
-genversion_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF) versuff.o
+genversion_LDADD = $(libamanda_la_LIBADD) versuff.o
 
-genversion.o: genversion.h
+genversion.@OBJEXT@: genversion.h
 genversion.h: $(top_builddir)/config.status
        -rm -f $@ $@.new
        echo '#define CC "$(CC)"' > $@.new
@@ -75,11 +78,11 @@ REGEXHSRC = $(REGsrcdir)/regex2.h \
                $(REGsrcdir)/regfree.c
 
 # these are used for testing only:
-TEST_PROGS = statfs token file security amfeatures
+TEST_PROGS = statfs token file bsdsecurity amfeatures
 
 CLEANFILES = regex.h regcomp.ih engine.ih regerror.ih *.test.c
 
-DISTCLEANFILES = version.c genversion
+DISTCLEANFILES = version.c genversion.h genversion amanda-int.h
 
 regex.h: $(REGEXHSRC) $(REGsrcdir)/mkh
        sh $(REGsrcdir)/mkh -o -i _REGEX_H_ $(REGEXHSRC) >$@
@@ -95,6 +98,17 @@ regerror.ih: $(REGsrcdir)/regerror.c $(REGsrcdir)/mkh
 
 # used for testing only
 
+STANDARD_COMMON_STUFF_NOT_FILE = \
+       alloc.$(OBJEXT) \
+       clock.$(OBJEXT) \
+       debug.$(OBJEXT) \
+       error.$(OBJEXT) \
+       util.$(OBJEXT)
+
+STANDARD_COMMON_STUFF = \
+       $(STANDARD_COMMON_STUFF_NOT_FILE) \
+       file.$(OBJEXT)
+
 statfs_SOURCES = statfs.test.c
 statfs_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
 
@@ -104,8 +118,19 @@ token_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
 file_SOURCES = file.test.c
 file_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF_NOT_FILE)
 
-security_SOURCES = security.test.c
-security_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
+bsdsecurity_SOURCES = bsd-security.test.c
+bsdsecurity_LDADD = $(libamanda_a_LIBADD) \
+                   alloc.$(OBJEXT) \
+                   clock.$(OBJEXT) \
+                   debug.$(OBJEXT) \
+                   dgram.$(OBJEXT) \
+                   error.$(OBJEXT) \
+                   event.$(OBJEXT) \
+                   file.$(OBJEXT) \
+                   packet.$(OBJEXT) \
+                   security.$(OBJEXT) \
+                   ssh-security.$(OBJEXT) \
+                   versuff.$(OBJEXT)
 
 amfeatures_SOURCES = amfeatures.test.c
 amfeatures_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
index c06902efbf6e1b0914887a58a68bedc334f7c6e7..18faf64404f7d8c4f1b97a0204e123aab9159e2f 100644 (file)
@@ -17,7 +17,7 @@
 # Makefile for Amanda library.
 
 
-SOURCES = $(libamanda_la_SOURCES) $(amfeatures_SOURCES) $(file_SOURCES) $(genversion_SOURCES) $(security_SOURCES) $(statfs_SOURCES) $(token_SOURCES)
+SOURCES = $(libamanda_la_SOURCES) $(amfeatures_SOURCES) $(bsdsecurity_SOURCES) $(file_SOURCES) $(genversion_SOURCES) $(statfs_SOURCES) $(token_SOURCES)
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -47,7 +47,7 @@ subdir = common-src
 DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/versuff.c.in alloca.c getcwd.c \
        memmove.c mktime.c snprintf.c strcasecmp.c strerror.c \
-       strftime.c strncasecmp.c strstr.c waitpid.c
+       strftime.c strncasecmp.c strstr.c waitpid.c writev.c
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
        $(top_srcdir)/configure.in
@@ -66,14 +66,16 @@ am__installdirs = "$(DESTDIR)$(libdir)"
 libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libamanda_la_DEPENDENCIES = @LTLIBOBJS@ @LTALLOCA@
-am_libamanda_la_OBJECTS = alloc.lo amflock.lo clock.lo debug.lo \
-       dgram.lo error.lo file.lo fileheader.lo amfeatures.lo match.lo \
-       protocol.lo regcomp.lo regerror.lo regexec.lo regfree.lo \
-       security.lo statfs.lo stream.lo token.lo util.lo versuff.lo \
-       version.lo pipespawn.lo sl.lo
+am_libamanda_la_OBJECTS = alloc.lo amflock.lo bsd-security.lo clock.lo \
+       debug.lo dgram.lo event.lo error.lo amfeatures.lo file.lo \
+       fileheader.lo krb4-security.lo krb5-security.lo match.lo \
+       packet.lo pipespawn.lo protocol.lo regcomp.lo regerror.lo \
+       regexec.lo regfree.lo rsh-security.lo security.lo sl.lo \
+       ssh-security.lo statfs.lo stream.lo tapelist.lo token.lo \
+       util.lo versuff.lo version.lo
 libamanda_la_OBJECTS = $(am_libamanda_la_OBJECTS)
 am__EXEEXT_1 = statfs$(EXEEXT) token$(EXEEXT) file$(EXEEXT) \
-       security$(EXEEXT) amfeatures$(EXEEXT)
+       bsdsecurity$(EXEEXT) amfeatures$(EXEEXT)
 am_amfeatures_OBJECTS = amfeatures.test.$(OBJEXT)
 amfeatures_OBJECTS = $(am_amfeatures_OBJECTS)
 am__DEPENDENCIES_1 = @LTLIBOBJS@ @LTALLOCA@
@@ -81,16 +83,18 @@ am__DEPENDENCIES_2 = alloc.$(OBJEXT) clock.$(OBJEXT) debug.$(OBJEXT) \
        error.$(OBJEXT) util.$(OBJEXT)
 am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) file.$(OBJEXT)
 amfeatures_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3)
+am_bsdsecurity_OBJECTS = bsd-security.test.$(OBJEXT)
+bsdsecurity_OBJECTS = $(am_bsdsecurity_OBJECTS)
+bsdsecurity_DEPENDENCIES = alloc.$(OBJEXT) clock.$(OBJEXT) \
+       debug.$(OBJEXT) dgram.$(OBJEXT) error.$(OBJEXT) \
+       event.$(OBJEXT) file.$(OBJEXT) packet.$(OBJEXT) \
+       security.$(OBJEXT) ssh-security.$(OBJEXT) versuff.$(OBJEXT)
 am_file_OBJECTS = file.test.$(OBJEXT)
 file_OBJECTS = $(am_file_OBJECTS)
 file_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
 am_genversion_OBJECTS = genversion.$(OBJEXT)
 genversion_OBJECTS = $(am_genversion_OBJECTS)
-genversion_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \
-       versuff.o
-am_security_OBJECTS = security.test.$(OBJEXT)
-security_OBJECTS = $(am_security_OBJECTS)
-security_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3)
+genversion_DEPENDENCIES = $(am__DEPENDENCIES_1) versuff.o
 am_statfs_OBJECTS = statfs.test.$(OBJEXT)
 statfs_OBJECTS = $(am_statfs_OBJECTS)
 statfs_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3)
@@ -109,10 +113,10 @@ CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
        $(AM_LDFLAGS) $(LDFLAGS) -o $@
 SOURCES = $(libamanda_la_SOURCES) $(amfeatures_SOURCES) \
-       $(file_SOURCES) $(genversion_SOURCES) $(security_SOURCES) \
+       $(bsdsecurity_SOURCES) $(file_SOURCES) $(genversion_SOURCES) \
        $(statfs_SOURCES) $(token_SOURCES)
 DIST_SOURCES = $(libamanda_la_SOURCES) $(amfeatures_SOURCES) \
-       $(file_SOURCES) $(genversion_SOURCES) $(security_SOURCES) \
+       $(bsdsecurity_SOURCES) $(file_SOURCES) $(genversion_SOURCES) \
        $(statfs_SOURCES) $(token_SOURCES)
 HEADERS = $(noinst_HEADERS)
 ETAGS = etags
@@ -165,7 +169,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -177,9 +183,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -192,6 +201,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -254,10 +264,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -313,39 +326,43 @@ REGDIR = ../regex-src
 REGsrcdir = $(srcdir)/$(REGDIR)
 INCLUDES = -I$(REGsrcdir)
 libamanda_la_SOURCES = \
-       alloc.c         amflock.c       clock.c         debug.c         \
-       dgram.c         error.c         file.c          fileheader.c    \
-       amfeatures.c    match.c                                         \
-       protocol.c      regcomp.c       regerror.c      regexec.c       \
-       regfree.c       security.c      statfs.c        stream.c        \
-       token.c         util.c          versuff.c       version.c       \
-        pipespawn.c    sl.c
+       alloc.c         amflock.c       \
+       bsd-security.c  \
+       clock.c         \
+       debug.c         dgram.c         \
+       event.c         error.c         \
+       amfeatures.c    \
+       file.c          fileheader.c    \
+       krb4-security.c krb5-security.c \
+       match.c         \
+       packet.c        pipespawn.c     protocol.c      \
+       regcomp.c       regerror.c      regexec.c       regfree.c       \
+       rsh-security.c  \
+       security.c      sl.c            ssh-security.c  statfs.c        \
+       stream.c        tapelist.c      \
+       token.c         \
+       util.c          \
+       versuff.c       version.c
 
 libamanda_la_LIBADD = @LTLIBOBJS@ @LTALLOCA@
 libamanda_la_LDFLAGS = -release $(VERSION)
-noinst_HEADERS = amanda.h      arglist.h       \
-                       clock.h         dgram.h         \
-                       amfeatures.h    protocol.h      \
-                       statfs.h        stream.h        \
-                       token.h         version.h       \
-                       amregex.h       fileheader.h    \
-                       util.h          pipespawn.h     \
-                       sl.h
+noinst_HEADERS = amanda.h      amregex.h       arglist.h       \
+                       clock.h         \
+                       dgram.h         \
+                       event.h         \
+                       amfeatures.h    \
+                       packet.h        pipespawn.h     protocol.h      \
+                       queue.h         \
+                       sl.h            security.h      statfs.h        \
+                       stream.h        \
+                       tapelist.h      \
+                       token.h         \
+                       util.h          \
+                       version.h       \
+                       fileheader.h
 
-STANDARD_COMMON_STUFF_NOT_FILE = \
-       alloc.$(OBJEXT) \
-       clock.$(OBJEXT) \
-       debug.$(OBJEXT) \
-       error.$(OBJEXT) \
-       util.$(OBJEXT)
-
-STANDARD_COMMON_STUFF = \
-       $(STANDARD_COMMON_STUFF_NOT_FILE) \
-       file.$(OBJEXT)
-
-EXTRA_DIST = krb4-security.c   krb4-security.h
 genversion_SOURCES = genversion.c
-genversion_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF) versuff.o
+genversion_LDADD = $(libamanda_la_LIBADD) versuff.o
 REGEXHSRC = $(REGsrcdir)/regex2.h \
                $(REGsrcdir)/regcomp.c \
                $(REGsrcdir)/regexec.c \
@@ -354,19 +371,42 @@ REGEXHSRC = $(REGsrcdir)/regex2.h \
 
 
 # these are used for testing only:
-TEST_PROGS = statfs token file security amfeatures
+TEST_PROGS = statfs token file bsdsecurity amfeatures
 CLEANFILES = regex.h regcomp.ih engine.ih regerror.ih *.test.c
-DISTCLEANFILES = version.c
+DISTCLEANFILES = version.c genversion.h genversion amanda-int.h
 
 # used for testing only
+STANDARD_COMMON_STUFF_NOT_FILE = \
+       alloc.$(OBJEXT) \
+       clock.$(OBJEXT) \
+       debug.$(OBJEXT) \
+       error.$(OBJEXT) \
+       util.$(OBJEXT)
+
+STANDARD_COMMON_STUFF = \
+       $(STANDARD_COMMON_STUFF_NOT_FILE) \
+       file.$(OBJEXT)
+
 statfs_SOURCES = statfs.test.c
 statfs_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
 token_SOURCES = token.test.c
 token_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
 file_SOURCES = file.test.c
 file_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF_NOT_FILE)
-security_SOURCES = security.test.c
-security_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
+bsdsecurity_SOURCES = bsd-security.test.c
+bsdsecurity_LDADD = $(libamanda_a_LIBADD) \
+                   alloc.$(OBJEXT) \
+                   clock.$(OBJEXT) \
+                   debug.$(OBJEXT) \
+                   dgram.$(OBJEXT) \
+                   error.$(OBJEXT) \
+                   event.$(OBJEXT) \
+                   file.$(OBJEXT) \
+                   packet.$(OBJEXT) \
+                   security.$(OBJEXT) \
+                   ssh-security.$(OBJEXT) \
+                   versuff.$(OBJEXT)
+
 amfeatures_SOURCES = amfeatures.test.c
 amfeatures_LDADD = $(libamanda_la_LIBADD) $(STANDARD_COMMON_STUFF)
 all: all-am
@@ -436,15 +476,15 @@ libamanda.la: $(libamanda_la_OBJECTS) $(libamanda_la_DEPENDENCIES)
 amfeatures$(EXEEXT): $(amfeatures_OBJECTS) $(amfeatures_DEPENDENCIES) 
        @rm -f amfeatures$(EXEEXT)
        $(LINK) $(amfeatures_LDFLAGS) $(amfeatures_OBJECTS) $(amfeatures_LDADD) $(LIBS)
+bsdsecurity$(EXEEXT): $(bsdsecurity_OBJECTS) $(bsdsecurity_DEPENDENCIES) 
+       @rm -f bsdsecurity$(EXEEXT)
+       $(LINK) $(bsdsecurity_LDFLAGS) $(bsdsecurity_OBJECTS) $(bsdsecurity_LDADD) $(LIBS)
 file$(EXEEXT): $(file_OBJECTS) $(file_DEPENDENCIES) 
        @rm -f file$(EXEEXT)
        $(LINK) $(file_LDFLAGS) $(file_OBJECTS) $(file_LDADD) $(LIBS)
 genversion$(EXEEXT): $(genversion_OBJECTS) $(genversion_DEPENDENCIES) 
        @rm -f genversion$(EXEEXT)
        $(LINK) $(genversion_LDFLAGS) $(genversion_OBJECTS) $(genversion_LDADD) $(LIBS)
-security$(EXEEXT): $(security_OBJECTS) $(security_DEPENDENCIES) 
-       @rm -f security$(EXEEXT)
-       $(LINK) $(security_LDFLAGS) $(security_OBJECTS) $(security_LDADD) $(LIBS)
 statfs$(EXEEXT): $(statfs_OBJECTS) $(statfs_DEPENDENCIES) 
        @rm -f statfs$(EXEEXT)
        $(LINK) $(statfs_LDFLAGS) $(statfs_OBJECTS) $(statfs_LDADD) $(LIBS)
@@ -469,31 +509,40 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strncasecmp.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strstr.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/waitpid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/writev.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfeatures.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfeatures.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amflock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsd-security.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsd-security.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clock.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dgram.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileheader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genversion.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/krb4-security.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/krb5-security.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipespawn.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regerror.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexec.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regfree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsh-security.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssh-security.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statfs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statfs.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapelist.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@
@@ -708,7 +757,7 @@ uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES
        cat $< > $@
        chmod a+x $@
 
-genversion.o: genversion.h
+genversion.@OBJEXT@: genversion.h
 genversion.h: $(top_builddir)/config.status
        -rm -f $@ $@.new
        echo '#define CC "$(CC)"' > $@.new
index ce5d1b3ec5a684aca078da0d89d40f6df47c76d8..0a0cdef3555f72a6b29d115910fdcd533b0bee06 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: alloc.c,v 1.17.2.1.4.3.2.3.2.1 2004/08/31 12:46:06 martinea Exp $
+ * $Id: alloc.c,v 1.35 2005/12/21 19:07:49 paddy_s Exp $
  *
  * Memory allocators with error handling.  If the allocation fails,
  * errordump() is called, relieving the caller from checking the return
  */
 #include "amanda.h"
 #include "arglist.h"
+#include "queue.h"
+
+static char *internal_vstralloc P((const char *, va_list));
 
 /*
  *=====================================================================
  * debug_caller_loc -- keep track of all allocation callers
  *
- * char *debug_caller_loc(char *file, int line)
+ * const char *debug_caller_loc(const char *file, int line)
  *
  * entry:      file = source file
  *             line = source line
  *=====================================================================
  */
 
-char *
+const char *
 debug_caller_loc(file, line)
-    char *file;
+    const char *file;
     int line;
 {
     struct loc_str {
        char *str;
-       struct loc_str *next;
-    };
-    static struct loc_str *root = NULL;
-    struct loc_str *ls, *ls_last;
-    int len;
-    int size;
-    char *p;
-    static char *loc = NULL;
-    static int loc_size = 0;
-
-    if ((p = strrchr(file, '/')) == NULL) {
-       p = file;                               /* keep the whole name */
-    } else {
-       p++;                                    /* just the last path element */
-    }
-
-    len = strlen (p);
-    size = len + 1 + NUM_STR_SIZE + 1;
-    if (size > loc_size) {
-       size = ((size + 64 - 1) / 64) * 64;     /* might as well get a bunch */
-       /*
-        * We should free the previous loc area, but we have marked it
-        * as a non-leak and the library considers it an error to free
-        * such an area, so we just ignore it.  We probably grabbed
-        * enough the first time that this will not even happen.
-        */
-       loc = malloc (size);
-       if (loc == NULL) {
-           return "??";                        /* not much better than abort */
-       }
-       malloc_mark (loc);
-       loc_size = size;
-    }
-
-    strcpy (loc, p);
-    ap_snprintf(loc + len, 1 + NUM_STR_SIZE, "@%d", line);
-
-    for (ls_last = NULL, ls = root; ls != NULL; ls_last = ls, ls = ls->next) {
-       if (strcmp (loc, ls->str) == 0) {
-           break;
+       LIST_ENTRY(loc_str) le;
+    } *ls;
+    static LIST_HEAD(, loc_str) root = LIST_HEAD_INITIALIZER(root);
+    static char loc[256];      /* big enough for filename@lineno */
+    const char *p;
+
+    if ((p = strrchr(file, '/')) != NULL)
+       file = p + 1;                           /* just the last path element */
+
+    snprintf(loc, sizeof(loc), "%s@%d", file, line);
+
+    for (ls = LIST_FIRST(&root); ls != NULL; ls = LIST_NEXT(ls, le)) {
+       if (strcmp(loc, ls->str) == 0) {
+           if (ls != LIST_FIRST(&root)) {
+               /*
+                * This is a repeat and was not at the head of the list.
+                * Unlink it and move it to the front.
+                */
+               LIST_REMOVE(ls, le);
+               LIST_INSERT_HEAD(&root, ls, le);
+           }
+           return (ls->str);
        }
     }
 
-    if (ls == NULL) {
-       /*
-        * This is a new entry.  Put it at the head of the list.
-        */
-       ls = malloc (sizeof (*ls));
-       if (ls == NULL) {
-           return "??";                        /* not much better than abort */
-       }
-       malloc_mark (ls);
-       size = strlen (loc) + 1;
-       ls->str = malloc (size);
-       if (ls->str == NULL) {
-           free (ls);
-           return "??";                        /* not much better than abort */
-       }
-       malloc_mark (ls->str);
-       strcpy (ls->str, loc);
-       ls->next = root;
-       root = ls;
-    } else if (ls_last != NULL) {
-       /*
-        * This is a repeat and was not at the head of the list.
-        * Unlink it and move it to the front.
-        */
-       ls_last->next = ls->next;
-       ls->next = root;
-       root = ls;
-    } else {
-       /*
-        * This is a repeat but was already at the head of the list,
-        * so nothing else needs to be done.
-        */
+    /*
+     * This is a new entry.  Put it at the head of the list.
+     */
+    ls = malloc(sizeof(*ls));
+    if (ls == NULL)
+       return ("??");                  /* not much better than abort */
+    ls->str = malloc(strlen(loc) + 1);
+    if (ls->str == NULL) {
+       free(ls);
+       return ("??");                  /* not much better than abort */
     }
-    return ls->str;
+    strcpy(ls->str, loc);
+    malloc_mark(ls);
+    malloc_mark(ls->str);
+    LIST_INSERT_HEAD(&root, ls, le);
+    return (ls->str);
 }
 
 /*
@@ -208,7 +175,7 @@ debug_alloc_pop ()
  */
 void *
 debug_alloc(s, l, size)
-    char *s;
+    const char *s;
     int l;
     size_t size;
 {
@@ -216,7 +183,7 @@ debug_alloc(s, l, size)
 
     malloc_enter(debug_caller_loc(s, l));
     addr = (void *)malloc(max(size, 1));
-    if(addr == NULL) {
+    if (addr == NULL) {
        errordump("%s@%d: memory allocation failed (%u bytes requested)",
                  s ? s : "(unknown)",
                  s ? l : -1,
@@ -232,7 +199,7 @@ debug_alloc(s, l, size)
  */
 void *
 debug_newalloc(s, l, old, size)
-    char *s;
+    const char *s;
     int l;
     void *old;
     size_t size;
@@ -253,7 +220,7 @@ debug_newalloc(s, l, old, size)
  */
 char *
 debug_stralloc(s, l, str)
-    char *s;
+    const char *s;
     int l;
     const char *str;
 {
@@ -263,9 +230,28 @@ debug_stralloc(s, l, str)
     addr = debug_alloc(s, l, strlen(str) + 1);
     strcpy(addr, str);
     malloc_leave(debug_caller_loc(s, l));
-    return addr;
+    return (addr);
 }
 
+/* vstrextend -- Extends the existing string by appending the other 
+ * arguments. */
+arglist_function(char *vstrextend,
+                 char **,
+                 oldstr)
+{
+       char *keep = *oldstr;
+       va_list ap;
+
+       arglist_start(ap, oldstr);
+
+       if (*oldstr == NULL)
+               *oldstr = "";
+       *oldstr = internal_vstralloc(*oldstr, ap);
+        amfree(keep);
+
+       arglist_end(ap);
+        return *oldstr;
+}
 
 /*
  * internal_vstralloc - copies up to MAX_STR_ARGS strings into newly
@@ -354,7 +340,7 @@ arglist_function(char *debug_vstralloc, const char *, str)
  */
 char *
 debug_newstralloc(s, l, oldstr, newstr)
-    char *s;
+    const char *s;
     int l;
     char *oldstr;
     const char *newstr;
@@ -365,7 +351,7 @@ debug_newstralloc(s, l, oldstr, newstr)
     addr = debug_stralloc(s, l, newstr);
     amfree(oldstr);
     malloc_leave(debug_caller_loc(s, l));
-    return addr;
+    return (addr);
 }
 
 
@@ -392,45 +378,6 @@ arglist_function1(char *debug_newvstralloc,
 }
 
 
-/*
- * sbuf_man - static buffer manager.
- *
- * Manage a bunch of static buffer pointers.
- */
-void *sbuf_man(e_bufs, ptr)
-    void *e_bufs; /* XXX - I dont think this is right */
-    void *ptr;
-{
-       SBUF2_DEF(1) *bufs;
-       int slot;
-
-       bufs = e_bufs;
-
-       /* try and trap bugs */
-       assert(bufs->magic == SBUF_MAGIC);
-       assert(bufs->max > 0);
-
-       /* initialise first time through */
-       if(bufs->cur == -1)
-               for(slot=0; slot < bufs->max; slot++) {
-                       bufs->bufp[slot] = (void *)0;
-               } 
-
-       /* calculate the next slot */
-       slot = bufs->cur + 1;
-       if (slot >= bufs->max) slot = 0;
-
-       /* free the previous inhabitant */
-       if(bufs->bufp[slot] != (void *)0) free(bufs->bufp[slot]);
-
-       /* store the new one */
-       bufs->bufp[slot] = ptr;
-       bufs->cur = slot;
-
-       return ptr;
-}
-
-
 /*
  * safe_env - build a "safe" environment list.
  */
@@ -445,6 +392,7 @@ safe_env()
 #ifdef NEED_PATH_ENV
        "PATH",
 #endif
+       "DISPLAY",
        NULL
     };
 
@@ -500,7 +448,7 @@ safe_env()
 
 int
 debug_amtable_alloc(s, l, table, current, elsize, count, bump, init_func)
-    char *s;
+    const char *s;
     int l;
     void **table;
     int *current;
index f32ebf7c18b86c505bba95ecc347d1e42e2991a0..66cff1d624c1f288cc9cfdb805ab280376f2d9b7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amanda.h,v 1.66.2.7.4.5.2.12.2.6 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amanda.h,v 1.123 2006/03/03 15:05:15 vectro Exp $
  *
  * the central header file included by all amanda sources
  */
 #  include <sys/ioctl.h>
 #endif
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
 #ifdef HAVE_SYS_PARAM_H
 #  include <sys/param.h>
 #endif
 #  include <sys/stat.h>
 #endif
 
+#ifdef HAVE_SYS_UIO_H
+#  include <sys/uio.h>
+#else
+struct iovec {
+    void *iov_base;
+    int iov_len;
+};
+#endif
+
 #ifdef HAVE_WAIT_H
 #  include <wait.h>
 #endif
 # endif
 #endif
 
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
+#ifndef WIFSIGNALED
+# define WIFSIGNALED(stat_val) (WTERMSIG(stat_val) != 0)
 #endif
 
-/*
- * At present, the kerberos routines require atexit(), or equivilent.  If 
- * you're not using kerberos, you don't need it at all.  If you just null
- * out the definition, you'll end up with ticket files hanging around in
- * /tmp.
- */
-#if defined(KRB4_SECURITY)
-#   if !defined(HAVE_ATEXIT) 
-#      if defined(HAVE_ON_EXIT)
-#          define atexit(func) on_exit(func, 0)
-#      else
-#         define atexit(func) (you must to resolve lack of atexit in amanda.h)
-#      endif
-#   endif
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
 #endif
 
 #include <ctype.h>
 #include <arpa/inet.h>
 #endif
 
-#ifdef KRB4_SECURITY
-#  include <des.h>
-#  include <krb.h>
-#endif
-
 /*
  * The dbmalloc package comes from:
  *
@@ -318,6 +314,10 @@ extern int errno;
 #  define FD_ZERO(p)      memset((p), 0, sizeof(*(p)))
 #endif
 
+#ifndef FD_COPY
+#  define FD_COPY(p, q)   memcpy((q), (p), sizeof(fd_set))
+#endif
+
 
 /*
  * Define MAX_HOSTNAME_LENGTH as the size of arrays to hold hostname's.
@@ -333,15 +333,21 @@ extern int errno;
 #endif
 
 /*
- * define prototype macro so that prototypes can be declared in both ANSI
- * and classic C environments.
+ * Macros to allow code to adapt to both ANSI and class C environments.
+ *
+ * P(): prototype argument macro - removes arguments from prototypes in
+ *      class C environments
+ * stringize(): turn a bare word or words into a quoted string
+ * stringconcat(): turn two quoted strings into one
  */
 #if STDC_HEADERS
 #  define P(parms)     parms
 #  define stringize(x) #x
+#  define stringconcat(x, y) x ## y
 #else
 #  define P(parms)     ()
 #  define stringize(x) "x"
+#  define stringconcat(x, y) x/**/y
 #endif
 
 /*
@@ -362,8 +368,13 @@ extern int errno;
 
 #else  /* ASSERTIONS */
 
-#define assert(exp) {if(!(exp)) error("assert: %s false, file %s, line %d", \
-                                  stringize(exp), __FILE__, __LINE__);}
+#define assert(exp)    do {                                            \
+    if (!(exp)) {                                                      \
+       onerror(abort);                                                 \
+       error("assert: %s false, file %s, line %d",                     \
+          stringize(exp), __FILE__, __LINE__);                         \
+    }                                                                  \
+} while (0)
 
 #endif /* ASSERTIONS */
 
@@ -383,7 +394,7 @@ extern int errno;
 extern void debug_open P((void));
 extern void debug_reopen P((char *file, char *notation));
 extern void debug_close P((void));
-extern void debug_printf P((char *format, ...))
+extern void debug_printf P((const char *format, ...))
     __attribute__ ((format (printf, 1, 2)));
 extern int  debug_fd P((void));
 extern FILE *  debug_fp P((void));
@@ -429,7 +440,7 @@ extern char *debug_prefix_time P((char *));
 #define am_round(v,u)  ((((v) + (u) - 1) / (u)) * (u))
 #define am_floor(v,u)  (((v) / (u)) * (u))
 
-/* Holding disk block size.  Do not even think about changing this!  :-) */
+/* Holding disk block size.  Do not even think about changint this!  :-) */
 #define DISK_BLOCK_KB          32
 #define DISK_BLOCK_BYTES       (DISK_BLOCK_KB * 1024)
 
@@ -438,39 +449,33 @@ extern char *debug_prefix_time P((char *));
 /* by configure --with-maxtapeblocksize     */
 #define MAX_TAPE_BLOCK_BYTES (MAX_TAPE_BLOCK_KB*1024)
 
+/* Maximum length of tape label, plus one for null-terminator. */
+#define MAX_TAPE_LABEL_LEN (10240)
+#define MAX_TAPE_LABEL_BUF (MAX_TAPE_LABEL_LEN+1)
+
 /* Define miscellaneous amanda functions.  */
 #define ERR_INTERACTIVE        1
 #define ERR_SYSLOG     2
 #define ERR_AMANDALOG  4
 
-/* For static buffer manager [alloc.c:sbuf_man()] */
-#define SBUF_MAGIC 42
-#define SBUF_DEF(name, len) static SBUF2_DEF(len) name = {SBUF_MAGIC, len, -1}
-#define SBUF2_DEF(len)                 \
-    struct {                   \
-       int magic;              \
-       int max, cur;           \
-       void *bufp[len];        \
-    }
-
 extern void   set_logerror P((void (*f)(char *)));
 extern void   set_pname P((char *pname));
 extern char  *get_pname P((void));
 extern int    erroutput_type;
-extern void   error     P((char *format, ...))
-    __attribute__ ((format (printf, 1, 2)));
-extern void   errordump P((char *format, ...))
-    __attribute__ ((format (printf, 1, 2)));
+extern void   error     P((const char *format, ...))
+    __attribute__ ((format (printf, 1, 2), noreturn));
+extern void   errordump P((const char *format, ...))
+    __attribute__ ((format (printf, 1, 2), noreturn));
 extern int    onerror         P((void (*errf)(void)));
 
-extern void  *debug_alloc           P((char *c, int l, size_t size));
-extern void  *debug_newalloc        P((char *c, int l, void *old, size_t size));
-extern char  *debug_stralloc        P((char *c, int l, const char *str));
-extern char  *debug_newstralloc     P((char *c, int l, char *oldstr, const char *newstr));
-extern char  *debug_caller_loc      P((char *file, int line));
-
-extern int   debug_alloc_push      P((char *file, int line));
-extern void  debug_alloc_pop       P((void));
+extern void *debug_alloc P((const char *c, int l, size_t size));
+extern void *debug_newalloc P((const char *c, int l, void *old, size_t size));
+extern char *debug_stralloc P((const char *c, int l, const char *str));
+extern char *debug_newstralloc P((const char *c, int l, char *oldstr,
+    const char *newstr));
+extern const char *debug_caller_loc P((const char *file, int line));
+extern int debug_alloc_push P((char *file, int line));
+extern void debug_alloc_pop P((void));
 
 #define        alloc(s)                debug_alloc(__FILE__, __LINE__, (s))
 #define        newalloc(p,s)           debug_newalloc(__FILE__, __LINE__, (p), (s))
@@ -516,12 +521,16 @@ extern char  *debug_newvstralloc    P((char *oldstr, const char *newstr, ...));
 #define        stralloc2(s1,s2)      vstralloc((s1),(s2),NULL)
 #define        newstralloc2(p,s1,s2) newvstralloc((p),(s1),(s2),NULL)
 
-extern char  *debug_agets     P((char *c, int l, FILE *file));
-extern char  *debug_areads    P((char *c, int l, int fd));
+/* Usage: vstrextend(foo, "bar, "baz", NULL). Extends the existing 
+ * string, or allocates a brand new one. */
+extern char *vstrextend P((char **oldstr, ...));
+
+extern char  *debug_agets   P((const char *c, int l, FILE *file));
+extern char  *debug_areads  P((const char *c, int l, int fd));
 #define agets(f)             debug_agets(__FILE__,__LINE__,(f))
 #define areads(f)            debug_areads(__FILE__,__LINE__,(f))
 
-extern int debug_amtable_alloc P((char *file,
+extern int debug_amtable_alloc P((const char *file,
                                  int line,
                                  void **table,
                                  int *current,
@@ -529,22 +538,22 @@ extern int debug_amtable_alloc P((char *file,
                                  int count,
                                  int bump,
                                  void (*init_func)(void *)));
-#define amtable_alloc(t,c,s,n,b,f) debug_amtable_alloc(__FILE__,       \
-                                                      __LINE__,        \
-                                                      (t),             \
-                                                      (c),             \
-                                                      (s),             \
-                                                      (n),             \
-                                                      (b),             \
-                                                      (f))
+#define amtable_alloc(t,c,s,n,b,f) debug_amtable_alloc(__FILE__,      \
+                                                    __LINE__,        \
+                                                    (t),             \
+                                                    (c),             \
+                                                    (s),             \
+                                                    (n),             \
+                                                    (b),             \
+                                                    (f))
+
 extern void amtable_free      P((void **table, int *current));
 
-extern void  *sbuf_man        P((void *bufs, void *ptr));
 extern uid_t  client_uid;
 extern gid_t  client_gid;
-extern void   safe_cd        P((void));
-extern void   safe_fd        P((int fd_start, int fd_count));
-extern void   save_core              P((void));
+extern void   safe_fd         P((int fd_start, int fd_count));
+extern void   safe_cd         P((void));
+extern void   save_core       P((void));
 extern char **safe_env        P((void));
 extern char  *validate_regexp P((char *regex));
 extern char  *validate_glob   P((char *glob));
@@ -557,6 +566,7 @@ extern char  *tar_to_regex    P((char *glob));
 extern int    match_host      P((char *glob, char *host));
 extern int    match_disk      P((char *glob, char *disk));
 extern int    match_datestamp P((char *dateexp, char *datestamp));
+extern int    match_level     P((char *levelexp, char *level));
 extern time_t unctime         P((char *timestr));
 extern ssize_t  areads_dataready  P((int fd));
 extern void     areads_relbuf     P((int fd));
@@ -629,7 +639,7 @@ extern void     areads_relbuf     P((int fd));
 /*
  * Return the number of elements in an array.
  */
-#define am_countof(a)        (sizeof(a) / sizeof((a)[0]))
+#define am_countof(a)  (sizeof(a) / sizeof((a)[0]))
 
 /*
  * min/max.  Don't do something like
@@ -640,8 +650,15 @@ extern void     areads_relbuf     P((int fd));
  */
 #undef min
 #undef max
-#define min(a, b)       ((a) < (b) ? (a) : (b))
-#define max(a, b)       ((a) > (b) ? (a) : (b))
+#define        min(a, b)       ((a) < (b) ? (a) : (b))
+#define        max(a, b)       ((a) > (b) ? (a) : (b))
+
+/*
+ * Utility bitmask manipulation macros.
+ */
+#define        SET(t, f)       ((t) |= (f))
+#define        CLR(t, f)       ((t) &= ~((unsigned)(f)))
+#define        ISSET(t, f)     ((t) & (f))
 
 /*
  * Utility string macros.  All assume a variable holds the current
@@ -707,7 +724,7 @@ extern void     areads_relbuf     P((int fd));
  *           if NULL on exit, the field was too small for the input
  */
 
-#define        STR_SIZE        1024            /* a generic string buffer size */
+#define        STR_SIZE        4096            /* a generic string buffer size */
 #define        NUM_STR_SIZE    32              /* a generic number buffer size */
 
 #define        skip_whitespace(ptr,c) do {                                     \
@@ -779,13 +796,18 @@ extern int    mkpdir    P((char *file, int mode, uid_t uid, gid_t gid));
 extern int    rmpdir    P((char *file, char *topdir));
 extern char  *sanitise_filename P((char *inp));
 
+/* from bsd-security.c */
+extern char  *check_user_ruserok     P((const char *host,
+                                       struct passwd *pwd,
+                                       const char *user));
+extern char  *check_user_amandahosts P((const char *host,
+                                       struct passwd *pwd,
+                                       const char *user));
+
 extern int debug;
-extern char *version_info[];
+extern int check_security P((struct sockaddr_in *, char *, unsigned long,
+                             char **));
 
-/* from security.c */
-extern int security_ok P((struct sockaddr_in *addr,
-                         char *str, uint32_t cksum, char **errstr));
-extern char *get_bsd_security P((void));
 
 /*
  * Handle functions which are not always declared on all systems.  This
@@ -925,19 +947,7 @@ extern int gettimeofday P((struct timeval *tp));
 # define initgroups(name,basegid) 0
 #else
 # ifndef HAVE_INITGROUPS_DECL
-/* modification by BIS@BBN 5/20/2003:
- * In some Unix systems, basegid is defined as a gid_t; in others
- * it is defined as an int.  On Mac OS X, there is a "pre-compiled"
- * unistd.h which causes the gcc -E command in the ICE_CHECK_DECL
- * autoconf macro to not succeed.  Thus, on Mac OS X, configure thinks
- * we don't have this declaration when we actually do.  Since Mac OS X
- * defines basegid as an int, this declaration causes a compilation
- * failure.  The path of least resistance for fixing this problem
- * is to just change the basegid declaration from gid_t to int, since
- * other (but not all) UNIX flavors also defined basegid as an int.
 extern int initgroups P((const char *name, gid_t basegid));
- */
-extern int initgroups P((const char *name, int basegid));
 # endif
 #endif
 
@@ -973,6 +983,10 @@ extern void *memset P((void *s, int c, size_t n));
 extern char *mktemp P((char *template));
 #endif
 
+#ifndef HAVE_MKSTEMP_DECL
+extern int mkstemp P((char *template));
+#endif
+
 #ifndef HAVE_MKTIME_DECL
 extern time_t mktime P((struct tm *timeptr));
 #endif
@@ -1100,18 +1114,14 @@ extern int shmget P((key_t key, size_t size, int shmflg));
 #endif
 #endif
 
-#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF)
-#define ap_snprintf    snprintf
-#define ap_vsnprintf   vsnprintf
-#endif
 #ifndef HAVE_SNPRINTF_DECL
 #include "arglist.h"
-int ap_snprintf  P((char *buf, size_t len, const char *format,...))
+int snprintf  P((char *buf, size_t len, const char *format,...))
                    __attribute__((format(printf,3,4)));
 #endif
 #ifndef HAVE_VSNPRINTF_DECL
 #include "arglist.h"
-int ap_vsnprintf P((char *buf, size_t len, const char *format, va_list ap));
+int vsnprintf P((char *buf, size_t len, const char *format, va_list ap));
 #endif
 
 #ifndef HAVE_SOCKET_DECL
@@ -1194,6 +1204,10 @@ extern pid_t waitpid P((pid_t pid, amwait_t *stat_loc, int options));
 #endif
 #endif
 
+#ifndef HAVE_WRITEV_DECL
+extern ssize_t writev P((int fd, const struct iovec *iov, int iovcnt));
+#endif
+
 #ifndef STDIN_FILENO
 #define STDIN_FILENO 0
 #endif
@@ -1215,4 +1229,83 @@ error: Don t know how to define S_ISDIR
 #endif
 #endif
 
+#if SIZEOF_OFF_T > SIZEOF_LONG
+#  define        OFF_T_FMT       LL_FMT
+#else
+#  define        OFF_T_FMT       "%ld"
+#endif
+
+#if SIZEOF_LONG == 8
+   typedef long am64_t;
+#  ifdef LONG_MAX
+#    define AM64_MAX LONG_MAX
+#  else
+#    define AM64_MAX 9223372036854775807L
+#  endif
+#  ifdef LONG_MIN
+#    define AM64_MIN LONG_MIN
+#  else
+#    define AM64_MIN -9223372036854775807L -1L
+#  endif
+#  define AM64_FMT "%ld"
+#else
+#if SIZEOF_LONG_LONG == 8
+   typedef long long am64_t;
+#  ifdef LONG_LONG_MAX
+#    define AM64_MAX LONG_LONG_MAX
+#  else
+#    define AM64_MAX 9223372036854775807LL
+#  endif
+#  ifdef LONG_LONG_MIN
+#    define AM64_MIN LONG_LONG_MIN
+#  else
+#    define AM64_MIN -9223372036854775807LL -1LL
+#  endif
+#  define AM64_FMT LL_FMT
+#else
+#if SIZEOF_INTMAX_T == 8
+   typedef intmax_t am64_t;
+#  ifdef INTMAX_MAX
+#    define AM64_MAX INTMAX_MAX
+#  else
+#    define AM64_MAX 9223372036854775807LL
+#  endif
+#  ifdef INTMAX_MIN
+#    define AM64_MIN INTMAX_MIN
+#  else
+#    define AM64_MIN -9223372036854775807LL -1LL
+#  endif
+#  define AM64_FMT LL_FMT
+#else
+#if SIZEOF_OFF_T == 8
+   typedef off_t am64_t;
+#  ifdef OFF_MAX
+#    define AM64_MAX OFF_MAX
+#  else
+#    define AM64_MAX 9223372036854775807LL
+#  endif
+#  ifdef OFF_MIN
+#    define AM64_MIN OFF_MIN
+#  else
+#    define AM64_MIN -9223372036854775807LL -1LL
+#  endif
+#  define AM64_FMT OFF_T_FMT
+#else  /* no 64 bits tyupe found, use long. */
+   typedef long am64_t;
+#  ifdef LONG_MAX
+#    define AM64_MAX LONG_MAX
+#  else
+#    define AM64_MAX 2147483647
+#  endif
+#  ifdef LONG_MIN
+#    define AM64_MIN LONG_MIN
+#  else
+#    define AM64_MIN -2147483647 -1
+#  endif
+#  define AM64_FMT "%ld"
+#endif
+#endif
+#endif
+#endif
+
 #endif /* !AMANDA_H */
index 63dcea385df4426022b27b5dee7a425205db8dae..94fad87839fb396a2086fd15a0d14f86495bd3f7 100644 (file)
  */
 
 /*
- * $Id: amfeatures.c,v 1.1.2.9.2.3 2004/08/11 19:16:28 martinea Exp $
+ * $Id: amfeatures.c,v 1.18 2006/03/14 13:11:58 martinea Exp $
  *
  * Feature test related code.
  */
 
-#include <amanda.h>
-#include <amfeatures.h>
+#include "amanda.h"
+#include "amfeatures.h"
 
 /*
  *=====================================================================
@@ -109,9 +109,25 @@ am_init_feature_set()
        am_add_feature(f, fe_amidxtaped_nargs);
        am_add_feature(f, fe_amidxtaped_config);
 
+        am_add_feature(f, fe_recover_splits);
+        am_add_feature(f, fe_amidxtaped_exchange_features);
+
        am_add_feature(f, fe_partial_estimate);
        am_add_feature(f, fe_calcsize_estimate);
        am_add_feature(f, fe_selfcheck_calcsize);
+
+       am_add_feature(f, fe_options_compress_cust);
+       am_add_feature(f, fe_options_srvcomp_cust);
+       am_add_feature(f, fe_options_encrypt_cust);
+       am_add_feature(f, fe_options_encrypt_serv_cust);
+       am_add_feature(f, fe_options_client_decrypt_option);
+       am_add_feature(f, fe_options_server_decrypt_option);
+
+        am_add_feature(f, fe_amindexd_marshall_in_OLSD);
+        am_add_feature(f, fe_amindexd_marshall_in_ORLD);
+        am_add_feature(f, fe_amindexd_marshall_in_DHST);
+
+        am_add_feature(f, fe_amrecover_FEEDME);
     }
     return f;
 }
@@ -332,7 +348,7 @@ am_feature_to_string(f)
     } else {
        result = alloc((f->size * 2) + 1);
        for (i = 0; i < f->size; i++) {
-           ap_snprintf(result + (i * 2), 2 + 1, "%02x", f->bytes[i]);
+           snprintf(result + (i * 2), 2 + 1, "%02x", f->bytes[i]);
        }
        result[i * 2] = '\0';
     }
index 645f283d462bc89c29aaa90b465e5e01e4a1c80b..8d9e9bddffd5f275c5bd5d68c9b8bc06f3ab1934 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 /*
- * $Id: amfeatures.h,v 1.1.2.6.2.3 2004/08/11 19:16:28 martinea Exp $
+ * $Id: amfeatures.h,v 1.15 2006/03/14 13:11:58 martinea Exp $
  *
  * Define feature test related items.
  */
@@ -93,7 +93,7 @@ typedef enum {
 
     fe_program_dump,
     fe_program_gnutar,
-    fe_program_dumper_api,
+    fe_program_dumper_api,             /* require fe_sendsize_req_options */
 
     fe_options_compress_fast,
     fe_options_compress_best,
@@ -138,6 +138,21 @@ typedef enum {
     fe_calcsize_estimate,
     fe_selfcheck_calcsize,
 
+    fe_recover_splits,
+    fe_amidxtaped_exchange_features,
+
+    fe_options_compress_cust,
+    fe_options_srvcomp_cust,
+    fe_options_encrypt_cust,
+    fe_options_encrypt_serv_cust,
+    fe_options_client_decrypt_option,
+    fe_options_server_decrypt_option,
+
+    fe_amindexd_marshall_in_OLSD,
+    fe_amindexd_marshall_in_ORLD,
+    fe_amindexd_marshall_in_DHST,
+    fe_amrecover_FEEDME,
+
     /*
      * All new features must be inserted immediately *before* this entry.
      */
index 528f7782eee66cf7c74f948618d6343f22be8781..9fe27c7c575397c2e1878c3ef92b524b4bc9dcb0 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amflock.c,v 1.17.4.6.6.1.2.2 2005/10/06 17:26:36 martinea Exp $
+ * $Id: amflock.c,v 1.27 2005/10/06 17:26:21 martinea Exp $
  *
  * file locking routines, put here to hide the system dependant stuff
  * from the rest of the code
@@ -284,7 +284,7 @@ int op;    /* true to lock; false to unlock */
 
        /* lock the resource */
 
-       ap_snprintf(pid_str, sizeof(pid_str), "%ld", mypid);
+       snprintf(pid_str, sizeof(pid_str), "%ld", mypid);
        tlockfile = vstralloc(AMANDA_TMPDIR, "am", res, ".", pid_str, NULL);
 
        (void)create_lock(tlockfile, mypid);
index f606ea2469ad803ab6fbcb97e34e0a2a4f4e9702..6aa54c6fc4ffb32ea54e0203e9b10bc1041f67be 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amregex.h,v 1.9 1998/07/04 00:18:36 oliva Exp $
+ * $Id: amregex.h,v 1.10 1999/04/10 06:18:44 kashmir Exp $
  *
  * compatibility header file for Henry Spencer's regex library.
  */
@@ -92,18 +92,14 @@ extern void *memset P((void *s, int c, size_t n));
 #define USEBCOPY
 #endif
 
-#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF)
-#define ap_snprintf    snprintf
-#define ap_vsnprintf   vsnprintf
-#endif
 #ifndef HAVE_SNPRINTF_DECL
 #include "arglist.h"
-int ap_snprintf  P((char *buf, size_t len, const char *format,...))
+int snprintf  P((char *buf, size_t len, const char *format,...))
                    __attribute__((format(printf,3,4)));
 #endif
 #ifndef HAVE_VSNPRINTF_DECL
 #include "arglist.h"
-int ap_vsnprintf P((char *buf, size_t len, const char *format, va_list ap));
+int vsnprintf P((char *buf, size_t len, const char *format, va_list ap));
 #endif
 
 #define POSIX_MISTAKE
index e26f714744d13661ba63514892af8c06ca5a0c3a..1c87202cda094d6697c0d9bd8607691273584140 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: arglist.h,v 1.4.10.2 2002/12/03 21:36:47 martinea Exp $
+ * $Id: arglist.h,v 1.7 2002/12/03 21:36:39 martinea Exp $
  *
  * support macros for variable argument list declaration and definition
  */
              arg2_type arg2_name, \
              hook_type hook_name, ...)
 
+#define arglist_function3(fdecl, arg1_type, arg1_name, arg2_type, arg2_name, \
+                         arg3_type, arg3_name, hook_type, hook_name) \
+       fdecl(arg1_type arg1_name, arg2_type arg2_name, \
+             arg3_type arg3_name, hook_type hook_name, ...)
+
 #define arglist_start(arg,hook_name)   va_start(arg,hook_name)
 
 #else
        hook_type hook_name;                                    \
        va_dcl
 
+#define arglist_function3(fdecl, arg1_type, arg1_name, arg2_type, arg2_name, \
+                         arg3_type, arg3_name, hook_type, hook_name) \
+       fdecl(arg1_name, arg2_name, arg3_name, hook_name, va_alist)     \
+       arg1_type arg1_name;                                            \
+       arg2_type arg2_name;                                            \
+       arg3_type arg3_name;                                            \
+       hook_type hook_name;                                            \
+       va_dcl
+
 #define arglist_start(arg,hook_name)   va_start(arg)
 
 #endif
diff --git a/common-src/bsd-security.c b/common-src/bsd-security.c
new file mode 100644 (file)
index 0000000..60e63d3
--- /dev/null
@@ -0,0 +1,1865 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: bsd-security.c,v 1.54 2006/03/09 16:51:41 martinea Exp $
+ *
+ * "BSD" security module
+ */
+
+#include "amanda.h"
+#include "util.h"
+#include "clock.h"
+#include "dgram.h"
+#include "event.h"
+#include "packet.h"
+#include "security.h"
+#include "stream.h"
+#include "version.h"
+
+/*#define       BSD_DEBUG*/
+
+#ifdef BSD_DEBUG
+#define bsdprintf(x)    dbprintf(x)
+#else
+#define bsdprintf(x)
+#endif
+
+#ifndef SO_RCVBUF
+#undef DUMPER_SOCKET_BUFFERING
+#endif
+
+#ifdef BSD_SECURITY                                            /* { */
+
+/*
+ * Change the following from #undef to #define to cause detailed logging
+ * of the security steps, e.g. into /tmp/amanda/amandad*debug.
+ */
+#undef SHOW_SECURITY_DETAIL
+
+#if defined(TEST)                                              /* { */
+#define SHOW_SECURITY_DETAIL
+#undef bsdprintf
+#define bsdprintf(p)   printf p
+#endif                                                         /* } */
+
+/*
+ * This is the private handle data
+ */
+struct bsd_handle {
+    /*
+     * This must be first.  Instances of bsd_handle will be cast to
+     * security_handle_t's.
+     */
+    security_handle_t sech;
+
+    /*
+     * protocol handle for this request.  Each request gets its own
+     * handle, so we differentiate packets for them with a "handle" header
+     * in each packet.
+     *
+     */
+    int event_id; /* unique event_id */
+    char *proto_handle;
+
+    /*
+     * sequence number.
+     */
+    int sequence;
+
+    /*
+     * The remote host we're transmitting to
+     */
+    char hostname[256];
+    struct sockaddr_in peer;
+
+    /*
+     * Function to call when recvpkt detects new incoming data for this
+     * handle
+     */
+    void (*fn) P((void *, pkt_t *, security_status_t));
+
+    /*
+     * Argument for previous function
+     */
+    void *arg;
+
+    /*
+     * read (EV_WAIT) handle for a recv
+     */
+    event_handle_t *ev_read;
+
+    /*
+     * Timeout handle for a recv
+     */
+    event_handle_t *ev_timeout;
+
+    struct bsd_handle *prev, *next;
+};
+
+struct bsd_handle *bh_first=NULL, *bh_last=NULL;
+
+/*
+ * This is the internal security_stream data
+ */
+struct bsd_stream {
+    /*
+     * This must be first, because instances of this will be cast
+     * to security_stream_t's outside of this module.
+     */
+    security_stream_t secstr;
+
+    /*
+     * This is the file descriptor which we will do io on
+     */
+    int fd;
+
+    /*
+     * This is the file descriptor which we will listen for incoming
+     * connections on (for streams which receive connections)
+     */
+    int socket;
+
+    /*
+     * This is the local port this stream is bound to
+     */
+    int port;
+
+    /*
+     * This is the read event handle for this data stream
+     */
+    event_handle_t *ev_read;
+
+    /*
+     * This is the function and argument that is called when this stream
+     * is readable.  It is passed a buffer of data read.
+     */
+    void (*fn) P((void *, void *, ssize_t));
+    void *arg;
+
+    /*
+     * This is the buffer that we read data into that will be passed
+     * to the read callback.
+     */
+    char databuf[NETWORK_BLOCK_BYTES];
+};
+
+/*
+ * Interface functions
+ */
+static void bsd_connect P((const char *,
+    char *(*)(char *, void *), 
+    void (*)(void *, security_handle_t *, security_status_t), void *));
+static void bsd_accept P((int, int, void (*)(security_handle_t *, pkt_t *)));
+static void bsd_close P((void *));
+static int bsd_sendpkt P((void *, pkt_t *));
+static void bsd_recvpkt P((void *,
+    void (*)(void *, pkt_t *, security_status_t), void *, int));
+static void bsd_recvpkt_cancel P((void *));
+
+static void *bsd_stream_server P((void *));
+static int bsd_stream_accept P((void *));
+static void *bsd_stream_client P((void *, int));
+static void bsd_stream_close P((void *));
+static int bsd_stream_auth P((void *));
+static int bsd_stream_id P((void *));
+static int bsd_stream_write P((void *, const void *, size_t));
+static void bsd_stream_read P((void *, void (*)(void *, void *, ssize_t),
+    void *));
+static void bsd_stream_read_cancel P((void *));
+
+/*
+ * This is our interface to the outside world
+ */
+const security_driver_t bsd_security_driver = {
+    "BSD",
+    bsd_connect,
+    bsd_accept,
+    bsd_close,
+    bsd_sendpkt,
+    bsd_recvpkt,
+    bsd_recvpkt_cancel,
+    bsd_stream_server,
+    bsd_stream_accept,
+    bsd_stream_client,
+    bsd_stream_close,
+    bsd_stream_auth,
+    bsd_stream_id,
+    bsd_stream_write,
+    bsd_stream_read,
+    bsd_stream_read_cancel,
+};
+
+/*
+ * This is data local to the datagram socket.  We have one datagram
+ * per process, so it is global.
+ */
+static struct {
+    dgram_t dgram;             /* datagram to read/write from */
+    struct sockaddr_in peer;   /* who sent it to us */
+    pkt_t pkt;                 /* parsed form of dgram */
+    char *handle;              /* handle from recvd packet */
+    int sequence;              /* seq no of packet */
+    event_handle_t *ev_read;   /* read event handle from dgram */
+    int refcnt;                        /* number of handles blocked for reading */
+} netfd;
+
+/* generate new handles from here */
+static int newhandle = 0;
+static int newevent = 0;
+
+/*
+ * We register one event handler for our network fd which takes
+ * care of all of our async requests.  When all async requests
+ * have either been satisfied or cancelled, we unregister our
+ * network event handler.
+ */
+#define        netfd_addref()  do      {                                       \
+    if (netfd.refcnt++ == 0) {                                         \
+       assert(netfd.ev_read == NULL);                                  \
+       netfd.ev_read = event_register(netfd.dgram.socket, EV_READFD,   \
+           netfd_read_callback, NULL);                                 \
+    }                                                                  \
+    assert(netfd.refcnt > 0);                                          \
+} while (0)
+
+/*
+ * If this is the last request to be removed, then remove the
+ * reader event from the netfd.
+ */
+#define        netfd_delref()  do      {                                       \
+    assert(netfd.refcnt > 0);                                          \
+    if (--netfd.refcnt == 0) {                                         \
+       assert(netfd.ev_read != NULL);                                  \
+       event_release(netfd.ev_read);                                   \
+       netfd.ev_read = NULL;                                           \
+    }                                                                  \
+} while (0)
+
+/*
+ * This is the function and argument that is called when new requests
+ * arrive on the netfd.
+ */
+static void (*accept_fn) P((security_handle_t *, pkt_t *));
+
+/*
+ * These are the internal helper functions
+ */
+static char *check_user P((struct bsd_handle *, const char *));
+static int inithandle P((struct bsd_handle *, struct hostent *,
+                        int, char *, int));
+static const char *pkthdr2str P((const struct bsd_handle *, const pkt_t *));
+static int str2pkthdr P((void));
+static void netfd_read_callback P((void *));
+static void recvpkt_callback P((void *));
+static void recvpkt_timeout P((void *));
+static int recv_security_ok P((struct bsd_handle *));
+static void stream_read_callback P((void *));
+
+
+#if defined(SHOW_SECURITY_DETAIL)                              /* { */
+/*
+ * Display stat() information about a file.
+ */
+void show_stat_info(a, b)
+    char *a, *b;
+{
+    char *name = vstralloc(a, b, NULL);
+    struct stat sbuf;
+    struct passwd *pwptr;
+    char *owner;
+    struct group *grptr;
+    char *group;
+
+    if (stat(name, &sbuf) != 0) {
+       bsdprintf(("%s: cannot stat %s: %s\n",
+                  debug_prefix_time(NULL), name, strerror(errno)));
+       amfree(name);
+       return;
+    }
+    if ((pwptr = getpwuid(sbuf.st_uid)) == NULL) {
+       owner = alloc(NUM_STR_SIZE + 1);
+       snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
+    } else {
+       owner = stralloc(pwptr->pw_name);
+    }
+    if ((grptr = getgrgid(sbuf.st_gid)) == NULL) {
+       group = alloc(NUM_STR_SIZE + 1);
+       snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
+    } else {
+       group = stralloc(grptr->gr_name);
+    }
+    bsdprintf(("%s: processing file: %s\n", debug_prefix(NULL), name));
+    bsdprintf(("%s:                  owner=%s group=%s mode=%03o\n",
+              debug_prefix(NULL), owner, group, (int) (sbuf.st_mode & 0777)));
+    amfree(name);
+    amfree(owner);
+    amfree(group);
+}
+#endif                                                         /* } */
+
+/*
+ * Setup and return a handle outgoing to a client
+ */
+static void
+bsd_connect(hostname, conf_fn, fn, arg)
+    const char *hostname;
+    char *(*conf_fn) P((char *, void *));
+    void (*fn) P((void *, security_handle_t *, security_status_t));
+    void *arg;
+{
+    struct bsd_handle *bh;
+    struct servent *se;
+    struct hostent *he;
+    int port;
+    struct timeval sequence_time;
+    amanda_timezone dontcare;
+    int sequence;
+    char *handle;
+
+    assert(hostname != NULL);
+
+    bh = alloc(sizeof(*bh));
+    bh->proto_handle=NULL;
+    security_handleinit(&bh->sech, &bsd_security_driver);
+
+    /*
+     * Only init the socket once
+     */
+    if (netfd.dgram.socket == 0) {
+       uid_t euid;
+       dgram_zero(&netfd.dgram);
+       
+       euid = geteuid();
+       seteuid(0);
+       dgram_bind(&netfd.dgram, &port);
+       seteuid(euid);
+       /*
+        * We must have a reserved port.  Bomb if we didn't get one.
+        */
+       if (port >= IPPORT_RESERVED) {
+           security_seterror(&bh->sech,
+               "unable to bind to a reserved port (got port %d)",
+               port);
+           (*fn)(arg, &bh->sech, S_ERROR);
+           return;
+       }
+    }
+
+    if ((he = gethostbyname(hostname)) == NULL) {
+       security_seterror(&bh->sech,
+           "%s: could not resolve hostname", hostname);
+       (*fn)(arg, &bh->sech, S_ERROR);
+       return;
+    }
+    if ((se = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL)
+       port = htons(AMANDA_SERVICE_DEFAULT);
+    else
+       port = se->s_port;
+    amanda_gettimeofday(&sequence_time, &dontcare);
+    sequence = (int)sequence_time.tv_sec ^ (int)sequence_time.tv_usec;
+    handle=malloc(15);
+    snprintf(handle,14,"000-%08x", newhandle++);
+    if (inithandle(bh, he, port, handle, sequence) < 0)
+       (*fn)(arg, &bh->sech, S_ERROR);
+    else
+       (*fn)(arg, &bh->sech, S_OK);
+}
+
+/*
+ * Setup to accept new incoming connections
+ */
+static void
+bsd_accept(in, out, fn)
+    int in, out;
+    void (*fn) P((security_handle_t *, pkt_t *));
+{
+
+    assert(in >= 0 && out >= 0);
+    assert(fn != NULL);
+
+    /*
+     * We assume in and out point to the same socket, and just use
+     * in.
+     */
+    dgram_socket(&netfd.dgram, in);
+
+    /*
+     * Assign the function and return.  When they call recvpkt later,
+     * the recvpkt callback will call this function when it discovers
+     * new incoming connections
+     */
+    accept_fn = fn;
+
+    netfd_addref();
+}
+
+/*
+ * Given a hostname and a port, setup a bsd_handle
+ */
+static int
+inithandle(bh, he, port, handle, sequence)
+    struct bsd_handle *bh;
+    struct hostent *he;
+    int port;
+    char *handle;
+    int sequence;
+{
+    int i;
+
+    assert(he != NULL);
+    assert(port > 0);
+
+    /*
+     * Save the hostname and port info
+     */
+    strncpy(bh->hostname, he->h_name, sizeof(bh->hostname) - 1);
+    bh->hostname[sizeof(bh->hostname) - 1] = '\0';
+    bh->peer.sin_addr = *(struct in_addr *)he->h_addr;
+    bh->peer.sin_port = port;
+    bh->peer.sin_family = AF_INET;
+
+    bh->prev = bh_last;
+    if(bh_last) {bh->prev->next = bh;}
+    if(!bh_first) {bh_first = bh;}
+    bh->next = NULL;
+    bh_last = bh;
+
+    /*
+     * Do a forward lookup of the hostname.  This is unnecessary if we
+     * are initiating the connection, but is very serious if we are
+     * receiving.  We want to make sure the hostname
+     * resolves back to the remote ip for security reasons.
+     */
+    if ((he = gethostbyname(bh->hostname)) == NULL) {
+       security_seterror(&bh->sech,
+           "%s: could not resolve hostname", bh->hostname);
+       return (-1);
+    }
+    /*
+     * Make sure the hostname matches.  This should always work.
+     */
+    if (strncasecmp(bh->hostname, he->h_name, strlen(bh->hostname)) != 0) {
+       security_seterror(&bh->sech,
+           "%s: did not resolve to %s", bh->hostname, bh->hostname);
+       return (-1);
+    }
+
+    /*
+     * Now look for a matching ip address.
+     */
+    for (i = 0; he->h_addr_list[i] != NULL; i++) {
+       if (memcmp(&bh->peer.sin_addr, he->h_addr_list[i],
+           sizeof(struct in_addr)) == 0) {
+           break;
+       }
+    }
+
+    /*
+     * If we didn't find it, try the aliases.  This is a workaround for
+     * Solaris if DNS goes over NIS.
+     */
+    if (he->h_addr_list[i] == NULL) {
+       const char *ipstr = inet_ntoa(bh->peer.sin_addr);
+       for (i = 0; he->h_aliases[i] != NULL; i++) {
+           if (strcmp(he->h_aliases[i], ipstr) == 0)
+               break;
+       }
+       /*
+        * No aliases either.  Failure.  Someone is fooling with us or
+        * DNS is messed up.
+        */
+       if (he->h_aliases[i] == NULL) {
+           security_seterror(&bh->sech,
+               "DNS check failed: no matching ip address for %s",
+               bh->hostname);
+           return (-1);
+       }
+    }
+
+    bh->sequence = sequence;
+    bh->event_id = newevent++;
+    bh->proto_handle = handle;
+    bh->fn = NULL;
+    bh->arg = NULL;
+    bh->ev_read = NULL;
+    bh->ev_timeout = NULL;
+
+    bsdprintf(("%s: adding handle '%s'\n",
+              debug_prefix_time(NULL), bh->proto_handle));
+
+    return(0);
+}
+
+/*
+ * Frees a handle allocated by the above
+ */
+static void
+bsd_close(cookie)
+    void *cookie;
+{
+    struct bsd_handle *bh = cookie;
+
+    if(bh->proto_handle == NULL) {
+       return;
+    }
+
+    bsdprintf(("%s: close handle '%s'\n",
+              debug_prefix_time(NULL), bh->proto_handle));
+
+    bsd_recvpkt_cancel(bh);
+    if(bh->next) {
+       bh->next->prev = bh->prev;
+    }
+    else {
+       bh_last = bh->prev;
+    }
+    if(bh->prev) {
+       bh->prev->next = bh->next;
+    }
+    else {
+       bh_first = bh->next;
+    }
+
+    amfree(bh);
+}
+
+/*
+ * Transmit a packet.  Add security information first.
+ */
+static int
+bsd_sendpkt(cookie, pkt)
+    void *cookie;
+    pkt_t *pkt;
+{
+    struct bsd_handle *bh = cookie;
+    struct passwd *pwd;
+
+    assert(bh != NULL);
+    assert(pkt != NULL);
+
+    /*
+     * Initialize this datagram, and add the header
+     */
+    dgram_zero(&netfd.dgram);
+    dgram_cat(&netfd.dgram, pkthdr2str(bh, pkt));
+
+    /*
+     * Add the security info.  This depends on which kind of packet we're
+     * sending.
+     */
+    switch (pkt->type) {
+    case P_REQ:
+       /*
+        * Requests get sent with our username in the body
+        */
+       if ((pwd = getpwuid(geteuid())) == NULL) {
+           security_seterror(&bh->sech,
+               "can't get login name for my uid %ld", (long)getuid());
+           return (-1);
+       }
+       dgram_cat(&netfd.dgram, "SECURITY USER %s\n", pwd->pw_name);
+       break;
+
+    default:
+       break;
+    }
+
+    /*
+     * Add the body, and send it
+     */
+    dgram_cat(&netfd.dgram, pkt->body);
+    if (dgram_send_addr(bh->peer, &netfd.dgram) != 0) {
+       security_seterror(&bh->sech,
+           "send %s to %s failed: %s", pkt_type2str(pkt->type),
+           bh->hostname, strerror(errno));
+       return (-1);
+    }
+    return (0);
+}
+
+/*
+ * Set up to receive a packet asynchronously, and call back when it has
+ * been read.
+ */
+static void
+bsd_recvpkt(cookie, fn, arg, timeout)
+    void *cookie, *arg;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    int timeout;
+{
+    struct bsd_handle *bh = cookie;
+
+    assert(bh != NULL);
+    assert(fn != NULL);
+
+
+    /*
+     * Subsequent recvpkt calls override previous ones
+     */
+    if (bh->ev_read == NULL) {
+       netfd_addref();
+       bh->ev_read = event_register(bh->event_id, EV_WAIT,
+           recvpkt_callback, bh);
+    }
+    if (bh->ev_timeout != NULL)
+       event_release(bh->ev_timeout);
+    if (timeout < 0)
+       bh->ev_timeout = NULL;
+    else
+       bh->ev_timeout = event_register(timeout, EV_TIME, recvpkt_timeout, bh);
+    bh->fn = fn;
+    bh->arg = arg;
+}
+
+/*
+ * Remove a async receive request on this handle from the queue.
+ * If it is the last one to be removed, then remove the event
+ * handler for our network fd
+ */
+static void
+bsd_recvpkt_cancel(cookie)
+    void *cookie;
+{
+    struct bsd_handle *bh = cookie;
+
+    assert(bh != NULL);
+
+    if (bh->ev_read != NULL) {
+       netfd_delref();
+       event_release(bh->ev_read);
+       bh->ev_read = NULL;
+    }
+
+    if (bh->ev_timeout != NULL) {
+       event_release(bh->ev_timeout);
+       bh->ev_timeout = NULL;
+    }
+}
+
+/*
+ * Callback for received packets.  This is the function bsd_recvpkt
+ * registers with the event handler.  It is called when the event handler
+ * realizes that data is waiting to be read on the network socket.
+ */
+static void
+netfd_read_callback(cookie)
+    void *cookie;
+{
+    struct bsd_handle *bh;
+    struct hostent *he;
+    int a;
+
+    assert(cookie == NULL);
+
+#ifndef TEST                                                   /* { */
+    /*
+     * Receive the packet.
+     */
+    dgram_zero(&netfd.dgram);
+    if (dgram_recv(&netfd.dgram, 0, &netfd.peer) < 0)
+       return;
+#endif /* !TEST */                                             /* } */
+
+    /*
+     * Parse the packet.
+     */
+    if (str2pkthdr() < 0)
+       return;
+
+    /*
+     * If there are events waiting on this handle, we're done
+     */
+    bh = bh_first;
+    while(bh != NULL && (strcmp(bh->proto_handle, netfd.handle) != 0 ||
+                        bh->sequence != netfd.sequence ||
+                        bh->peer.sin_addr.s_addr != netfd.peer.sin_addr.s_addr ||
+                        bh->peer.sin_port != netfd.peer.sin_port)) {
+       bh = bh->next;
+    }
+    if (bh && event_wakeup(bh->event_id) > 0)
+       return;
+
+    /*
+     * If we didn't find a handle, then check for a new incoming packet.
+     * If no accept handler was setup, then just return.
+     */
+    if (accept_fn == NULL)
+       return;
+
+    he = gethostbyaddr((void *)&netfd.peer.sin_addr,
+       (int)sizeof(netfd.peer.sin_addr), AF_INET);
+    if (he == NULL)
+       return;
+    bh = alloc(sizeof(*bh));
+    bh->proto_handle=NULL;
+    security_handleinit(&bh->sech, &bsd_security_driver);
+    a = inithandle(bh,
+                  he,
+                  netfd.peer.sin_port,
+                  netfd.handle,
+                  netfd.sequence);
+    if (a < 0) {
+       if(bh->next) {
+           bh->next->prev = bh->prev;
+       }
+       else {
+           bh_last = bh->prev;
+       }
+       if(bh->prev) {
+           bh->prev->next = bh->next;
+       }
+       else {
+           bh_first = bh->prev;
+       }
+
+       bsdprintf(("%s: closeX handle '%s'\n",
+                 debug_prefix_time(NULL), bh->proto_handle));
+
+       amfree(bh);
+       return;
+    }
+    /*
+     * Check the security of the packet.  If it is bad, then pass NULL
+     * to the accept function instead of a packet.
+     */
+    if (recv_security_ok(bh) < 0)
+       (*accept_fn)(&bh->sech, NULL);
+    else
+       (*accept_fn)(&bh->sech, &netfd.pkt);
+}
+
+/*
+ * This is called when a handle is woken up because data read off of the
+ * net is for it.
+ */
+static void
+recvpkt_callback(cookie)
+    void *cookie;
+{
+    struct bsd_handle *bh = cookie;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    void *arg;
+
+    assert(bh != NULL);
+    bsdprintf(("%s: receive handle '%s' netfd '%s'\n",
+              debug_prefix_time(NULL), bh->proto_handle,netfd.handle));
+
+    if(strcmp(bh->proto_handle,netfd.handle) != 0) assert(1);
+
+    /* if it didn't come from the same host/port, forget it */
+    if (memcmp(&bh->peer.sin_addr, &netfd.peer.sin_addr,
+       sizeof(netfd.peer.sin_addr)) != 0 ||
+       bh->peer.sin_port != netfd.peer.sin_port) {
+       netfd.handle = NULL;
+       return;
+    }
+
+    /*
+     * We need to cancel the recvpkt request before calling the callback
+     * because the callback may reschedule us.
+     */
+    fn = bh->fn;
+    arg = bh->arg;
+    bsd_recvpkt_cancel(bh);
+
+    /*
+     * Check the security of the packet.  If it is bad, then pass NULL
+     * to the packet handling function instead of a packet.
+     */
+    if (recv_security_ok(bh) < 0)
+       (*fn)(arg, NULL, S_ERROR);
+    else
+       (*fn)(arg, &netfd.pkt, S_OK);
+}
+
+/*
+ * This is called when a handle times out before receiving a packet.
+ */
+static void
+recvpkt_timeout(cookie)
+    void *cookie;
+{
+    struct bsd_handle *bh = cookie;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    void *arg;
+
+    assert(bh != NULL);
+
+    assert(bh->ev_timeout != NULL);
+    fn = bh->fn;
+    arg = bh->arg;
+    bsd_recvpkt_cancel(bh);
+    (*fn)(arg, NULL, S_TIMEOUT);
+
+}
+
+/*
+ * Check the security of a received packet.  Returns negative on security
+ * violation, or returns 0 if ok.  Removes the security info from the pkt_t.
+ */
+static int
+recv_security_ok(bh)
+    struct bsd_handle *bh;
+{
+    char *tok, *security, *body, *result;
+    pkt_t *pkt = &netfd.pkt;
+
+    /*
+     * Set this preempively before we mangle the body.  
+     */
+    security_seterror(&bh->sech,
+       "bad SECURITY line: '%s'", pkt->body);
+
+    /*
+     * Now, find the SECURITY line in the body, and parse it out
+     * into an argv.
+     */
+    if (strncmp(pkt->body, "SECURITY", sizeof("SECURITY") - 1) == 0) {
+       tok = strtok(pkt->body, " ");
+       assert(strcmp(tok, "SECURITY") == 0);
+       /* security info goes until the newline */
+       security = strtok(NULL, "\n");
+       body = strtok(NULL, "");
+       /*
+        * If the body is f-ked, then try to recover
+        */
+       if (body == NULL) {
+           if (security != NULL)
+               body = security + strlen(security) + 2;
+           else
+               body = pkt->body;
+       }
+    } else {
+       security = NULL;
+       body = pkt->body;
+    }
+
+    /*
+     * We need to do different things depending on which type of packet
+     * this is.
+     */
+    switch (pkt->type) {
+    case P_REQ:
+       /*
+        * Request packets must come from a reserved port
+        */
+       if (ntohs(bh->peer.sin_port) >= IPPORT_RESERVED) {
+           security_seterror(&bh->sech,
+               "host %s: port %d not secure", bh->hostname,
+               ntohs(bh->peer.sin_port));
+           return (-1);
+       }
+
+       /*
+        * Request packets contain a remote username.  We need to check
+        * that we allow it in.
+        *
+        * They will look like:
+        *      SECURITY USER [username]
+        */
+
+       /* there must be some security info */
+       if (security == NULL) {
+           security_seterror(&bh->sech,
+               "no bsd SECURITY for P_REQ");
+           return (-1);
+       }
+
+       /* second word must be USER */
+       if ((tok = strtok(security, " ")) == NULL)
+           return (-1);        /* default errmsg */
+       if (strcmp(tok, "USER") != 0) {
+           security_seterror(&bh->sech,
+               "REQ SECURITY line parse error, expecting USER, got %s", tok);
+           return (-1);
+       }
+
+       /* the third word is the username */
+       if ((tok = strtok(NULL, "")) == NULL)
+           return (-1);        /* default errmsg */
+       if ((result = check_user(bh, tok)) != NULL) {
+           security_seterror(&bh->sech, "%s", result);
+           amfree(result);
+           return (-1);
+       }
+
+       /* we're good to go */
+       break;
+    default:
+       break;
+    }
+
+    /*
+     * If there is security info at the front of the packet, we need to
+     * shift the rest of the data up and nuke it.
+     */
+    if (body != pkt->body)
+       memmove(pkt->body, body, strlen(body) + 1);
+    return (0);
+}
+
+static char *
+check_user(bh, remoteuser)
+    struct bsd_handle *bh;
+    const char *remoteuser;
+{
+    struct passwd *pwd;
+    char *r;
+    char *result = NULL;
+    char *localuser = NULL;
+
+    /* lookup our local user name */
+    if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
+       return vstralloc("getpwnam(", CLIENT_LOGIN, ") fails", NULL);
+    }
+
+    /*
+     * Make a copy of the user name in case getpw* is called by
+     * any of the lower level routines.
+     */
+    localuser = stralloc(pwd->pw_name);
+
+#ifndef USE_AMANDAHOSTS
+    r = check_user_ruserok(bh->hostname, pwd, remoteuser);
+#else
+    r = check_user_amandahosts(bh->hostname, pwd, remoteuser);
+#endif
+    if (r != NULL) {
+       result = vstralloc("access as ", localuser, " not allowed",
+                          " from ", remoteuser, "@", bh->hostname,
+                          ": ", r,
+                          NULL);
+       amfree(r);
+    }
+    amfree(localuser);
+    return result;
+}
+
+/*
+ * See if a remote user is allowed in.  This version uses ruserok()
+ * and friends.
+ *
+ * Returns 0 on success, or negative on error.
+ */
+char *
+check_user_ruserok(host, pwd, remoteuser)
+    const char *host;
+    struct passwd *pwd;
+    const char *remoteuser;
+{
+    int saved_stderr;
+    int fd[2];
+    FILE *fError;
+    amwait_t exitcode;
+    pid_t ruserok_pid;
+    pid_t pid;
+    char *es;
+    char *result;
+    int ok;
+    char number[NUM_STR_SIZE];
+    uid_t myuid = getuid();
+
+    /*
+     * note that some versions of ruserok (eg SunOS 3.2) look in
+     * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to
+     * chdir ourselves.  Sigh.
+     *
+     * And, believe it or not, some ruserok()'s try an initgroup just
+     * for the hell of it.  Since we probably aren't root at this point
+     * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
+     * into our stderr output even though the initgroup failure is not a
+     * problem and is expected.  Thanks a lot.  Not.
+     */
+    if (pipe(fd) != 0) {
+       return stralloc2("pipe() fails: ", strerror(errno));
+    }
+    if ((ruserok_pid = fork()) < 0) {
+       return stralloc2("fork() fails: ", strerror(errno));
+    } else if (ruserok_pid == 0) {
+       int ec;
+
+       close(fd[0]);
+       fError = fdopen(fd[1], "w");
+       /* pamper braindead ruserok's */
+       if (chdir(pwd->pw_dir) != 0) {
+           fprintf(fError, "chdir(%s) failed: %s",
+                   pwd->pw_dir, strerror(errno));
+           fclose(fError);
+           exit(1);
+       }
+
+#if defined(SHOW_SECURITY_DETAIL)                              /* { */
+       {
+       char *dir = stralloc(pwd->pw_dir);
+
+       bsdprintf(("%s: calling ruserok(%s, %d, %s, %s)\n",
+                  debug_prefix_time(NULL),
+                  host, myuid == 0, remoteuser, pwd->pw_name));
+       if (myuid == 0) {
+           bsdprintf(("%s: because you are running as root, ",
+                      debug_prefix(NULL)));
+           bsdprintf(("/etc/hosts.equiv will not be used\n"));
+       } else {
+           show_stat_info("/etc/hosts.equiv", NULL);
+       }
+       show_stat_info(dir, "/.rhosts");
+       amfree(dir);
+       }
+#endif                                                         /* } */
+
+       saved_stderr = dup(2);
+       close(2);
+       if (open("/dev/null", O_RDWR) == -1) {
+            dbprintf(("Could not open /dev/null: %s\n",
+                     strerror(errno)));
+           ec = 1;
+       } else {
+           ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);
+           if (ok < 0) {
+               ec = 1;
+           } else {
+               ec = 0;
+           }
+       }
+       (void)dup2(saved_stderr,2);
+       close(saved_stderr);
+       exit(ec);
+    }
+    close(fd[1]);
+    fError = fdopen(fd[0], "r");
+
+    result = NULL;
+    while ((es = agets(fError)) != NULL) {
+       if (result == NULL) {
+           result = stralloc("");
+       } else {
+           strappend(result, ": ");
+       }
+       strappend(result, es);
+    }
+    close(fd[0]);
+
+    while (1) {
+       if ((pid = wait(&exitcode)) == (pid_t) -1) {
+           if (errno == EINTR) {
+               continue;
+           }
+           amfree(result);
+           return stralloc2("ruserok wait failed: %s", strerror(errno));
+       }
+       if (pid == ruserok_pid) {
+           break;
+       }
+    }
+    if (WIFSIGNALED(exitcode)) {
+       amfree(result);
+       snprintf(number, sizeof(number), "%d", WTERMSIG(exitcode));
+       return stralloc2("ruserok child got signal ", number);
+    }
+    if (WEXITSTATUS(exitcode) == 0) {
+       amfree(result);
+    } else if (result == NULL) {
+       result = stralloc("ruserok failed");
+    }
+
+    return result;
+}
+
+/*
+ * Check to see if a user is allowed in.  This version uses .amandahosts
+ * Returns -1 on failure, or 0 on success.
+ */
+char *
+check_user_amandahosts(host, pwd, remoteuser)
+    const char *host;
+    struct passwd *pwd;
+    const char *remoteuser;
+{
+    char *line = NULL;
+    char *filehost;
+    const char *fileuser;
+    char *ptmp = NULL;
+    char *result = NULL;
+    FILE *fp = NULL;
+    int found;
+    struct stat sbuf;
+    char n1[NUM_STR_SIZE];
+    char n2[NUM_STR_SIZE];
+    int hostmatch;
+    int usermatch;
+    uid_t localuid;
+    char *localuser = NULL;
+
+    /*
+     * Save copies of what we need from the passwd structure in case
+     * any other code calls getpw*.
+     */
+    localuid = pwd->pw_uid;
+    localuser = stralloc(pwd->pw_name);
+
+    ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
+#if defined(SHOW_SECURITY_DETAIL)                              /* { */
+    show_stat_info(ptmp, "");;
+#endif                                                         /* } */
+    if ((fp = fopen(ptmp, "r")) == NULL) {
+       result = vstralloc("cannot open ", ptmp, ": ", strerror(errno), NULL);
+       amfree(ptmp);
+       amfree(localuser);
+       return result;
+    }
+
+    /*
+     * Make sure the file is owned by the Amanda user and does not
+     * have any group/other access allowed.
+     */
+    if (fstat(fileno(fp), &sbuf) != 0) {
+       result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL);
+       goto common_exit;
+    }
+    if (sbuf.st_uid != localuid) {
+       snprintf(n1, sizeof(n1), "%ld", (long)sbuf.st_uid);
+       snprintf(n2, sizeof(n2), "%ld", (long)localuid);
+       result = vstralloc(ptmp, ": ",
+                          "owned by id ", n1,
+                          ", should be ", n2,
+                          NULL);
+       goto common_exit;
+    }
+    if ((sbuf.st_mode & 077) != 0) {
+       result = stralloc2(ptmp,
+         ": incorrect permissions; file must be accessible only by its owner");
+       goto common_exit;
+    }
+
+    /*
+     * Now, scan the file for the host/user.
+     */
+    found = 0;
+    while ((line = agets(fp)) != NULL) {
+#if defined(SHOW_SECURITY_DETAIL)                              /* { */
+       bsdprintf(("%s: processing line: <%s>\n", debug_prefix(NULL), line));
+#endif                                                         /* } */
+       /* get the host out of the file */
+       if ((filehost = strtok(line, " \t")) == NULL) {
+           amfree(line);
+           continue;
+       }
+
+       /* get the username.  If no user specified, then use the local user */
+       if ((fileuser = strtok(NULL, " \t")) == NULL) {
+           fileuser = localuser;
+       }
+
+       hostmatch = (strcasecmp(filehost, host) == 0);
+       usermatch = (strcasecmp(fileuser, remoteuser) == 0);
+#if defined(SHOW_SECURITY_DETAIL)                              /* { */
+       bsdprintf(("%s: comparing \"%s\" with\n", debug_prefix(NULL), filehost));
+       bsdprintf(("%s:           \"%s\" (%s)\n", host,
+                 debug_prefix(NULL), hostmatch ? "match" : "no match"));
+       bsdprintf(("%s:       and \"%s\" with\n", fileuser, debug_prefix(NULL)));
+       bsdprintf(("%s:           \"%s\" (%s)\n", remoteuser,
+                 debug_prefix(NULL), usermatch ? "match" : "no match"));
+#endif                                                         /* } */
+       amfree(line);
+       /* compare */
+       if (hostmatch && usermatch) {
+           /* success */
+           found = 1;
+           break;
+       }
+    }
+    if (! found) {
+       result = vstralloc(ptmp, ": ",
+                          "\"", host, " ", remoteuser, "\"",
+                          " entry not found",
+                          NULL);
+    }
+
+common_exit:
+
+    afclose(fp);
+    amfree(ptmp);
+    amfree(line);
+    amfree(localuser);
+
+    return result;
+}
+
+/* return 1 on success, 0 on failure */
+int
+check_security(addr, str, cksum, errstr)
+struct sockaddr_in *addr;
+char *str;
+unsigned long cksum;
+char **errstr;
+{
+    char *remotehost = NULL, *remoteuser = NULL;
+    char *bad_bsd = NULL;
+    struct hostent *hp;
+    struct passwd *pwptr;
+    int myuid, i, j;
+    char *s, *fp;
+    int ch;
+
+    *errstr = NULL;
+
+    /* what host is making the request? */
+
+    hp = gethostbyaddr((char *)&addr->sin_addr, sizeof(addr->sin_addr),
+                      AF_INET);
+    if(hp == NULL) {
+       /* XXX include remote address in message */
+       *errstr = vstralloc("[",
+                           "addr ", inet_ntoa(addr->sin_addr), ": ",
+                           "hostname lookup failed",
+                           "]", NULL);
+       return 0;
+    }
+    remotehost = stralloc(hp->h_name);
+
+    /* Now let's get the hostent for that hostname */
+    hp = gethostbyname( remotehost );
+    if(hp == NULL) {
+       /* XXX include remote hostname in message */
+       *errstr = vstralloc("[",
+                           "host ", remotehost, ": ",
+                           "hostname lookup failed",
+                           "]", NULL);
+       amfree(remotehost);
+       return 0;
+    }
+
+    /* Verify that the hostnames match -- they should theoretically */
+    if( strncasecmp( remotehost, hp->h_name, strlen(remotehost)+1 ) != 0 ) {
+       *errstr = vstralloc("[",
+                           "hostnames do not match: ",
+                           remotehost, " ", hp->h_name,
+                           "]", NULL);
+       amfree(remotehost);
+       return 0;
+    }
+
+    /* Now let's verify that the ip which gave us this hostname
+     * is really an ip for this hostname; or is someone trying to
+     * break in? (THIS IS THE CRUCIAL STEP)
+     */
+    for (i = 0; hp->h_addr_list[i]; i++) {
+       if (memcmp(hp->h_addr_list[i],
+                  (char *) &addr->sin_addr, sizeof(addr->sin_addr)) == 0)
+           break;                     /* name is good, keep it */
+    }
+
+    /* If we did not find it, your DNS is messed up or someone is trying
+     * to pull a fast one on you. :(
+     */
+
+   /*   Check even the aliases list. Work around for Solaris if dns goes over NIS */
+
+    if( !hp->h_addr_list[i] ) {
+        for (j = 0; hp->h_aliases[j] !=0 ; j++) {
+            if ( strcmp(hp->h_aliases[j],inet_ntoa(addr->sin_addr)) == 0)
+                break;                          /* name is good, keep it */
+        }
+       if( !hp->h_aliases[j] ) {
+           *errstr = vstralloc("[",
+                               "ip address ", inet_ntoa(addr->sin_addr),
+                               " is not in the ip list for ", remotehost,
+                               "]",
+                               NULL);
+           amfree(remotehost);
+           return 0;
+       }
+    }
+
+    /* next, make sure the remote port is a "reserved" one */
+
+    if(ntohs(addr->sin_port) >= IPPORT_RESERVED) {
+       char number[NUM_STR_SIZE];
+
+       snprintf(number, sizeof(number), "%d", ntohs(addr->sin_port));
+       *errstr = vstralloc("[",
+                           "host ", remotehost, ": ",
+                           "port ", number, " not secure",
+                           "]", NULL);
+       amfree(remotehost);
+       return 0;
+    }
+
+    /* extract the remote user name from the message */
+
+    s = str;
+    ch = *s++;
+
+    bad_bsd = vstralloc("[",
+                       "host ", remotehost, ": ",
+                       "bad bsd security line",
+                       "]", NULL);
+
+#define sc "USER "
+    if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
+       *errstr = bad_bsd;
+       bad_bsd = NULL;
+       amfree(remotehost);
+       return 0;
+    }
+    s += sizeof(sc)-1;
+    ch = s[-1];
+#undef sc
+
+    skip_whitespace(s, ch);
+    if(ch == '\0') {
+       *errstr = bad_bsd;
+       bad_bsd = NULL;
+       amfree(remotehost);
+       return 0;
+    }
+    fp = s - 1;
+    skip_non_whitespace(s, ch);
+    s[-1] = '\0';
+    remoteuser = stralloc(fp);
+    s[-1] = ch;
+    amfree(bad_bsd);
+
+    /* lookup our local user name */
+
+    myuid = getuid();
+    if((pwptr = getpwuid(myuid)) == NULL)
+        error("error [getpwuid(%d) fails]", myuid);
+
+    dbprintf(("bsd security: remote host %s user %s local user %s\n",
+             remotehost, remoteuser, pwptr->pw_name));
+
+#ifndef USE_AMANDAHOSTS
+    s = check_user_ruserok(remotehost, pwptr, remoteuser);
+#else
+    s = check_user_amandahosts(remotehost, pwptr, remoteuser);
+#endif
+
+    if (s != NULL) {
+       *errstr = vstralloc("[",
+                           "access as ", pwptr->pw_name, " not allowed",
+                           " from ", remoteuser, "@", remotehost,
+                           ": ", s, "]", NULL);
+    }
+    amfree(s);
+    amfree(remotehost);
+    amfree(remoteuser);
+    return *errstr == NULL;
+}
+
+
+/*
+ * Create the server end of a stream.  For bsd, this means setup a tcp
+ * socket for receiving a connection.
+ */
+static void *
+bsd_stream_server(h)
+    void *h;
+{
+    struct bsd_stream *bs = NULL;
+#ifndef TEST                                                   /* { */
+    struct bsd_handle *bh = h;
+
+    assert(bh != NULL);
+
+    bs = alloc(sizeof(*bs));
+    security_streaminit(&bs->secstr, &bsd_security_driver);
+    bs->socket = stream_server(&bs->port, STREAM_BUFSIZE, STREAM_BUFSIZE);
+    if (bs->socket < 0) {
+       security_seterror(&bh->sech,
+           "can't create server stream: %s", strerror(errno));
+       amfree(bs);
+       return (NULL);
+    }
+    bs->fd = -1;
+    bs->ev_read = NULL;
+#endif /* !TEST */                                             /* } */
+    return (bs);
+}
+
+/*
+ * Accepts a new connection on unconnected streams.  Assumes it is ok to
+ * block on accept()
+ */
+static int
+bsd_stream_accept(s)
+    void *s;
+{
+#ifndef TEST                                                   /* { */
+    struct bsd_stream *bs = s;
+
+    assert(bs != NULL);
+    assert(bs->socket != -1);
+    assert(bs->fd < 0);
+
+    bs->fd = stream_accept(bs->socket, 30, -1, -1);
+    if (bs->fd < 0) {
+       security_stream_seterror(&bs->secstr,
+           "can't accept new stream connection: %s", strerror(errno));
+       return (-1);
+    }
+#endif /* !TEST */                                             /* } */
+    return (0);
+}
+
+/*
+ * Return a connected stream
+ */
+static void *
+bsd_stream_client(h, id)
+    void *h;
+    int id;
+{
+    struct bsd_stream *bs = NULL;
+#ifndef TEST                                                   /* { */
+    struct bsd_handle *bh = h;
+#ifdef DUMPER_SOCKET_BUFFERING
+    int rcvbuf = sizeof(bs->databuf) * 2;
+#endif
+
+    assert(bh != NULL);
+
+    if (id < 0) {
+       security_seterror(&bh->sech,
+           "%d: invalid security stream id", id);
+       return (NULL);
+    }
+
+    bs = alloc(sizeof(*bs));
+    security_streaminit(&bs->secstr, &bsd_security_driver);
+    bs->fd = stream_client(bh->hostname, id, STREAM_BUFSIZE, STREAM_BUFSIZE,
+       &bs->port, 0);
+    if (bs->fd < 0) {
+       security_seterror(&bh->sech,
+           "can't connect stream to %s port %d: %s", bh->hostname,
+           id, strerror(errno));
+       amfree(bs);
+       return (NULL);
+    }
+    bs->socket = -1;   /* we're a client */
+    bs->ev_read = NULL;
+#ifdef DUMPER_SOCKET_BUFFERING
+    setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf));
+#endif
+#endif /* !TEST */                                             /* } */
+    return (bs);
+}
+
+/*
+ * Close and unallocate resources for a stream
+ */
+static void
+bsd_stream_close(s)
+    void *s;
+{
+    struct bsd_stream *bs = s;
+
+    assert(bs != NULL);
+
+    if (bs->fd != -1)
+       aclose(bs->fd);
+    if (bs->socket != -1)
+       aclose(bs->socket);
+    bsd_stream_read_cancel(bs);
+    amfree(bs);
+}
+
+/*
+ * Authenticate a stream.  bsd streams have no authentication
+ */
+static int
+bsd_stream_auth(s)
+    void *s;
+{
+
+    return (0);        /* success */
+}
+
+/*
+ * Returns the stream id for this stream.  This is just the local port.
+ */
+static int
+bsd_stream_id(s)
+    void *s;
+{
+    struct bsd_stream *bs = s;
+
+    assert(bs != NULL);
+
+    return (bs->port);
+}
+
+/*
+ * Write a chunk of data to a stream.  Blocks until completion.
+ */
+static int
+bsd_stream_write(s, buf, size)
+    void *s;
+    const void *buf;
+    size_t size;
+{
+#ifndef TEST                                                   /* { */
+    struct bsd_stream *bs = s;
+
+    assert(bs != NULL);
+
+    if (fullwrite(bs->fd, buf, size) < 0) {
+       security_stream_seterror(&bs->secstr,
+           "write error on stream %d: %s", bs->port, strerror(errno));
+       return (-1);
+    }
+#endif /* !TEST */                                             /* } */
+    return (0);
+}
+
+/*
+ * Submit a request to read some data.  Calls back with the given function
+ * and arg when completed.
+ */
+static void
+bsd_stream_read(s, fn, arg)
+    void *s, *arg;
+    void (*fn) P((void *, void *, ssize_t));
+{
+    struct bsd_stream *bs = s;
+
+    /*
+     * Only one read request can be active per stream.
+     */
+    if (bs->ev_read != NULL)
+       event_release(bs->ev_read);
+
+    bs->ev_read = event_register(bs->fd, EV_READFD, stream_read_callback, bs);
+    bs->fn = fn;
+    bs->arg = arg;
+}
+
+/*
+ * Cancel a previous stream read request.  It's ok if we didn't
+ * have a read scheduled.
+ */
+static void
+bsd_stream_read_cancel(s)
+    void *s;
+{
+    struct bsd_stream *bs = s;
+
+    assert(bs != NULL);
+
+    if (bs->ev_read != NULL) {
+       event_release(bs->ev_read);
+       bs->ev_read = NULL;
+    }
+}
+
+/*
+ * Callback for bsd_stream_read
+ */
+static void
+stream_read_callback(arg)
+    void *arg;
+{
+    struct bsd_stream *bs = arg;
+    ssize_t n;
+
+    assert(bs != NULL);
+
+    /*
+     * Remove the event first, in case they reschedule it in the callback.
+     */
+    bsd_stream_read_cancel(bs);
+    do {
+       n = read(bs->fd, bs->databuf, sizeof(bs->databuf));
+    } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
+    if (n < 0)
+       security_stream_seterror(&bs->secstr, strerror(errno));
+    (*bs->fn)(bs->arg, bs->databuf, n);
+}
+
+/*
+ * Convert a packet header into a string
+ */
+static const char *
+pkthdr2str(bh, pkt)
+    const struct bsd_handle *bh;
+    const pkt_t *pkt;
+{
+    static char retbuf[256];
+
+    assert(bh != NULL);
+    assert(pkt != NULL);
+
+    snprintf(retbuf, sizeof(retbuf), "Amanda %d.%d %s HANDLE %s SEQ %d\n",
+       VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
+       bh->proto_handle, bh->sequence);
+
+    bsdprintf(("%s: pkthdr2str handle '%s'\n",
+              debug_prefix_time(NULL), bh->proto_handle));
+
+    /* check for truncation.  If only we had asprintf()... */
+    assert(retbuf[strlen(retbuf) - 1] == '\n');
+
+    return (retbuf);
+}
+
+/*
+ * Parses out the header line in 'str' into the pkt and handle
+ * Returns negative on parse error.
+ */
+static int
+str2pkthdr()
+{
+    char *str;
+    const char *tok;
+    pkt_t *pkt;
+
+    pkt = &netfd.pkt;
+
+    assert(netfd.dgram.cur != NULL);
+    str = stralloc(netfd.dgram.cur);
+
+    /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
+
+    /* Read in "Amanda" */
+    if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
+       goto parse_error;
+
+    /* nothing is done with the major/minor numbers currently */
+    if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
+       goto parse_error;
+
+    /* Read in the packet type */
+    if ((tok = strtok(NULL, " ")) == NULL)
+       goto parse_error;
+    pkt_init(pkt, pkt_str2type(tok), "");
+    if (pkt->type == (pktype_t)-1)    
+       goto parse_error;
+
+    /* Read in "HANDLE" */
+    if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
+       goto parse_error;
+
+    /* parse the handle */
+    if ((tok = strtok(NULL, " ")) == NULL)
+       goto parse_error;
+    netfd.handle = stralloc(tok);
+
+    /* Read in "SEQ" */
+    if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)   
+       goto parse_error;
+
+    /* parse the sequence number */   
+    if ((tok = strtok(NULL, "\n")) == NULL)
+       goto parse_error;
+    netfd.sequence = atoi(tok);
+
+    /* Save the body, if any */       
+    if ((tok = strtok(NULL, "")) != NULL)
+       pkt_cat(pkt, "%s", tok);
+
+    amfree(str);
+    return (0);
+
+parse_error:
+#if 0 /* XXX we have no way of passing this back up */
+    security_seterror(&bh->sech,
+       "parse error in packet header : '%s'", origstr);
+#endif
+    amfree(str);
+    return (-1);
+}
+
+#endif /* BSD_SECURITY */                                      /* } */
+
+#if defined(TEST)                                              /* { */
+
+/*
+ * The following dummy bind_portrange function is so we do not need to
+ * drag in util.o just for the test program.
+ */
+int
+bind_portrange(s, addrp, first_port, last_port, proto)
+    int s;
+    struct sockaddr_in *addrp;
+    int first_port, last_port;
+    char *proto;
+{
+    return 0;
+}
+
+/*
+ * Construct a datestamp (YYYYMMDD) from a time_t.
+ */
+char *
+construct_datestamp(t)
+    time_t *t;
+{
+    struct tm *tm;
+    char datestamp[3*NUM_STR_SIZE];
+    time_t when;
+
+    if(t == NULL) {
+       when = time((time_t *)NULL);
+    } else {
+       when = *t;
+    }
+    tm = localtime(&when);
+    snprintf(datestamp, sizeof(datestamp),
+             "%04d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
+    return stralloc(datestamp);
+}
+
+/*
+ * Construct a timestamp (YYYYMMDDHHMMSS) from a time_t.
+ */
+char *
+construct_timestamp(t)
+    time_t *t;
+{
+    struct tm *tm;
+    char timestamp[6*NUM_STR_SIZE];
+    time_t when;
+
+    if(t == NULL) {
+       when = time((time_t *)NULL);
+    } else {
+       when = *t;
+    }
+    tm = localtime(&when);
+    snprintf(timestamp, sizeof(timestamp),
+            "%04d%02d%02d%02d%02d%02d",
+            tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+            tm->tm_hour, tm->tm_min, tm->tm_sec);
+    return stralloc(timestamp);
+}
+
+/*
+ * The following are so we can include security.o but not all the rest
+ * of the security modules.
+ */
+const security_driver_t krb4_security_driver = {};
+const security_driver_t krb5_security_driver = {};
+const security_driver_t rsh_security_driver = {};
+
+/*
+ * This function will be called to accept the connection and is used
+ * to report success or failure.
+ */
+static void fake_accept_function(handle, pkt)
+    security_handle_t *handle;
+    pkt_t *pkt;
+{
+    if (pkt == NULL) {
+       fputs(handle->error, stdout);
+       fputc('\n', stdout);
+    } else {
+       fputs("access is allowed\n", stdout);
+    }
+}
+
+int
+main (argc, argv)
+{
+    char *remoteuser;
+    char *remotehost;
+    struct hostent *hp;
+    struct bsd_handle *bh;
+    void *save_cur;
+    struct passwd *pwent;
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    /*
+     * The following is stolen from amandad to emulate what it would
+     * do on startup.
+     */
+    if(client_uid == (uid_t) -1 && (pwent = getpwnam(CLIENT_LOGIN)) != NULL) {
+       client_uid = pwent->pw_uid;
+       client_gid = pwent->pw_gid;
+       endpwent();
+    }
+
+#ifdef FORCE_USERID
+    /* we'd rather not run as root */
+    if (geteuid() == 0) {
+       if(client_uid == (uid_t) -1) {
+           error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN);
+       }
+       initgroups(CLIENT_LOGIN, client_gid);
+       setgid(client_gid);
+       setegid(client_gid);
+       seteuid(client_uid);
+    }
+#endif /* FORCE_USERID */
+
+    if (isatty(0)) {
+       fputs("Remote user: ", stdout);
+       fflush(stdout);
+    }
+    if ((remoteuser = agets(stdin)) == NULL) {
+       return 0;
+    }
+
+    if (isatty(0)) {
+       fputs("Remote host: ", stdout);
+       fflush(stdout);
+    }
+    if ((remotehost = agets(stdin)) == NULL) {
+       return 0;
+    }
+
+    set_pname("security");
+    startclock();
+
+    if ((hp = gethostbyname(remotehost)) == NULL) {
+       fprintf(stderr, "cannot look up remote host %s\n", remotehost);
+       return 1;
+    }
+    memcpy((char *)&netfd.peer.sin_addr,
+          (char *)hp->h_addr,
+          sizeof(hp->h_addr));
+    /*
+     * Fake that it is coming from a reserved port.
+     */
+    netfd.peer.sin_port = htons(IPPORT_RESERVED - 1);
+
+    bh = alloc(sizeof(*bh));
+    bh->proto_handle=NULL;
+    netfd.pkt.type = P_REQ;
+    dgram_zero(&netfd.dgram);
+    save_cur = netfd.dgram.cur;                                /* cheating */
+    dgram_cat(&netfd.dgram, "%s", pkthdr2str(bh, &netfd.pkt));
+    dgram_cat(&netfd.dgram, "SECURITY USER %s\n", remoteuser);
+    netfd.dgram.cur = save_cur;                                /* cheating */
+
+    accept_fn = fake_accept_function;
+    netfd_read_callback(NULL);
+
+    return 0;
+}
+
+#endif                                                         /* } */
index 840992f86378f45c85cf06960eee3667e799c718..732b4ef01b578b3b57c1a4e0ca16b53ad572851d 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: clock.c,v 1.2.2.2 2002/03/31 21:01:33 jrjackson Exp $
+ * $Id: clock.c,v 1.5 2002/04/08 00:16:18 jrjackson Exp $
  *
  * timing functions
  */
@@ -41,12 +41,6 @@ times_t times_zero = {{0,0}};
 times_t start_time;
 static int clock_running = 0;
 
-#ifdef HAVE_TWO_ARG_GETTIMEOFDAY
-#  define amanda_gettimeofday(x, y) gettimeofday((x), (y))
-#else
-#  define amanda_gettimeofday(x, y) gettimeofday((x))
-#endif
-
 int clock_is_running()
 {
     return clock_running;
@@ -54,9 +48,7 @@ int clock_is_running()
 
 void startclock()
 {
-#ifdef HAVE_TWO_ARG_GETTIMEOFDAY
-    struct timezone dontcare;
-#endif
+    amanda_timezone dontcare;
 
     clock_running = 1;
     amanda_gettimeofday(&start_time.r, &dontcare);
@@ -66,10 +58,7 @@ times_t stopclock()
 {
     times_t diff;
     struct timeval end_time;
-
-#ifdef HAVE_TWO_ARG_GETTIMEOFDAY
-    struct timezone dontcare;
-#endif
+    amanda_timezone dontcare;
 
     if(!clock_running) {
        fprintf(stderr,"stopclock botch\n");
@@ -85,10 +74,7 @@ times_t curclock()
 {
     times_t diff;
     struct timeval end_time;
-
-#ifdef HAVE_TWO_ARG_GETTIMEOFDAY
-    struct timezone dontcare;
-#endif
+    amanda_timezone dontcare;
 
     if(!clock_running) {
        fprintf(stderr,"curclock botch\n");
@@ -125,7 +111,7 @@ times_t t;
     char *s;
 
     /* tv_sec/tv_usec are longs on some systems */
-    ap_snprintf(str[n], sizeof(str[n]),
+    snprintf(str[n], sizeof(str[n]),
                "rtime %d.%03d", (int)t.r.tv_sec, (int)t.r.tv_usec/1000);
     s = str[n++];
     n %= am_countof(str);
@@ -140,7 +126,7 @@ times_t t;
     char *s;
 
     /* tv_sec/tv_usec are longs on some systems */
-    ap_snprintf(str[n], sizeof(str[n]),
+    snprintf(str[n], sizeof(str[n]),
                "%d.%03d", (int)t.r.tv_sec, (int)t.r.tv_usec/1000);
     s = str[n++];
     n %= am_countof(str);
index 8d3922e2dd2694e3f3d916c0409d9febb4776c1a..4da1cfca8757559e6f29bb2fbc65653b1e3cb89a 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: clock.h,v 1.2.2.2 2002/03/31 21:01:33 jrjackson Exp $
+ * $Id: clock.h,v 1.5 2002/04/08 00:16:18 jrjackson Exp $
  *
  * interface for timing functions
  */
@@ -44,6 +44,14 @@ typedef struct times_s {
 
 extern times_t times_zero, start_time;
 
+#ifdef HAVE_TWO_ARG_GETTIMEOFDAY
+#  define amanda_timezone struct timezone
+#  define amanda_gettimeofday(x, y) gettimeofday((x), (y))
+#else
+#  define amanda_timezone int
+#  define amanda_gettimeofday(x, y) gettimeofday((x))
+#endif
+
 void startclock P((void));
 times_t stopclock P((void));
 times_t curclock P((void));
index ce546bc37801dd89a44c482bf2d30a47cfee2696..66d31bd42c409247d4e8a5c9f9b847be6703a64c 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: debug.c,v 1.17.4.3.4.3.2.9.2.1 2005/09/20 19:06:37 jrjackson Exp $
+ * $Id: debug.c,v 1.36 2006/01/12 01:57:05 paddy_s Exp $
  *
  * debug log subroutines
  */
 
 #include "amanda.h"
-#include "clock.h"
 #include "util.h"
 #include "arglist.h"
+#include "clock.h"
 
 #ifndef AMANDA_DBGDIR
 #  define AMANDA_DBGDIR                AMANDA_TMPDIR
@@ -54,7 +54,7 @@ static pid_t debug_prefix_pid = 0;
 /*
  * Format and write a debug message to the process debug file.
  */
-printf_arglist_function(void debug_printf, char *, format)
+printf_arglist_function(void debug_printf, const char *, format)
 {
     va_list argp;
     int save_errno;
@@ -100,7 +100,7 @@ get_debug_name(t, n)
     if(n == 0) {
        number[0] = '\0';
     } else {
-       ap_snprintf(number, sizeof(number), "%03d", n - 1);
+       snprintf(number, sizeof(number), "%03d", n - 1);
     }
     result = vstralloc(get_pname(), ".", ts, number, ".debug", NULL);
     amfree(ts);
@@ -260,6 +260,7 @@ void debug_open()
     int fd = -1;
     int i;
     char *s = NULL;
+    mode_t mask;
 
     /*
      * Do initial setup.
@@ -267,17 +268,31 @@ void debug_open()
     debug_setup_1();
 
     /*
-     * Create the new file.
+     * Create the new file with a unique sequence number.
      */
-    for(i = 0;
-       (dbfilename = get_debug_name(curtime, i)) != NULL
-       && (s = newvstralloc(s, dbgdir, dbfilename, NULL)) != NULL
-       && (fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0600)) < 0;
-       i++, free(dbfilename)) {}
-    if(dbfilename == NULL) {
-       error("cannot create %s debug file", get_pname());
+    mask = umask(0037); /* Allow the group read bit through */
+    for(i = 0; fd < 0; i++) {
+        if ((dbfilename = get_debug_name(curtime, i)) == NULL) {
+           error("Cannot create %s debug file", get_pname());
+            /* NOTREACHED */
+        }
+
+        if ((s = newvstralloc(s, dbgdir, dbfilename, NULL)) == NULL) {
+           error("Cannot allocate %s debug file name memory", get_pname());
+            /* NOTREACHED */
+        }
+        amfree(dbfilename);
+
+        if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
+            if (errno != EEXIST) {
+                error("Cannot create %s debug file: %s",
+                       get_pname(), strerror(errno));
+                /* NOTREACHED */
+            }
+            amfree(s);
+        }
     }
-    amfree(dbfilename);
+    (void)umask(mask); /* Restore mask */
 
     /*
      * Finish setup.
@@ -311,7 +326,7 @@ void debug_reopen(dbfilename, notation)
     } else {
        s = newvstralloc(s, dbgdir, dbfilename, NULL);
     }
-    if ((fd = open(s, O_RDWR|O_APPEND, 0600)) < 0) {
+    if ((fd = open(s, O_RDWR|O_APPEND)) < 0) {
        error("cannot reopen %s debug file %s", get_pname(), dbfilename);
     }
 
@@ -383,26 +398,31 @@ void set_debug_prefix_pid(p)
 char *debug_prefix(suffix)
     char *suffix;
 {
+    int save_errno;
     static char *s = NULL;
     char debug_pid[NUM_STR_SIZE];
 
+    save_errno = errno;
     s = newvstralloc(s, get_pname(), suffix, NULL);
     if (debug_prefix_pid != (pid_t) 0) {
-       ap_snprintf(debug_pid, sizeof(debug_pid),
-                   "%ld",
-                   (long) debug_prefix_pid);
+       snprintf(debug_pid, sizeof(debug_pid),
+                "%ld",
+                (long) debug_prefix_pid);
        s = newvstralloc(s, s, "[", debug_pid, "]", NULL);
     }
+    errno = save_errno;
     return s;
 }
 
 char *debug_prefix_time(suffix)
     char *suffix;
 {
+    int save_errno;
     static char *s = NULL;
     char *t1;
     char *t2;
 
+    save_errno = errno;
     if (clock_is_running()) {
        t1 = ": time ";
        t2 = walltime_str(curclock());
@@ -412,6 +432,7 @@ char *debug_prefix_time(suffix)
 
     s = newvstralloc(s, debug_prefix(suffix), t1, t2, NULL);
 
+    errno = save_errno;
     return s;
 }
 #endif
index 60ba12369b0699299b56961b80c60fcea5426c5f..cdf8a09912110f1f414e625c193afe2242b89959 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  *                        University of Maryland at College Park
  */
 /* 
- * $Id: dgram.c,v 1.11.2.3.4.3.2.4 2002/11/12 19:19:03 martinea Exp $
+ * $Id: dgram.c,v 1.29 2006/01/12 01:57:05 paddy_s Exp $
  *
  * library routines to marshall/send, recv/unmarshall UDP packets
  */
 #include "amanda.h"
+#include "arglist.h"
 #include "dgram.h"
 #include "util.h"
 
@@ -79,17 +80,19 @@ int *portp;
      * If a port range was specified, we try to get a port in that
      * range first.  Next, we try to get a reserved port.  If that
      * fails, we just go for any port.
+     * 
+     * In all cases, not to use port that's assigned to other services. 
      *
      * It is up to the caller to make sure we have the proper permissions
      * to get the desired port, and to make sure we return a port that
      * is within the range it requires.
      */
 #ifdef UDPPORTRANGE
-    if (bind_portrange(s, &name, UDPPORTRANGE) == 0)
+    if (bind_portrange(s, &name, UDPPORTRANGE, "udp") == 0)
        goto out;
 #endif
 
-    if (bind_portrange(s, &name, 512, IPPORT_RESERVED - 1) == 0)
+    if (bind_portrange(s, &name, 512, IPPORT_RESERVED - 1, "udp") == 0)
        goto out;
 
     name.sin_port = INADDR_ANY;
@@ -118,6 +121,7 @@ out:
     }
     *portp = ntohs(name.sin_port);
     dgram->socket = s;
+
     dbprintf(("%s: dgram_bind: socket bound to %s.%d\n",
              debug_prefix_time(NULL),
              inet_ntoa(name.sin_addr),
@@ -182,6 +186,17 @@ dgram_t *dgram;
                      wait_count));
            continue;
        }
+#endif
+#ifdef EAGAIN
+       if(errno == EAGAIN && wait_count++ < max_wait) {
+           sleep(5);
+           dbprintf(("%s: dgram_send_addr: sendto(%s.%d): retry %d after EAGAIN\n",
+                     debug_prefix_time(NULL),
+                     inet_ntoa(addr_save.sin_addr),
+                     (int) ntohs(addr.sin_port),
+                     wait_count));
+           continue;
+       }
 #endif
        save_errno = errno;
        dbprintf(("%s: dgram_send_addr: sendto(%s.%d) failed: %s \n",
@@ -313,33 +328,25 @@ dgram_t *dgram;
     *(dgram->cur) = '\0';
 }
 
-dgram_t *debug_dgram_alloc(s, l)
-char *s;
-int l;
+printf_arglist_function1(void dgram_cat, dgram_t *, dgram, const char *, fmt)
 {
-    dgram_t *p;
+    size_t bufsize;
+    va_list argp;
 
-    malloc_enter(dbmalloc_caller_loc(s, l));
-    p = (dgram_t *) alloc(sizeof(dgram_t));
-    dgram_zero(p);
-    p->socket = -1;
-    malloc_leave(dbmalloc_caller_loc(s, l));
+    assert(dgram != NULL);
+    assert(fmt != NULL);
 
-    return p;
-}
+    assert(dgram->len == dgram->cur - dgram->data);
+    assert(dgram->len >= 0 && dgram->len < sizeof(dgram->data));
 
+    bufsize = sizeof(dgram->data) - dgram->len;
+    if (bufsize <= 0)
+       return;
 
-void dgram_cat(dgram, str)
-dgram_t *dgram;
-const char *str;
-{
-    int len = strlen(str);
-
-    if(dgram->len + len > MAX_DGRAM) len = MAX_DGRAM - dgram->len;
-    strncpy(dgram->cur, str, len);
-    dgram->cur += len;
-    dgram->len += len;
-    *(dgram->cur) = '\0';
+    arglist_start(argp, fmt);
+    dgram->len += vsnprintf(dgram->cur, bufsize, fmt, argp);
+    dgram->cur = dgram->data + dgram->len;
+    arglist_end(argp);
 }
 
 void dgram_eatline(dgram)
index 6a58346f632f8dd515361dbe64b015c6c217e926..01edece2089ac2143c3e7e0cd11550176c461aff 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: dgram.h,v 1.6.2.2.4.1.2.1 2002/03/24 19:23:23 jrjackson Exp $
+ * $Id: dgram.h,v 1.13 2001/07/13 22:38:05 jrjackson Exp $
  *
  * interface for datagram module
  */
@@ -54,11 +54,8 @@ int dgram_send P((char *hostname, int port, dgram_t *dgram));
 int dgram_send_addr P((struct sockaddr_in addr, dgram_t *dgram));
 int dgram_recv P((dgram_t *dgram, int timeout, struct sockaddr_in *fromaddr));
 void dgram_zero P((dgram_t *dgram));
-void dgram_cat P((dgram_t *dgram, const char *str));
+void dgram_cat P((dgram_t *dgram, const char *fmt, ...))
+    __attribute__ ((format (printf, 2, 3)));
 void dgram_eatline P((dgram_t *dgram));
 
-extern dgram_t  *debug_dgram_alloc  P((char *c, int l));
-
-#define        dgram_alloc()           debug_dgram_alloc(__FILE__, __LINE__)
-
 #endif /* ! DGRAM_H */
index 5ce8b468bc2d9a3bce1f58cba589a66f80979f2d..1b6f9478a02e663daa1a2699d1cd6226b3aee251 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: error.c,v 1.8.4.1.2.2.2.4 2003/04/27 01:17:50 martinea Exp $
+ * $Id: error.c,v 1.18 2003/04/27 01:17:19 martinea Exp $
  *
  * error handling common to Amanda programs
  */
@@ -97,7 +97,7 @@ char *msg;
  * Prints an error message, calls the functions installed via onerror(),
  * then exits.
  */
-printf_arglist_function(void error, char *, format)
+printf_arglist_function(void error, const char *, format)
 {
     va_list argp;
     int i;
@@ -107,7 +107,7 @@ printf_arglist_function(void error, char *, format)
     /* format and output the error message */
 
     arglist_start(argp, format);
-    ap_vsnprintf(linebuf, sizeof(linebuf), format, argp);
+    vsnprintf(linebuf, sizeof(linebuf), format, argp);
     arglist_end(argp);
     output_error_message(linebuf);
 
@@ -126,7 +126,7 @@ printf_arglist_function(void error, char *, format)
  * Prints an error message, calls the functions installed via onerror(),
  * then calls abort() to drop core.
  */
-printf_arglist_function(void errordump, char *, format)
+printf_arglist_function(void errordump, const char *, format)
 {
     va_list argp;
     int i;
@@ -135,7 +135,7 @@ printf_arglist_function(void errordump, char *, format)
     /* format error message */
 
     arglist_start(argp, format);
-    ap_vsnprintf(linebuf, sizeof(linebuf), format, argp);
+    vsnprintf(linebuf, sizeof(linebuf), format, argp);
     arglist_end(argp);
     output_error_message(linebuf);
 
diff --git a/common-src/event.c b/common-src/event.c
new file mode 100644 (file)
index 0000000..6809ca1
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: event.c,v 1.20 2005/10/02 15:31:07 martinea Exp $
+ *
+ * Event handler.  Serializes different kinds of events to allow for
+ * a uniform interface, central state storage, and centralized
+ * interdependency logic.
+ */
+
+/*#define      EVENT_DEBUG*/
+
+#ifdef EVENT_DEBUG
+#define eventprintf(x)    dbprintf(x)
+#else
+#define eventprintf(x)
+#endif
+
+#include "amanda.h"
+#include "event.h"
+#include "queue.h"
+
+/*
+ * The opaque handle passed back to the caller.  This is typedefed to
+ * event_handle_t in our header file.
+ */
+struct event_handle {
+    event_fn_t fn;             /* function to call when this fires */
+    void *arg;                 /* argument to pass to previous function */
+    event_type_t type;         /* type of event */
+    event_id_t data;           /* type data */
+    time_t lastfired;          /* timestamp of last fired (EV_TIME only) */
+    LIST_ENTRY(event_handle) le; /* queue handle */
+};
+
+/*
+ * eventq is a queue of currently active events.
+ * cache is a queue of unused handles.  We keep a few around to avoid
+ * malloc overhead when doing a lot of register/releases.
+ */
+static struct {
+    LIST_HEAD(, event_handle) listhead;
+    int qlength;
+} eventq = {
+    LIST_HEAD_INITIALIZER(eventq.listhead), 0
+}, cache = {
+    LIST_HEAD_INITIALIZER(eventq.listhead), 0
+};
+#define        eventq_first(q)         LIST_FIRST(&q.listhead)
+#define        eventq_next(eh)         LIST_NEXT(eh, le)
+#define        eventq_add(q, eh)       LIST_INSERT_HEAD(&q.listhead, eh, le);
+#define        eventq_remove(eh)       LIST_REMOVE(eh, le);
+
+/*
+ * How many items we can have in the handle cache before we start
+ * freeing.
+ */
+#define        CACHEDEPTH      10
+
+/*
+ * A table of currently set signal handlers.
+ */
+static struct sigtabent {
+    event_handle_t *handle;    /* handle for this signal */
+    int score;                 /* number of signals recvd since last checked */
+    void (*oldhandler) P((int));/* old handler (for unsetting) */
+} sigtable[NSIG];
+
+#ifdef EVENT_DEBUG
+static const char *event_type2str P((event_type_t));
+#endif
+#define        fire(eh)        (*(eh)->fn)((eh)->arg)
+static void signal_handler P((int));
+static event_handle_t *gethandle P((void));
+static void puthandle P((event_handle_t *));
+
+/*
+ * Add a new event.  See the comment in event.h for what the arguments
+ * mean.
+ */
+event_handle_t *
+event_register(data, type, fn, arg)
+    event_id_t data;
+    event_type_t type;
+    event_fn_t fn;
+    void *arg;
+{
+    event_handle_t *handle;
+
+    switch (type) {
+    case EV_READFD:
+    case EV_WRITEFD:
+       /* make sure we aren't given a high fd that will overflow a fd_set */
+       assert(data < FD_SETSIZE);
+       break;
+
+    case EV_SIG:
+       /* make sure signals are within range */
+       assert(data < NSIG);
+       /* make sure we don't double-register a signal */
+       assert(sigtable[data].handle == NULL);
+       break;
+
+    case EV_TIME:
+    case EV_WAIT:
+       break;
+
+    case EV_DEAD:
+    default:
+       /* callers can't register EV_DEAD */
+       assert(0);
+       break;
+    }
+
+    handle = gethandle();
+    handle->fn = fn;
+    handle->arg = arg;
+    handle->type = type;
+    handle->data = data;
+    handle->lastfired = -1;
+    eventq_add(eventq, handle);
+    eventq.qlength++;
+
+    eventprintf(("%s: event: register: %X data=%lu, type=%s\n", debug_prefix_time(NULL), (int)handle,
+                handle->data, event_type2str(handle->type)));
+    return (handle);
+}
+
+/*
+ * Mark an event to be released.  Because we may be traversing the queue
+ * when this is called, we must wait until later to actually remove
+ * the event.
+ */
+void
+event_release(handle)
+    event_handle_t *handle;
+{
+
+    assert(handle != NULL);
+
+    eventprintf(("%s: event: release (mark): %X data=%lu, type=%s\n", debug_prefix_time(NULL),
+       (int)handle, handle->data, event_type2str(handle->type)));
+    assert(handle->type != EV_DEAD);
+
+    /*
+     * For signal events, we need to specially remove then from the
+     * signal event table.
+     */
+    if (handle->type == EV_SIG) {
+       struct sigtabent *se = &sigtable[handle->data];
+
+       assert(se->handle == handle);
+       signal(handle->data, se->oldhandler);
+       se->handle = NULL;
+       se->score = 0;
+    }
+
+    /*
+     * Decrement the qlength now since this is no longer a real
+     * event.
+     */
+    eventq.qlength--;
+
+    /*
+     * Mark it as dead and leave it for the loop to remove.
+     */
+    handle->type = EV_DEAD;
+}
+
+/*
+ * Fire all EV_WAIT events waiting on the specified id.
+ */
+int
+event_wakeup(id)
+    event_id_t id;
+{
+    event_handle_t *eh;
+    int nwaken = 0;
+
+    eventprintf(("%s: event: wakeup: enter (%lu)\n", debug_prefix_time(NULL), id));
+
+    assert(id >= 0);
+
+    for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) {
+
+       if (eh->type == EV_WAIT && eh->data == id) {
+           eventprintf(("%s: event: wakeup: %X id=%lu\n", debug_prefix_time(NULL), (int)eh, id));
+           fire(eh);
+           nwaken++;
+       }
+    }
+    return (nwaken);
+}
+
+
+/*
+ * The event loop.  We need to be specially careful here with adds and
+ * deletes.  Since adds and deletes will often happen while this is running,
+ * we need to make sure we don't end up referencing a dead event handle.
+ */
+void
+event_loop(dontblock)
+    const int dontblock;
+{
+#ifdef ASSERTIONS
+    static int entry = 0;
+#endif
+    fd_set readfds, writefds, errfds, werrfds;
+    struct timeval timeout, *tvptr;
+    int ntries, maxfd, rc, interval;
+    time_t curtime;
+    event_handle_t *eh, *nexteh;
+    struct sigtabent *se;
+
+    eventprintf(("%s: event: loop: enter: dontblock=%d, qlength=%d\n", debug_prefix_time(NULL),
+                dontblock, eventq.qlength));
+
+    /*
+     * If we have no events, we have nothing to do
+     */
+    if (eventq.qlength == 0)
+       return;
+
+    /*
+     * We must not be entered twice
+     */
+    assert(++entry == 1);
+
+    ntries = 0;
+
+    /*
+     * Save a copy of the current time once, to reduce syscall load
+     * slightly.
+     */
+    curtime = time(NULL);
+
+    do {
+#ifdef EVENT_DEBUG
+       eventprintf(("%s: event: loop: dontblock=%d, qlength=%d\n", debug_prefix_time(NULL), dontblock,
+           eventq.qlength));
+       for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) {
+           eventprintf(("%s: %X: %s data=%lu fn=0x%x arg=0x%x\n", debug_prefix_time(NULL), (int)eh,
+               event_type2str(eh->type), eh->data, (int)eh->fn, (int)eh->arg));
+       }
+#endif
+       /*
+        * Set ourselves up with no timeout initially.
+        */
+       timeout.tv_sec = 0;
+       timeout.tv_usec = 0;
+
+       /*
+        * If we can block, initially set the tvptr to NULL.  If
+        * we come across timeout events in the loop below, they
+        * will set it to an appropriate buffer.  If we don't
+        * see any timeout events, then tvptr will remain NULL
+        * and the select will properly block indefinately.
+        *
+        * If we can't block, set it to point to the timeout buf above.
+        */
+       if (dontblock)
+           tvptr = &timeout;
+       else
+           tvptr = NULL;
+
+       /*
+        * Rebuild the select bitmasks each time.
+        */
+       FD_ZERO(&readfds);
+       FD_ZERO(&writefds);
+       FD_ZERO(&errfds);
+       maxfd = 0;
+
+       /*
+        * Run through each event handle and setup the events.
+        * We save our next pointer early in case we GC some dead
+        * events.
+        */
+       for (eh = eventq_first(eventq); eh != NULL; eh = nexteh) {
+           nexteh = eventq_next(eh);
+
+           switch (eh->type) {
+
+           /*
+            * Read fds just get set into the select bitmask
+            */
+           case EV_READFD:
+               FD_SET(eh->data, &readfds);
+               FD_SET(eh->data, &errfds);
+               maxfd = max(maxfd, eh->data);
+               break;
+
+           /*
+            * Likewise with write fds
+            */
+           case EV_WRITEFD:
+               FD_SET(eh->data, &writefds);
+               FD_SET(eh->data, &errfds);
+               maxfd = max(maxfd, eh->data);
+               break;
+
+           /*
+            * Only set signals that aren't already set to avoid unnecessary
+            * syscall overhead.
+            */
+           case EV_SIG:
+               se = &sigtable[eh->data];
+
+               if (se->handle == eh)
+                   break;
+
+               /* no previous handle */
+               assert(se->handle == NULL);
+               se->handle = eh;
+               se->score = 0;
+               se->oldhandler = signal(eh->data, signal_handler);
+               break;
+
+           /*
+            * Compute the timeout for this select
+            */
+           case EV_TIME:
+               /* if we're not supposed to block, then leave it at 0 */
+               if (dontblock)
+                   break;
+
+               if (eh->lastfired == -1)
+                   eh->lastfired = curtime;
+
+               interval = eh->data - (curtime - eh->lastfired);
+               if (interval < 0)
+                   interval = 0;
+
+               if (tvptr != NULL)
+                   timeout.tv_sec = min(timeout.tv_sec, interval);
+               else {
+                   /* this is the first timeout */
+                   tvptr = &timeout;
+                   timeout.tv_sec = interval;
+               }
+               break;
+
+           /*
+            * Wait events are processed immediately by event_wakeup()
+            */
+           case EV_WAIT:
+               break;
+
+           /*
+            * Prune dead events
+            */
+           case EV_DEAD:
+               eventq_remove(eh);
+               puthandle(eh);
+               break;
+
+           default:
+               assert(0);
+               break;
+           }
+       }
+
+       /*
+        * Let 'er rip
+        */
+       eventprintf(("%s: event: select: dontblock=%d, maxfd=%d, timeout=%ld\n", debug_prefix_time(NULL),
+           dontblock, maxfd, tvptr != NULL ? timeout.tv_sec : -1));
+       rc = select(maxfd + 1, &readfds, &writefds, &errfds, tvptr);
+       eventprintf(("%s: event: select returns %d\n", debug_prefix_time(NULL), rc));
+
+       /*
+        * Select errors can mean many things.  Interrupted events should
+        * not be fatal, since they could be delivered signals which still
+        * need to have their events fired.
+        */
+       if (rc < 0) {
+           if (errno != EINTR) {
+               if (++ntries > 5)
+                   error("select failed: %s", strerror(errno));
+               continue;
+           }
+           /* proceed if errno == EINTR, we may have caught a signal */
+
+           /* contents cannot be trusted */
+           FD_ZERO(&readfds);
+           FD_ZERO(&writefds);
+           FD_ZERO(&errfds);
+       }
+
+       /*
+        * Grab the current time again for use in timed events.
+        */
+       curtime = time(NULL);
+
+       /*
+        * We need to copy the errfds into werrfds, so file descriptors
+        * that are being polled for both reading and writing have
+        * both of their poll events 'see' the error.
+        */
+       memcpy(&werrfds, &errfds, sizeof(werrfds));
+
+       /*
+        * Now run through the events and fire the ones that are ready.
+        * Don't handle file descriptor events if the select failed.
+        */
+       for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) {
+           switch (eh->type) {
+
+           /*
+            * Read fds: just fire the event if set in the bitmask
+            */
+           case EV_READFD:
+               if (FD_ISSET(eh->data, &readfds) ||
+                   FD_ISSET(eh->data, &errfds)) {
+                   FD_CLR(eh->data, &readfds);
+                   FD_CLR(eh->data, &errfds);
+                   fire(eh);
+               }
+               break;
+
+           /*
+            * Write fds: same as Read fds
+            */
+           case EV_WRITEFD:
+               if (FD_ISSET(eh->data, &writefds) ||
+                   FD_ISSET(eh->data, &werrfds)) {
+                   FD_CLR(eh->data, &writefds);
+                   FD_CLR(eh->data, &werrfds);
+                   fire(eh);
+               }
+               break;
+
+           /*
+            * Signal events: check the score for fires, and run the
+            * event if we got one.
+            */
+           case EV_SIG:
+               se = &sigtable[eh->data];
+               if (se->score > 0) {
+                   assert(se->handle == eh);
+                   se->score = 0;
+                   fire(eh);
+               }
+               break;
+
+           /*
+            * Timed events: check the interval elapsed since last fired,
+            * and set it off if greater or equal to requested interval.
+            */
+           case EV_TIME:
+               if (eh->lastfired == -1)
+                   eh->lastfired = curtime;
+               if (curtime - eh->lastfired >= eh->data) {
+                   eh->lastfired = curtime;
+                   fire(eh);
+               }
+               break;
+
+           /*
+            * Wait events are handled immediately by event_wakeup()
+            * Dead events are handled by the pre-select loop.
+            */
+           case EV_WAIT:
+           case EV_DEAD:
+               break;
+
+           default:
+               assert(0);
+               break;
+           }
+       }
+    } while (!dontblock && eventq.qlength > 0);
+
+    assert(--entry == 0);
+}
+
+/*
+ * Generic signal handler.  Used to count caught signals for the event
+ * loop.
+ */
+static void
+signal_handler(signo)
+    int signo;
+{
+
+    assert(signo >= 0 && signo < sizeof(sigtable) / sizeof(sigtable[0]));
+    sigtable[signo].score++;
+}
+
+/*
+ * Return a new handle.  Take from the handle cache if not empty.  Otherwise,
+ * alloc a new one.
+ */
+static event_handle_t *
+gethandle()
+{
+    event_handle_t *eh;
+
+    if ((eh = eventq_first(cache)) != NULL) {
+       assert(cache.qlength > 0);
+       eventq_remove(eh);
+       cache.qlength--;
+       return (eh);
+    }
+    assert(cache.qlength == 0);
+    return (alloc(sizeof(*eh)));
+}
+
+/*
+ * Free a handle.  If there's space in the handle cache, put it there.
+ * Otherwise, free it.
+ */
+static void
+puthandle(eh)
+    event_handle_t *eh;
+{
+
+    if (cache.qlength > CACHEDEPTH) {
+       amfree(eh);
+       return;
+    }
+    eventq_add(cache, eh);
+    cache.qlength++;
+}
+
+#ifdef EVENT_DEBUG
+/*
+ * Convert an event type into a string
+ */
+static const char *
+event_type2str(type)
+    event_type_t type;
+{
+    static const struct {
+       event_type_t type;
+       const char name[12];
+    } event_types[] = {
+#define        X(s)    { s, stringize(s) }
+       X(EV_READFD),
+       X(EV_WRITEFD),
+       X(EV_SIG),
+       X(EV_TIME),
+       X(EV_WAIT),
+       X(EV_DEAD),
+#undef X
+    };
+    int i;
+
+    for (i = 0; i < sizeof(event_types) / sizeof(event_types[0]); i++)
+       if (type == event_types[i].type)
+           return (event_types[i].name);
+    return ("BOGUS EVENT TYPE");
+}
+#endif /* EVENT_DEBUG */
diff --git a/common-src/event.h b/common-src/event.h
new file mode 100644 (file)
index 0000000..367f3b5
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: event.h,v 1.6 2005/11/30 22:35:11 martinea Exp $
+ */
+#ifndef EVENT_H
+#define EVENT_H
+
+/*
+ * These functions define a generic event interface.  One can register a
+ * function vector and the type of events to act on, and the event handler
+ * will dispatch as necessary.
+ */
+
+/*
+ * An opaque handle returned by the registry functions that can be
+ * used to unregister an event in the future.
+ */
+struct event_handle;
+typedef struct event_handle event_handle_t;
+
+/*
+ * The 'id' of the event.  The meaning of this is dependant on the type
+ * of event we are registering.  This is hopefully wide enough that
+ * callers can cast pointers to it and keep the value untruncated and
+ * unique.
+ */
+typedef        unsigned long event_id_t;
+
+/*
+ * The types of events we can register.
+ */
+typedef enum {
+    EV_READFD,                 /* file descriptor is ready for reading */
+    EV_WRITEFD,                        /* file descriptor is ready for writing */
+    EV_SIG,                    /* signal has fired */
+    EV_TIME,                   /* n seconds have elapsed */
+    EV_WAIT,                   /* event_wakeup() was called with this id */
+    EV_DEAD                    /* internal use only */
+} event_type_t;
+
+/*
+ * The function signature for functions that get called when an event
+ * fires.
+ */
+typedef void (*event_fn_t) P((void *));
+
+/*
+ * Register an event handler.
+ *
+ * For readfd and writefd events, the first arg is the file descriptor.
+ * There can be multiple callers firing on the same file descriptor.
+ *
+ * For signal events, the first arg is the signal number as defined in
+ * <signal.h>.  There can only be one signal handler. (do we need more?)
+ *
+ * For time events, the first arg is the interval in seconds between
+ * pulses.  There can be multiple time events, of course.  Don't
+ * count on the time events being too accurate.  They depend on the
+ * caller calling event_loop() often enough.
+ */
+event_handle_t *event_register P((event_id_t, event_type_t,
+    event_fn_t, void *));
+
+/*
+ * Release an event handler.
+ */
+void event_release P((event_handle_t *));
+
+/*
+ * Wake up all EV_WAIT events waiting on a specific id
+ */
+int event_wakeup P((event_id_t));
+
+/*
+ * Process events.  If the argument is nonzero, then the loop does
+ * not block.
+ */
+void event_loop P((const int));
+
+#endif /* EVENT_H */
index 0e47b0142a4821b24a53597e65ad001b43e933de..ce4d28bd6695362e4426fd9acc5e9c32663dbfd6 100644 (file)
@@ -23,7 +23,7 @@
  * Author: AMANDA core development group.
  */
 /*
- * $Id: file.c,v 1.14.4.6.4.2.2.5.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: file.c,v 1.35 2006/03/09 16:51:41 martinea Exp $
  *
  * file and directory bashing routines
  */
@@ -31,6 +31,8 @@
 #include "amanda.h"
 #include "util.h"
 
+static int mk1dir P((const char *, int, uid_t, gid_t));
+
 uid_t client_uid = (uid_t) -1;
 gid_t client_gid = (gid_t) -1;
 
@@ -40,8 +42,8 @@ gid_t client_gid = (gid_t) -1;
 **       it will do nothing - only root is permitted to change the owner
 **       of a file.
 */
-int mk1dir(dir, mode, uid, gid)
-char *dir;     /* directory to create */
+static int mk1dir(dir, mode, uid, gid)
+const char *dir; /* directory to create */
 int mode;      /* mode for new directory */
 uid_t uid;     /* uid for new directory */
 gid_t gid;     /* gid for new directory */
@@ -270,19 +272,21 @@ safe_fd(fd_start, fd_count)
     for(fd = 0; fd < FD_SETSIZE; fd++) {
        if (fd < 3) {
            /*
-            * Open three file descriptors.  If stdin, stdout and stderr
-            * are normal, i.e. open, we will open descriptor numbers
-            * 3 or higher which the rest of this loop will turn right
-            * around and close.  If one of the standard descriptors
-            * is not open it will end up pointing to /dev/null and the
-            * rest of the loop will leave it alone.
+            * Open three file descriptors.  If one of the standard
+            * descriptors is not open it will be pointed to /dev/null...
             *
             * This avoids, for instance, someone running us with stderr
             * closed so that when we open some other file, messages
             * sent to stderr do not accidentally get written to the
             * wrong file.
             */
-           (void) open("/dev/null", O_RDWR);
+           if (fcntl(fd, F_GETFD) == -1) {
+               if (open("/dev/null", O_RDWR) == -1) {
+                  fprintf(stderr, "/dev/null is inaccessable: %s\n",
+                          strerror(errno));
+                  exit(1);
+               }
+           }
        } else {
            /*
             * Make sure nobody spoofs us with a lot of extra open files
@@ -378,6 +382,7 @@ char *inp;
     while((ch = *s++) != '\0') {
        if(ch == '_') {
            if(d >= buf + buf_size) {
+               amfree(buf);
                return NULL;                    /* cannot happen */
            }
            *d++ = '_';                         /* convert _ to __ to try */
@@ -386,11 +391,13 @@ char *inp;
            ch = '_';   /* convert "bad" to "_" */
        }
        if(d >= buf + buf_size) {
+           amfree(buf);
            return NULL;                        /* cannot happen */
        }
        *d++ = ch;
     }
     if(d >= buf + buf_size) {
+       amfree(buf);
        return NULL;                            /* cannot happen */
     }
     *d = '\0';
@@ -415,7 +422,7 @@ char *inp;
 
 char *
 debug_agets(s, l, file)
-    char *s;
+    const char *s;
     int l;
     FILE *file;
 {
@@ -479,7 +486,7 @@ debug_agets(s, l, file)
  * Find/create a buffer for a particular file descriptor for use with
  * areads().
  *
- * void areads_getbuf (char *file, int line, int fd)
+ * void areads_getbuf (const char *file, int line, int fd)
  *
  * entry:      file, line = caller source location
  *             fd = file descriptor to look up
@@ -497,7 +504,7 @@ static ssize_t areads_bufsize = BUFSIZ;             /* for the test program */
 
 static void
 areads_getbuf(s, l, fd)
-    char *s;
+    const char *s;
     int l;
     int fd;
 {
@@ -588,7 +595,7 @@ areads_relbuf(fd)
 
 char *
 debug_areads (s, l, fd)
-    char *s;
+    const char *s;
     int l;
     int fd;
 {
@@ -670,6 +677,9 @@ int main(argc, argv)
 
        set_pname("file test");
 
+       /* Don't die when child closes pipe */
+       signal(SIGPIPE, SIG_IGN);
+
        name = "/tmp/a/b/c/d/e";
        if (argc > 2 && argv[1][0] != '\0') {
                name = argv[1];
index 928a37c04fa2aba2461a143379a3b5a773942eeb..ede34793e14dd587bbf95051c86b35d857dc1266 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: fileheader.c,v 1.11.4.1.4.1.2.6 2003/10/24 13:44:49 martinea Exp $
- *
+ * $Id: fileheader.c,v 1.34 2006/03/09 16:51:41 martinea Exp $
  */
 
 #include "amanda.h"
 #include "fileheader.h"
 
+static const char *filetype2str P((filetype_t));
+static filetype_t str2filetype P((const char *));
 
-void fh_init(file)
-dumpfile_t *file;
+void
+fh_init(file)
+    dumpfile_t *file;
 {
-    memset(file,'\0',sizeof(*file));
+    memset(file, '\0', sizeof(*file));
     file->blocksize = DISK_BLOCK_BYTES;
 }
 
-
 void
 parse_file_header(buffer, file, buflen)
-    char *buffer;
+    const char *buffer;
     dumpfile_t *file;
     size_t buflen;
 {
-    string_t line, save_line;
-    char *bp, *str, *ptr_buf, *start_buf;
-    int nchars;
-    char *verify;
-    char *s, *s1, *s2;
-    int ch;
-    int done;
-
-    /* isolate first line */
-
-    nchars = buflen<sizeof(line)? buflen : sizeof(line) - 1;
-    for(s=line, ptr_buf=buffer; ptr_buf < buffer+nchars; ptr_buf++, s++) {
-       ch = *ptr_buf;
-       if(ch == '\n') {
-           *s = '\0';
-           break;
-       }
-       *s = ch;
-    }
-    line[sizeof(line)-1] = '\0';
-    strncpy(save_line, line, sizeof(save_line));
+    char *buf, *line, *tok, *line1=NULL;
+    int lsize;
+    /* put the buffer into a writable chunk of memory and nul-term it */
+    buf = alloc(buflen + 1);
+    memcpy(buf, buffer, buflen);
+    buf[buflen] = '\0';
 
     fh_init(file); 
-    s = line;
-    ch = *s++;
 
-    skip_whitespace(s, ch);
-    str = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
+    for(line=buf,lsize=0; *line != '\n' && lsize < buflen; line++) {lsize++;};
+    *line = '\0';
+    line1 = alloc(lsize+1);
+    strncpy(line1,buf,lsize);
+    line1[lsize] = '\0';
+    *line = '\n';
 
-    if(strcmp(str, "NETDUMP:") != 0 && strcmp(str,"AMANDA:") != 0) {
+    tok = strtok(line1, " ");
+    if (tok == NULL)
+       goto weird_header;
+    if (strcmp(tok, "NETDUMP:") != 0 && strcmp(tok, "AMANDA:") != 0) {
+       amfree(buf);
        file->type = F_UNKNOWN;
+       amfree(line1);
        return;
     }
 
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
+    tok = strtok(NULL, " ");
+    if (tok == NULL)
        goto weird_header;
-    }
-    str = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
+    file->type = str2filetype(tok);
 
-    if(strcmp(str, "TAPESTART") == 0) {
-       file->type = F_TAPESTART;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       verify = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       if(strcmp(verify, "DATE") != 0) {
+    switch (file->type) {
+    case F_TAPESTART:
+       tok = strtok(NULL, " ");
+       if (tok == NULL || strcmp(tok, "DATE") != 0)
            goto weird_header;
-       }
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       copy_string(s, ch, file->datestamp, sizeof(file->datestamp), bp);
-       if(bp == NULL) {
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
            goto weird_header;
-       }
+       strncpy(file->datestamp, tok, sizeof(file->datestamp) - 1);
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
+       tok = strtok(NULL, " ");
+       if (tok == NULL || strcmp(tok, "TAPE") != 0)
            goto weird_header;
-       }
-       verify = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       if(strcmp(verify, "TAPE") != 0) {
-           goto weird_header;
-       }
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
            goto weird_header;
-       }
-       copy_string(s, ch, file->name, sizeof(file->name), bp);
-       if(bp == NULL) {
-           goto weird_header;
-       }
-    } else if(strcmp(str, "FILE") == 0 || 
-             strcmp(str, "CONT_FILE") == 0) {
-       if(strcmp(str, "FILE") == 0)
-           file->type = F_DUMPFILE;
-       else if(strcmp(str, "CONT_FILE") == 0)
-           file->type = F_CONT_DUMPFILE;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       copy_string(s, ch, file->datestamp, sizeof(file->datestamp), bp);
-       if(bp == NULL) {
-           goto weird_header;
-       }
+       strncpy(file->name, tok, sizeof(file->name) - 1);
+       break;
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       copy_string(s, ch, file->name, sizeof(file->name), bp);
-       if(bp == NULL) {
+    case F_DUMPFILE:
+    case F_CONT_DUMPFILE:
+    case F_SPLIT_DUMPFILE:
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
            goto weird_header;
-       }
+       strncpy(file->datestamp, tok, sizeof(file->datestamp) - 1);
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       copy_string(s, ch, file->disk, sizeof(file->disk), bp);
-       if(bp == NULL) {
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
            goto weird_header;
-       }
+       strncpy(file->name, tok, sizeof(file->name) - 1);
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       verify = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       if(strcmp(verify, "lev") != 0) {
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
            goto weird_header;
+       strncpy(file->disk, tok, sizeof(file->disk) - 1);
+       
+       if(file->type == F_SPLIT_DUMPFILE){
+           tok = strtok(NULL, " ");
+           if (tok == NULL || strcmp(tok, "part") != 0)
+               goto weird_header;
+
+           tok = strtok(NULL, "/");
+           if (tok == NULL || sscanf(tok, "%d", &file->partnum) != 1)
+               goto weird_header;
+
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           /* If totalparts == -1, then the original dump was done in 
+              streaming mode (no holding disk), thus we don't know how 
+               many parts there are. */
+            if(sscanf(tok, "%d", &file->totalparts) != 1){
+               goto weird_header;
+           }
        }
+       
 
-       skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, "%d", &file->dumplevel) != 1) {
+       tok = strtok(NULL, " ");
+       if (tok == NULL || strcmp(tok, "lev") != 0)
            goto weird_header;
-       }
-       skip_integer(s, ch);
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       verify = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       if(strcmp(verify, "comp") != 0) {
+       tok = strtok(NULL, " ");
+       if (tok == NULL || sscanf(tok, "%d", &file->dumplevel) != 1)
            goto weird_header;
-       }
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
+       tok = strtok(NULL, " ");
+       if (tok == NULL || strcmp(tok, "comp") != 0)
            goto weird_header;
-       }
-       copy_string(s, ch, file->comp_suffix, sizeof(file->comp_suffix), bp);
-       if(bp == NULL) {
+
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
            goto weird_header;
-       }
+       strncpy(file->comp_suffix, tok, sizeof(file->comp_suffix) - 1);
 
        file->compressed = strcmp(file->comp_suffix, "N");
        /* compatibility with pre-2.2 amanda */
-       if(strcmp(file->comp_suffix, "C") == 0) {
-           strncpy(file->comp_suffix, ".Z", sizeof(file->comp_suffix)-1);
-           file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
+       if (strcmp(file->comp_suffix, "C") == 0)
+           strncpy(file->comp_suffix, ".Z", sizeof(file->comp_suffix) - 1);
+              
+       tok = strtok(NULL, " ");
+        /* "program" is optional */
+        if (tok == NULL || strcmp(tok, "program") != 0) {
+           amfree(buf);
+           amfree(line1);
+            return;
+       }
+
+        tok = strtok(NULL, " ");
+        if (tok == NULL)
+            goto weird_header;
+        strncpy(file->program, tok, sizeof(file->program) - 1);
+        if (file->program[0] == '\0')
+            strncpy(file->program, "RESTORE", sizeof(file->program) - 1);
+
+       if ((tok = strtok(NULL, " ")) == NULL)
+             break;          /* reach the end of the buf */
+
+       /* "encryption" is optional */
+       if (BSTRNCMP(tok, "crypt") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->encrypt_suffix, tok,
+                   sizeof(file->encrypt_suffix) - 1);
+           file->encrypted = BSTRNCMP(file->encrypt_suffix, "N");
+           if ((tok = strtok(NULL, " ")) == NULL)
+               break;
        }
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           return;                             /* "program" is optional */
-       }
-       verify = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       if(strcmp(verify, "program") != 0) {
-           return;                             /* "program" is optional */
+       /* "srvcompprog" is optional */
+       if (BSTRNCMP(tok, "server_custom_compress") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->srvcompprog, tok, sizeof(file->srvcompprog) - 1);
+           if ((tok = strtok(NULL, " ")) == NULL)
+               break;      
        }
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       copy_string(s, ch, file->program, sizeof(file->program), bp);
-       if(bp == NULL) {
-           goto weird_header;
+       /* "clntcompprog" is optional */
+       if (BSTRNCMP(tok, "client_custom_compress") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->clntcompprog, tok, sizeof(file->clntcompprog) - 1);
+           if ((tok = strtok(NULL, " ")) == NULL)
+               break;
        }
 
-       if(file->program[0]=='\0') {
-           strncpy(file->program, "RESTORE", sizeof(file->program)-1);
-           file->program[sizeof(file->program)-1] = '\0';
+       /* "srv_encrypt" is optional */
+       if (BSTRNCMP(tok, "server_encrypt") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->srv_encrypt, tok, sizeof(file->srv_encrypt) - 1);
+           if ((tok = strtok(NULL, " ")) == NULL) 
+               break;
        }
 
-    } else if(strcmp(str, "TAPEEND") == 0) {
-       file->type = F_TAPEEND;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
-       }
-       verify = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       if(strcmp(verify, "DATE") != 0) {
-           return;                             /* "program" is optional */
+       /* "clnt_encrypt" is optional */
+       if (BSTRNCMP(tok, "client_encrypt") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->clnt_encrypt, tok, sizeof(file->clnt_encrypt) - 1);
+           if ((tok = strtok(NULL, " ")) == NULL) 
+               break;
        }
 
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           goto weird_header;
+       /* "srv_decrypt_opt" is optional */
+       if (BSTRNCMP(tok, "server_decrypt_option") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->srv_decrypt_opt, tok,
+                   sizeof(file->srv_decrypt_opt) - 1);
+           if ((tok = strtok(NULL, " ")) == NULL) 
+               break;
        }
-       copy_string(s, ch, file->datestamp, sizeof(file->datestamp), bp);
-       if(bp == NULL) {
-           goto weird_header;
+
+       /* "clnt_decrypt_opt" is optional */
+       if (BSTRNCMP(tok, "client_decrypt_option") == 0) {
+           tok = strtok(NULL, " ");
+           if (tok == NULL)
+               goto weird_header;
+           strncpy(file->clnt_decrypt_opt, tok,
+                   sizeof(file->clnt_decrypt_opt) - 1);
+           if ((tok = strtok(NULL, " ")) == NULL) 
+               break;
        }
-    } else {
+      break;
+      
+
+    case F_TAPEEND:
+       tok = strtok(NULL, " ");
+       /* DATE is optional */
+       if (tok == NULL || strcmp(tok, "DATE") != 0) {
+           amfree(buf);
+           amfree(line1);
+           return;
+       }
+       strncpy(file->datestamp, tok, sizeof(file->datestamp) - 1);
+       break;
+
+    default:
        goto weird_header;
     }
 
-    done=0;
-    do {
-       /* isolate the next line */
-       int max_char;
-       ptr_buf++;
-       start_buf = ptr_buf;
-       max_char = buflen - (ptr_buf - buffer);
-       nchars = max_char<sizeof(line)? max_char : sizeof(line) - 1;
-       for(s=line ; ptr_buf < start_buf+nchars; ptr_buf++, s++) {
-           ch = *ptr_buf;
-           if(ch == '\n') {
-               *s = '\0';
-               break;
-           }
-           else if(ch == '\0' || ch == '\014') {
-               done=1;
-               break;
-           }
-           *s = ch;
-       }
-       if (done == 1) break;
-       if(ptr_buf >= start_buf+nchars) done = 1;
-       line[sizeof(line)-1] = '\0';
-       s = line;
-       ch = *s++;
+    line = strtok(buf, "\n"); /* this is the first line */
+    /* iterate through the rest of the lines */
+    while ((line = strtok(NULL, "\n")) != NULL) {
 #define SC "CONT_FILENAME="
-       if(strncmp(line,SC,strlen(SC)) == 0) {
-           s = line + strlen(SC);
-           ch = *s++;
-           copy_string(s, ch, file->cont_filename, 
-                       sizeof(file->cont_filename), bp);
+       if (strncmp(line, SC, sizeof(SC) - 1) == 0) {
+           line += sizeof(SC) - 1;
+           strncpy(file->cont_filename, line,
+                   sizeof(file->cont_filename) - 1);
+                   continue;
        }
 #undef SC
+
 #define SC "PARTIAL="
-       else if(strncmp(line,SC,strlen(SC)) == 0) {
-           s = line + strlen(SC);
-           if(strncmp(s,"yes",3)==0 || strncmp(s,"YES",3)==0)
-               file->is_partial=1;
-           ch = *s++;
+       if (strncmp(line, SC, sizeof(SC) - 1) == 0) {
+           line += sizeof(SC) - 1;
+           file->is_partial = !strcasecmp(line, "yes");
+           continue;
        }
 #undef SC
+
 #define SC "To restore, position tape at start of file and run:"
-       else if(strncmp(line,SC,strlen(SC)) == 0) {
-       }
+       if (strncmp(line, SC, sizeof(SC) - 1) == 0)
+           continue;
 #undef SC
+
 #define SC "\tdd if=<tape> bs="
-       else if(strncmp(line,SC,strlen(SC)) == 0) {
-           s = strtok(line, "|");
-           s1 = strtok(NULL, "|");
-           s2 = strtok(NULL, "|");
-           if(!s1) {
-               strncpy(file->recover_cmd,"BUG",sizeof(file->recover_cmd));
-               file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0';
+       if (strncmp(line, SC, sizeof(SC) - 1) == 0) {
+           char *cmd1=NULL, *cmd2=NULL, *cmd3=NULL;
+
+           /* skip over dd command */
+           if ((cmd1 = strchr(line, '|')) == NULL) {
+
+               strncpy(file->recover_cmd, "BUG",
+                       sizeof(file->recover_cmd) - 1);
+               continue;
            }
-           else if(!s2) {
-               strncpy(file->recover_cmd,s1+1,sizeof(file->recover_cmd));
-               file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0';
+           *cmd1++ = '\0';
+
+           /* block out first pipeline command */
+           if ((cmd2 = strchr(cmd1, '|')) != NULL) {
+             *cmd2++ = '\0';
+             if ((cmd3 = strchr(cmd2, '|')) != NULL)
+               *cmd3++ = '\0';
            }
-           else {
-               strncpy(file->uncompress_cmd,s1, sizeof(file->uncompress_cmd));
-               file->uncompress_cmd[sizeof(file->uncompress_cmd)-2] = '\0';
-               strcat(file->uncompress_cmd,"|");
-               strncpy(file->recover_cmd,s2+1,sizeof(file->recover_cmd));
-               file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0';
+          
+           /* three cmds: decrypt    | uncompress | recover
+            * two   cmds: uncompress | recover
+            * XXX note that if there are two cmds, the first one 
+            * XXX could be either uncompress or decrypt. Since no
+            * XXX code actually call uncompress_cmd/decrypt_cmd, it's ok
+            * XXX for header information.
+            * one   cmds: recover
+            */
+
+           if (cmd3 == NULL) {
+             if (cmd2 == NULL) {
+               strncpy(file->recover_cmd, cmd1,
+                       sizeof(file->recover_cmd) - 1);
+             } else {
+               snprintf(file->uncompress_cmd,
+                        sizeof(file->uncompress_cmd), "%s|", cmd1);
+               strncpy(file->recover_cmd, cmd2,
+                       sizeof(file->recover_cmd) - 1);
+             }
+           } else {    /* cmd3 presents:  decrypt | uncompress | recover */
+             snprintf(file->decrypt_cmd,
+                      sizeof(file->decrypt_cmd), "%s|", cmd1);
+             snprintf(file->uncompress_cmd,
+                      sizeof(file->uncompress_cmd), "%s|", cmd2);
+             strncpy(file->recover_cmd, cmd3,
+                     sizeof(file->recover_cmd) - 1);
            }
+           continue;
        }
 #undef SC
-       else { /* ignore unknown line */
-       }
-    } while(!done);
-
+       /* XXX complain about weird lines? */
+    }
+    amfree(buf);
+    amfree(line1);
     return;
 
- weird_header:
-
-    fprintf(stderr, "%s: strange amanda header: \"%s\"\n", get_pname(), save_line);
+weird_header:
+    fprintf(stderr, "%s: strange amanda header: \"%.*s\"\n", get_pname(),
+       (int) buflen, buffer);
     file->type = F_WEIRD;
-    return;
+    amfree(buf);
+    amfree(line1);
 }
 
-
 void
 build_header(buffer, file, buflen)
     char *buffer;
-    dumpfile_t *file;
+    const dumpfile_t *file;
     size_t buflen;
 {
-    char *line = NULL;
-    char number[NUM_STR_SIZE*2];
+    int n;
+    char split_data[128] = "";
 
     memset(buffer,'\0',buflen);
 
     switch (file->type) {
-    case F_TAPESTART: ap_snprintf(buffer, buflen,
-                                 "AMANDA: TAPESTART DATE %s TAPE %s\n\014\n",
-                                 file->datestamp, file->name);
-                     break;
+    case F_TAPESTART:
+       snprintf(buffer, buflen,
+           "AMANDA: TAPESTART DATE %s TAPE %s\n014\n",
+           file->datestamp, file->name);
+       break;
+
+    case F_SPLIT_DUMPFILE:
+       snprintf(split_data, sizeof(split_data),
+                " part %d/%d ", file->partnum, file->totalparts);
+    /* FALLTHROUGH */
+       
     case F_CONT_DUMPFILE:
-    case F_DUMPFILE : if( file->type == F_DUMPFILE) {
-                       ap_snprintf(buffer, buflen,
-                                 "AMANDA: FILE %s %s %s lev %d comp %s program %s\n",
-                                 file->datestamp, file->name, file->disk,
-                                 file->dumplevel, file->comp_suffix,
-                                 file->program);
-                     }
-                     else if( file->type == F_CONT_DUMPFILE) {
-                       ap_snprintf(buffer, buflen,
-                                 "AMANDA: CONT_FILE %s %s %s lev %d comp %s program %s\n",
-                                 file->datestamp, file->name, file->disk,
-                                 file->dumplevel, file->comp_suffix,
-                                 file->program);
-                     }
-                     buffer[buflen-1] = '\0';
-                     if(strlen(file->cont_filename) != 0) {
-                       line = newvstralloc(line, "CONT_FILENAME=",
-                                           file->cont_filename, "\n", NULL);
-                       strncat(buffer,line,buflen-strlen(buffer));
-                     }
-                     if(file->is_partial != 0) {
-                       strncat(buffer,"PARTIAL=YES\n",buflen-strlen(buffer));
-                     }
-                     strncat(buffer,
-                       "To restore, position tape at start of file and run:\n",
-                       buflen-strlen(buffer));
-                     ap_snprintf(number, sizeof(number),
-                                 "%ld", file->blocksize / 1024);
-                     line = newvstralloc(line, "\t",
-                                      "dd",
-                                      " if=<tape>",
-                                      " bs=", number, "k",
-                                      " skip=1",
-                                      " |", file->uncompress_cmd,
-                                      " ", file->recover_cmd,
-                                      "\n",
-                                      "\014\n",        /* ?? */
-                                      NULL);
-                     strncat(buffer, line, buflen-strlen(buffer));
-                     amfree(line);
-                     buffer[buflen-1] = '\0';
-                     break;
-    case F_TAPEEND  : ap_snprintf(buffer, buflen,
-                                 "AMANDA: TAPEEND DATE %s\n\014\n",
-                                 file->datestamp);
-                     break;
-    case F_UNKNOWN  : break;
-    case F_WEIRD    : break;
+    case F_DUMPFILE :
+        n = snprintf(buffer, buflen,
+                     "AMANDA: %s %s %s %s %s lev %d comp %s program %s",
+                        filetype2str(file->type),
+                        file->datestamp, file->name, file->disk,
+                        split_data,
+                        file->dumplevel, file->comp_suffix, file->program); 
+       if ( n ) {
+         buffer += n;
+         buflen -= n;
+         n = 0;
+       }
+     
+       if (strcmp(file->encrypt_suffix, "enc") == 0) {  /* only output crypt if it's enabled */
+         n = snprintf(buffer, buflen, " crypt %s", file->encrypt_suffix);
+       }
+       if ( n ) {
+         buffer += n;
+         buflen -= n;
+         n = 0;
+       }
+
+       if (*file->srvcompprog) {
+           n = snprintf(buffer, buflen, " server_custom_compress %s", file->srvcompprog);
+       } else if (*file->clntcompprog) {
+           n = snprintf(buffer, buflen, " client_custom_compress %s", file->clntcompprog);
+       } 
+
+       if ( n ) {
+         buffer += n;
+         buflen -= n;
+         n = 0;
+       }
+
+       if (*file->srv_encrypt) {
+           n = snprintf(buffer, buflen, " server_encrypt %s", file->srv_encrypt);
+       } else if (*file->clnt_encrypt) {
+           n = snprintf(buffer, buflen, " client_encrypt %s", file->clnt_encrypt);
+       } 
+
+       if ( n ) {
+         buffer += n;
+         buflen -= n;
+         n = 0;
+       }
+       
+       if (*file->srv_decrypt_opt) {
+           n = snprintf(buffer, buflen, " server_decrypt_option %s", file->srv_decrypt_opt);
+       } else if (*file->clnt_decrypt_opt) {
+           n = snprintf(buffer, buflen, " client_decrypt_option %s", file->clnt_decrypt_opt);
+       } 
+
+       if ( n ) {
+         buffer += n;
+         buflen -= n;
+         n = 0;
+       }
+
+       n = snprintf(buffer, buflen, "\n");
+       buffer += n;
+       buflen -= n;
+
+       if (file->cont_filename[0] != '\0') {
+           n = snprintf(buffer, buflen, "CONT_FILENAME=%s\n",
+               file->cont_filename);
+           buffer += n;
+           buflen -= n;
+       }
+       if (file->is_partial != 0) {
+           n = snprintf(buffer, buflen, "PARTIAL=YES\n");
+           buffer += n;
+           buflen -= n;
+       }
+
+       n = snprintf(buffer, buflen, 
+           "To restore, position tape at start of file and run:\n");
+       buffer += n;
+       buflen -= n;
+
+       /* \014 == ^L */
+       n = snprintf(buffer, buflen,
+           "\tdd if=<tape> bs=%ldk skip=1 |%s %s %s\n\014\n",
+           file->blocksize / 1024, file->decrypt_cmd, file->uncompress_cmd, file->recover_cmd);
+       buffer += n;
+       buflen -= n;
+       break;
+
+    case F_TAPEEND:
+       snprintf(buffer, buflen, "AMANDA: TAPEEND DATE %s\n\014\n",
+           file->datestamp);
+       break;
+
+    case F_UNKNOWN:
+    case F_WEIRD:
+       break;
     }
 }
 
-
-void print_header(outf, file)
-FILE *outf;
-dumpfile_t *file;
 /*
  * Prints the contents of the file structure.
  */
+void
+print_header(outf, file)
+    FILE *outf;
+    const dumpfile_t *file;
 {
+    char number[NUM_STR_SIZE*2];
     switch(file->type) {
     case F_UNKNOWN:
        fprintf(outf, "UNKNOWN file\n");
@@ -430,32 +501,63 @@ dumpfile_t *file;
               file->datestamp, file->name);
        break;
     case F_DUMPFILE:
-       fprintf(outf, "dumpfile: date %s host %s disk %s lev %d comp %s",
-               file->datestamp, file->name, file->disk, file->dumplevel, 
-               file->comp_suffix);
-       if(*file->program)
-           fprintf(outf, " program %s\n",file->program);
-       else
-           fprintf(outf, "\n");
-       break;
     case F_CONT_DUMPFILE:
-       fprintf(outf, "cont dumpfile: date %s host %s disk %s lev %d comp %s",
-               file->datestamp, file->name, file->disk, file->dumplevel, 
-               file->comp_suffix);
-       if(*file->program)
-           fprintf(outf, " program %s\n",file->program);
-       else
-           fprintf(outf, "\n");
+       fprintf(outf, "%s: date %s host %s disk %s lev %d comp %s",
+           filetype2str(file->type), file->datestamp, file->name,
+           file->disk, file->dumplevel, file->comp_suffix);
+       if (*file->program)
+           fprintf(outf, " program %s",file->program);
+       if (strcmp(file->encrypt_suffix, "enc") == 0)
+           fprintf(outf, " crypt %s", file->encrypt_suffix);
+       if (*file->srvcompprog)
+           fprintf(outf, " server_custom_compress %s", file->srvcompprog);
+       if (*file->clntcompprog)
+           fprintf(outf, " client_custom_compress %s", file->clntcompprog);
+       if (*file->srv_encrypt)
+           fprintf(outf, " server_encrypt %s", file->srv_encrypt);
+       if (*file->clnt_encrypt)
+           fprintf(outf, " client_encrypt %s", file->clnt_encrypt);
+       if (*file->srv_decrypt_opt)
+           fprintf(outf, " server_decrypt_option %s", file->srv_decrypt_opt);
+       if (*file->clnt_decrypt_opt)
+           fprintf(outf, " client_decrypt_option %s", file->clnt_decrypt_opt);
+       fprintf(outf, "\n");
        break;
+    case F_SPLIT_DUMPFILE:
+        if(file->totalparts > 0){
+            snprintf(number, sizeof(number), "%d", file->totalparts);
+        }   
+        else snprintf(number, sizeof(number), "UNKNOWN");
+        fprintf(outf, "split dumpfile: date %s host %s disk %s part %d/%s lev %d comp %s",
+                      file->datestamp, file->name, file->disk, file->partnum,
+                      number, file->dumplevel, file->comp_suffix);
+        if (*file->program)
+            fprintf(outf, " program %s",file->program);
+       if (strcmp(file->encrypt_suffix, "enc") == 0)
+           fprintf(outf, " crypt %s", file->encrypt_suffix);
+       if (*file->srvcompprog)
+           fprintf(outf, " server_custom_compress %s", file->srvcompprog);
+       if (*file->clntcompprog)
+           fprintf(outf, " client_custom_compress %s", file->clntcompprog);
+       if (*file->srv_encrypt)
+           fprintf(outf, " server_encrypt %s", file->srv_encrypt);
+       if (*file->clnt_encrypt)
+           fprintf(outf, " client_encrypt %s", file->clnt_encrypt);
+       if (*file->srv_decrypt_opt)
+           fprintf(outf, " server_decrypt_option %s", file->srv_decrypt_opt);
+       if (*file->clnt_decrypt_opt)
+           fprintf(outf, " client_decrypt_option %s", file->clnt_decrypt_opt);
+        fprintf(outf, "\n");
+        break;
     case F_TAPEEND:
        fprintf(outf, "end of tape: date %s\n", file->datestamp);
        break;
     }
 }
 
-
-int known_compress_type(file)
-dumpfile_t *file;
+int
+known_compress_type(file)
+    const dumpfile_t *file;
 {
     if(strcmp(file->comp_suffix, ".Z") == 0)
        return 1;
@@ -463,5 +565,45 @@ dumpfile_t *file;
     if(strcmp(file->comp_suffix, ".gz") == 0)
        return 1;
 #endif
+    if(strcmp(file->comp_suffix, "cust") == 0)
+       return 1;
     return 0;
 }
+
+static const struct {
+    filetype_t type;
+    const char *str;
+} filetypetab[] = {
+    { F_UNKNOWN, "UNKNOWN" },
+    { F_WEIRD, "WEIRD" },
+    { F_TAPESTART, "TAPESTART" },
+    { F_TAPEEND,  "TAPEEND" },
+    { F_DUMPFILE, "FILE" },
+    { F_CONT_DUMPFILE, "CONT_FILE" },
+    { F_SPLIT_DUMPFILE, "SPLIT_FILE" }
+};
+#define        NFILETYPES      (sizeof(filetypetab) / sizeof(filetypetab[0]))
+
+static const char *
+filetype2str(type)
+    filetype_t type;
+{
+    int i;
+
+    for (i = 0; i < NFILETYPES; i++)
+       if (filetypetab[i].type == type)
+           return (filetypetab[i].str);
+    return ("UNKNOWN");
+}
+
+static filetype_t
+str2filetype(str)
+    const char *str;
+{
+    int i;
+
+    for (i = 0; i < NFILETYPES; i++)
+       if (strcmp(filetypetab[i].str, str) == 0)
+           return (filetypetab[i].type);
+    return (F_UNKNOWN);
+}
index 7666a0f678957feeac3eae4f79d0bbfe88dd89df..8398aeafd1899ff9e2522eadb94d07b52600477b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: fileheader.h,v 1.6.4.1.4.1.2.2 2002/02/11 01:30:42 jrjackson Exp $
+ * $Id: fileheader.h,v 1.15 2005/12/09 03:22:52 paddy_s Exp $
  *
  */
 
 #define FILEHEADER_H
 
 #include "amanda.h"
+#include "util.h"              /* for bstrncmp() */
 
 #define STRMAX         256
 
 typedef char string_t[STRMAX];
 typedef enum {
     F_UNKNOWN, F_WEIRD, F_TAPESTART, F_TAPEEND, 
-    F_DUMPFILE, F_CONT_DUMPFILE
+    F_DUMPFILE, F_CONT_DUMPFILE, F_SPLIT_DUMPFILE
 } filetype_t;
 
 typedef struct file_s {
@@ -46,25 +47,37 @@ typedef struct file_s {
     string_t datestamp;
     int dumplevel;
     int compressed;
+    int encrypted;
     string_t comp_suffix;
+    string_t encrypt_suffix;
     string_t name;     /* hostname or label */
     string_t disk;
     string_t program;
+    string_t srvcompprog;
+    string_t clntcompprog;
+    string_t srv_encrypt;
+    string_t clnt_encrypt;
     string_t recover_cmd;
     string_t uncompress_cmd;
+    string_t encrypt_cmd;
+    string_t decrypt_cmd;
+    string_t srv_decrypt_opt;
+    string_t clnt_decrypt_opt;
     string_t cont_filename;
     int is_partial;
+    int partnum;
+    int totalparts; /* -1 == UNKNOWN */
     long blocksize;
 } dumpfile_t;
 
 /* local functions */
 
 void  fh_init             P((dumpfile_t *file));
-void  parse_file_header   P((char *buffer, dumpfile_t *file, size_t buflen));
+void  parse_file_header   P((const char *buffer, dumpfile_t *file, size_t buflen));
 void  build_header        P((char *buffer,
-                            dumpfile_t *file,
+                            const dumpfile_t *file,
                             size_t buflen));
-void  print_header        P((FILE *outf, dumpfile_t *file));
-int   known_compress_type P((dumpfile_t *file));
+void  print_header        P((FILE *outf, const dumpfile_t *file));
+int   known_compress_type P((const dumpfile_t *file));
 
 #endif /* !FILEHEADER_H */
index 78becebcb9f9a93e7c3ab2d63a7489a1962b0835..074296bd3a79058550b1b7649f9b7eb88734bb94 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: genversion.c,v 1.18.4.4.4.1.2.2.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: genversion.c,v 1.31 2003/10/07 17:09:46 martinea Exp $
  *
  * dump the current Amanda version info
  */
 #include "version.h"
 #include "genversion.h"
 
-int main P((void));
+#define        LMARGIN         6
+#define RMARGIN        70
+
+static int linelen;
 
-#define MARGIN         70
+#define        startline(title)        printf("  \"%-*s", LMARGIN, title); linelen = 0
+#define        endline()               printf("\\n\",\n")
 
-#define newline() do {                                                 \
-    printf("  \"%s\\n\",\n", line);                                    \
-    *line = '\0';                                                      \
-    linelen = 0;                                                       \
-} while (0)
+static void prstr P((const char *));
+static void prvar P((const char *, const char *));
+int main P((void));
 
 /* Print a string */
-#define prstr(string) do {                                             \
-    int len = strlen(string);                                          \
-    if(linelen+len >= MARGIN) {                                        \
-       newline();                                                      \
-       ap_snprintf(line, sizeof(line), "%*s", indent, "");             \
-       linelen = indent;                                               \
-    }                                                                  \
-    line[sizeof(line)-1] = '\0';                                       \
-    strncat(line, (string), sizeof(line)-strlen(line));                        \
-    linelen += len;                                                    \
-} while (0)
-
-/* Print a text "variable" */
-#define prvar(var, val) do {                                           \
-    str = newvstralloc(str, (var), "=\\\"", (val), "\\\"", NULL);      \
-    prstr(str);                                                                \
-} while(0)
-
-/* Print a undef "variable" */
-#define prundefvar(var) do {                                           \
-    str = newvstralloc(str, (var), "=UNDEF", NULL);                    \
-    prstr(str);                                                                \
-} while(0)
-
-/* Print a numeric "variable" */
-#define prnum(var, val) do {                                           \
-    char number[NUM_STR_SIZE];                                         \
-    ap_snprintf(number, sizeof(number), "%ld", (long)(val));           \
-    str = newvstralloc(str, (var), "=", number, NULL);                 \
-    prstr(str);                                                                \
-} while(0)
-
-int main()
+static void
+prstr(string)
+    const char *string;
 {
-    char line[STR_SIZE], *str = NULL;
-    int  linelen, indent;
-    unsigned long malloc_hist_1, malloc_size_1;
-    unsigned long malloc_hist_2, malloc_size_2;
-
-    safe_fd(-1, 0);
-
-    set_pname("genversion");
+    size_t len = strlen(string) + 1;
+
+    /*
+     * If this string overflows this line, and there's other stuff
+     * on the line, create a new one.
+     */
+    if (linelen > 0 && linelen + len >= RMARGIN - LMARGIN) {
+       endline();
+       startline("");
+    }
+    printf(" %s", string);
+    linelen += len;
+}
 
-    malloc_size_1 = malloc_inuse(&malloc_hist_1);
+static char *buf = NULL;
+static size_t buf_len = 0;
 
-    printf("/* version.c - generated by genversion.c - DO NOT EDIT! */\n");
-    printf("char *version_info[] = {\n");
+/* Print a text variable */
+static void
+prvar(var, val)
+    const char *var, *val;
+{
+    size_t new_len;
+
+    new_len = strlen(var)
+             + sizeof("=\\\"")
+             + strlen(val)
+             + sizeof("\\\"")
+             + 1;
+    if(new_len > buf_len) {
+       free(buf);
+       buf_len = new_len;
+       buf = malloc(new_len);          /* let it die if malloc() fails */
+    }
+    sprintf(buf, "%s=\\\"%s\\\"", var, val);   /* safe */
+    prstr(buf);
+}
 
-    *line = '\0', linelen = 0, indent = 0;
+/* Print a undef variable */
+static void
+prundefvar(var)
+    const char *var;
+{
+    size_t new_len;
+
+    new_len = strlen(var)
+             + sizeof("=UNDEF")
+             + 1;
+    if(new_len > buf_len) {
+       free(buf);
+       buf_len = new_len;
+       buf = malloc(new_len);          /* let it die if malloc() fails */
+    }
+    sprintf(buf, "%s=UNDEF", var);     /* safe */
+    prstr(buf);
+}
 
+/* Print a numeric variable */
+static void
+prnum(var, val)
+    const char *var;
+    long val;
+{
+    static char number[NUM_STR_SIZE];
+    size_t new_len;
+
+    snprintf(number, sizeof(number), "%ld", val);
+    new_len = strlen(var)
+             + sizeof("=")
+             + strlen(number)
+             + 1;
+    if(new_len > buf_len) {
+       free(buf);
+       buf_len = new_len;
+       buf = malloc(new_len);          /* let it die if malloc() fails */
+    }
+    sprintf(buf, "%s=%s", var, number);                /* safe */
+    prstr(buf);
+}
 
-    prstr("build:"); indent = linelen;
+int
+main()
+{
+    const char *v;
+    char *verstr;
+    size_t v_len;
 
-    {
-       char version_str[STR_SIZE];
+    printf("/* version.c - generated by genversion.c - DO NOT EDIT! */\n");
+    printf("const char * const version_info[] = {\n");
 
-       ap_snprintf(version_str, sizeof(version_str), "Amanda-%s", version());
-       prvar(" VERSION", version_str);
-    }
+    startline("build:");
+    v = version();
+    v_len = sizeof("Amanda-") + strlen(v) + 1;
+    verstr = malloc(v_len);
+    sprintf(verstr, "Amanda-%s", v);           /* safe */
+    prvar("VERSION", verstr);
+    free(verstr);
 
 #ifdef BUILT_DATE
-    prvar(" BUILT_DATE", BUILT_DATE);
+    prvar("BUILT_DATE", BUILT_DATE);
 #else
-    prundefvar(" BUILT_DATE");
+    prundefvar("BUILT_DATE");
 #endif
 
 #ifdef BUILT_MACH
-    prvar(" BUILT_MACH", BUILT_MACH);
+    prvar("BUILT_MACH", BUILT_MACH);
 #else
-    prundefvar(" BUILT_MACH");
+    prundefvar("BUILT_MACH");
 #endif
 
 #ifdef CC
-    prvar(" CC", CC);
+    prvar("CC", CC);
 #else
-    prundefvar(" CC");
+    prundefvar("CC");
 #endif
 
-#ifdef CONFIGURE_COMMAND
-    prvar(" CONFIGURE_COMMAND", CONFIGURE_COMMAND);
+#ifdef CC
+    prvar("CONFIGURE_COMMAND", CONFIGURE_COMMAND);
 #else
-    prundefvar(" CONFIGURE_COMMAND");
+    prundefvar("CONFIGURE_COMMAND");
 #endif
 
-    newline();
+    endline();
 
+    startline("paths:");
 
-    prstr("paths:"); indent = linelen;
-
-    prvar(" bindir", bindir);
-    prvar(" sbindir", sbindir);
-    prvar(" libexecdir", libexecdir);
-    prvar(" mandir", mandir);
-    prvar(" AMANDA_TMPDIR", AMANDA_TMPDIR);
+    prvar("bindir", bindir);
+    prvar("sbindir", sbindir);
+    prvar("libexecdir", libexecdir);
+    prvar("mandir", mandir);
+    prvar("AMANDA_TMPDIR", AMANDA_TMPDIR);
 #ifdef AMANDA_DBGDIR
-    prvar(" AMANDA_DBGDIR", AMANDA_DBGDIR);
+    prvar("AMANDA_DBGDIR", AMANDA_DBGDIR);
 #else
-    prundefvar(" AMANDA_DBGDIR");
+    prundefvar("AMANDA_DBGDIR");
 #endif
-
-    prvar(" CONFIG_DIR", CONFIG_DIR);
+    prvar("CONFIG_DIR", CONFIG_DIR);
 
 #ifdef DEV_PREFIX
-    prvar(" DEV_PREFIX", DEV_PREFIX);
+    prvar("DEV_PREFIX", DEV_PREFIX);
 #else
-    prundefvar(" DEV_PREFIX");
+    prundefvar("DEV_PREFIX");
 #endif
 
 #ifdef RDEV_PREFIX
-    prvar(" RDEV_PREFIX", RDEV_PREFIX);
+    prvar("RDEV_PREFIX", RDEV_PREFIX);
 #else
-    prundefvar(" RDEV_PREFIX");
+    prundefvar("RDEV_PREFIX");
 #endif
 
 #ifdef DUMP
-    prvar(" DUMP", DUMP);
-    prvar(" RESTORE", RESTORE);
+    prvar("DUMP", DUMP);
+    prvar("RESTORE", RESTORE);
 #else
-    prundefvar(" DUMP");
-    prundefvar(" RESTORE");
+    prundefvar("DUMP");
+    prundefvar("RESTORE");
 #endif
 
 #ifdef VDUMP
-    prvar(" VDUMP", VDUMP);
-    prvar(" VRESTORE", VRESTORE);
+    prvar("VDUMP", VDUMP);
+    prvar("VRESTORE", VRESTORE);
 #else
-    prundefvar(" VDUMP");
-    prundefvar(" VRESTORE");
+    prundefvar("VDUMP");
+    prundefvar("VRESTORE");
 #endif
 
 #ifdef XFSDUMP
-    prvar(" XFSDUMP", XFSDUMP);
-    prvar(" XFSRESTORE", XFSRESTORE);
+    prvar("XFSDUMP", XFSDUMP);
+    prvar("XFSRESTORE", XFSRESTORE);
 #else
-    prundefvar(" XFSDUMP");
-    prundefvar(" XFSRESTORE");
+    prundefvar("XFSDUMP");
+    prundefvar("XFSRESTORE");
 #endif
 
 #ifdef VXDUMP
-    prvar(" VXDUMP", VXDUMP);
-    prvar(" VXRESTORE", VXRESTORE);
+    prvar("VXDUMP", VXDUMP);
+    prvar("VXRESTORE", VXRESTORE);
 #else
-    prundefvar(" VXDUMP");
-    prundefvar(" VXRESTORE");
+    prundefvar("VXDUMP");
+    prundefvar("VXRESTORE");
 #endif
 
 #ifdef SAMBA_CLIENT
-    prvar(" SAMBA_CLIENT", SAMBA_CLIENT);
+    prvar("SAMBA_CLIENT", SAMBA_CLIENT);
 #else
-    prundefvar(" SAMBA_CLIENT");
+    prundefvar("SAMBA_CLIENT");
 #endif
 
 #ifdef GNUTAR
-    prvar(" GNUTAR", GNUTAR);
+    prvar("GNUTAR", GNUTAR);
 #else
-    prundefvar(" GNUTAR");
+    prundefvar("GNUTAR");
 #endif
 
 #ifdef COMPRESS_PATH
-    prvar(" COMPRESS_PATH", COMPRESS_PATH);
+    prvar("COMPRESS_PATH", COMPRESS_PATH);
 #else
-    prundefvar(" COMPRESS_PATH");
+    prundefvar("COMPRESS_PATH");
 #endif
 
 #ifdef UNCOMPRESS_PATH
-    prvar(" UNCOMPRESS_PATH", UNCOMPRESS_PATH);
+    prvar("UNCOMPRESS_PATH", UNCOMPRESS_PATH);
 #else
-    prundefvar(" UNCOMPRESS_PATH");
+    prundefvar("UNCOMPRESS_PATH");
 #endif
 
 #ifdef LPRCMD
-    prvar(" LPRCMD", LPRCMD);
+    prvar("LPRCMD", LPRCMD);
 #else
     prundefvar(" LPRCMD");
 #endif
 
-    prvar(" MAILER", MAILER);
+    prvar("MAILER", MAILER);
 
 #ifdef GNUTAR_LISTED_INCREMENTAL_DIR
-    prvar(" listed_incr_dir", GNUTAR_LISTED_INCREMENTAL_DIR);
+    prvar("listed_incr_dir", GNUTAR_LISTED_INCREMENTAL_DIR);
 #else
-    prundefvar(" listed_incr_dir");
+    prundefvar("GNUTAR_LISTED_INCREMENTAL_DIR");
 #endif
+    endline();
 
-    newline();
-
+    startline("defs:");
 
-    prstr("defs: "); indent = linelen;
-
-    prvar(" DEFAULT_SERVER", DEFAULT_SERVER);
-    prvar(" DEFAULT_CONFIG", DEFAULT_CONFIG);
-    prvar(" DEFAULT_TAPE_SERVER", DEFAULT_TAPE_SERVER);
-    prvar(" DEFAULT_TAPE_DEVICE", DEFAULT_TAPE_DEVICE);
+    prvar("DEFAULT_SERVER", DEFAULT_SERVER);
+    prvar("DEFAULT_CONFIG", DEFAULT_CONFIG);
+    prvar("DEFAULT_TAPE_SERVER", DEFAULT_TAPE_SERVER);
+    prvar("DEFAULT_TAPE_DEVICE", DEFAULT_TAPE_DEVICE);
 
 #ifdef AIX_BACKUP
-    prstr(" AIX_BACKUP");
+    prstr("AIX_BACKUP");
 #endif
 
 #ifdef AIX_TAPEIO
-    prstr(" AIX_TAPEIO");
+    prstr("AIX_TAPEIO");
 #endif
 
 #ifdef BROKEN_VOID
-    prstr(" BROKEN_VOID");
+    prstr("BROKEN_VOID");
 #endif
 
 #ifdef DUMP_RETURNS_1
-    prstr(" DUMP_RETURNS_1");
+    prstr("DUMP_RETURNS_1");
 #endif
 
 #ifdef HAVE_MMAP
-    prstr(" HAVE_MMAP");
+    prstr("HAVE_MMAP");
 #endif
 
 #ifndef HAVE_STRERROR
-    prstr(" NEED_STRERROR");
+    prstr("NEED_STRERROR");
 #endif
 
 #ifndef HAVE_STRSTR
-    prstr(" NEED_STRSTR");
+    prstr("NEED_STRSTR");
 #endif
 
 #ifdef HAVE_SYSVSHM
-    prstr(" HAVE_SYSVSHM");
+    prstr("HAVE_SYSVSHM");
 #endif
 
 #ifdef USE_POSIX_FCNTL
-    prstr(" LOCKING=POSIX_FCNTL");
+    prstr("LOCKING=POSIX_FCNTL");
 #endif
 #ifdef USE_FLOCK
-    prstr(" LOCKING=FLOCK");
+    prstr("LOCKING=FLOCK");
 #endif
 #ifdef USE_LOCKF
-    prstr(" LOCKING=LOCKF");
+    prstr("LOCKING=LOCKF");
 #endif
 #ifdef USE_LNLOCK
-    prstr(" LOCKING=LNLOCK");
+    prstr("LOCKING=LNLOCK");
 #endif
 #if !defined(USE_POSIX_FCNTL) && !defined(USE_FLOCK) && !defined(USE_LOCK) && !defined(USE_LNLOCK)
-    prstr(" LOCKING=**NONE**");
+    prstr("LOCKING=**NONE**");
 #endif
 
 #ifdef STATFS_BSD
-    prstr(" STATFS_BSD");
+    prstr("STATFS_BSD");
 #endif
 
 #ifdef STATFS_OSF1
-    prstr(" STATFS_OSF1");
+    prstr("STATFS_OSF1");
 #endif
 
 #ifdef STATFS_ULTRIX
-    prstr(" STATFS_ULTRIX");
+    prstr("STATFS_ULTRIX");
 #endif
 
 #ifdef SETPGRP_VOID
-    prstr(" SETPGRP_VOID");
+    prstr("SETPGRP_VOID");
 #endif
 
 #ifdef ASSERTIONS
-    prstr(" ASSERTIONS");
+    prstr("ASSERTIONS");
 #endif
 
 #ifdef DEBUG_CODE
-    prstr(" DEBUG_CODE");
+    prstr("DEBUG_CODE");
 #endif
 
 #ifdef AMANDA_DEBUG_DAYS
-    prnum(" AMANDA_DEBUG_DAYS", AMANDA_DEBUG_DAYS);
+    prnum("AMANDA_DEBUG_DAYS", AMANDA_DEBUG_DAYS);
 #endif
 
 #ifdef BSD_SECURITY
-    prstr(" BSD_SECURITY");
+    prstr("BSD_SECURITY");
 #endif
 
-#ifdef USE_AMANDAHOSTS
-    prstr(" USE_AMANDAHOSTS");
+#ifdef KRB4_SECURITY
+    prstr("KRB4_SECURITY");
 #endif
 
-#ifdef USE_RUNDUMP
-    prstr(" USE_RUNDUMP");
+#ifdef KRB5_SECURITY
+    prstr("KRB5_SECURITY");
 #endif
 
-#ifdef KRB4_SECURITY
-#define HOSTNAME_INSTANCE "<hostname>"
-    {
-       char lifetime_str[NUM_STR_SIZE];
-
-       prstr(" KRB4_SECURITY");
-       prvar(" SERVER_HOST_PRINCIPLE", SERVER_HOST_PRINCIPLE);
-       prvar(" SERVER_HOST_INSTANCE", SERVER_HOST_INSTANCE);
-       prvar(" SERVER_HOST_KEY_FILE", SERVER_HOST_KEY_FILE);
-       prvar(" CLIENT_HOST_PRINCIPLE", CLIENT_HOST_PRINCIPLE);
-       prvar(" CLIENT_HOST_INSTANCE", CLIENT_HOST_INSTANCE);
-       prvar(" CLIENT_HOST_KEY_FILE", CLIENT_HOST_KEY_FILE);
-       ap_snprintf(lifetime_str, sizeof(lifetime_str), "%d", TICKET_LIFETIME);
-       prvar(" TICKET_LIFETIME", lifetime_str);
-    }
+#ifdef RSH_SECURITY
+    prstr("RSH_SECURITY");
+#endif
+
+#ifdef USE_AMANDAHOSTS
+    prstr("USE_AMANDAHOSTS");
+#endif
+
+#ifdef USE_RUNDUMP
+    prstr("USE_RUNDUMP");
 #endif
 
-    prvar(" CLIENT_LOGIN", CLIENT_LOGIN);
+    prvar("CLIENT_LOGIN", CLIENT_LOGIN);
 
 #ifdef FORCE_USERID
-    prstr(" FORCE_USERID");
+    prstr("FORCE_USERID");
 #endif
 
 #ifdef USE_VERSION_SUFFIXES
-    prstr(" USE_VERSION_SUFFIXES");
+    prstr("USE_VERSION_SUFFIXES");
 #endif
 
 #ifdef HAVE_GZIP
-    prstr(" HAVE_GZIP");
+    prstr("HAVE_GZIP");
 #endif
 
 #ifdef COMPRESS_SUFFIX
-    prvar(" COMPRESS_SUFFIX", COMPRESS_SUFFIX);
+    prvar("COMPRESS_SUFFIX", COMPRESS_SUFFIX);
 #endif
 
 #ifdef COMPRESS_FAST_OPT
-    prvar(" COMPRESS_FAST_OPT", COMPRESS_FAST_OPT);
+    prvar("COMPRESS_FAST_OPT", COMPRESS_FAST_OPT);
 #endif
 
 #ifdef COMPRESS_BEST_OPT
-    prvar(" COMPRESS_BEST_OPT", COMPRESS_BEST_OPT);
+    prvar("COMPRESS_BEST_OPT", COMPRESS_BEST_OPT);
 #endif
 
 #ifdef UNCOMPRESS_OPT
-    prvar(" UNCOMPRESS_OPT", UNCOMPRESS_OPT);
+    prvar("UNCOMPRESS_OPT", UNCOMPRESS_OPT);
 #endif
 
-    newline();
-
+    endline();
 
     printf("  0\n};\n");
 
-    amfree(str);
-
-    malloc_size_2 = malloc_inuse(&malloc_hist_2);
-
-    if(malloc_size_1 != malloc_size_2) {
-       malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
-    }
-
-    return 0;
+    exit(0);
 }
index 93e52f8ace3303a1c73b225b969ab91c59277273..a7601c638d75717698790da4ba53b54cbeceb3c7 100644 (file)
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
-/* $Id: getcwd.c,v 1.3.12.1 2002/02/11 01:30:42 jrjackson Exp $ */
+/* $Id: getcwd.c,v 1.4 2002/02/11 01:32:10 jrjackson Exp $ */
 
 #ifndef lint
-static char rcsid[] = "$Header: /cvsroot/amanda/amanda/common-src/getcwd.c,v 1.3.12.1 2002/02/11 01:30:42 jrjackson Exp $ SPRITE (Berkeley)";
+static char rcsid[] = "$Header: /cvsroot/amanda/amanda/common-src/getcwd.c,v 1.4 2002/02/11 01:32:10 jrjackson Exp $ SPRITE (Berkeley)";
 #endif /* not lint */
 
 #include <stdio.h>
index 521ba7139e705ae3edb97ad5087a54a3d1f040af..d11d5c325c82a006e1d13c16c00e150ef9616126 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1993 University of Maryland
+ * Copyright (c) 1993,1999 University of Maryland
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
  */
+
 /*
+ * $Id: krb4-security.c,v 1.9 2006/02/21 04:13:55 ktill Exp $
+ *
  * krb4-security.c - helper functions for kerberos v4 security.
  */
+
+#include "config.h"
+#ifdef KRB4_SECURITY
+
+#include <des.h>
+#include <krb.h>
+
 #include "amanda.h"
-#include "krb4-security.h"
+#include "dgram.h"
+#include "event.h"
+#include "packet.h"
+#include "queue.h"
+#include "security.h"
 #include "protocol.h"
+#include "stream.h"
+#include "version.h"
+
+
+/*
+ * If you don't have atexit() or on_exit(), you could just consider
+ * making atexit() empty and clean up your ticket files some other
+ * way
+ */
+#ifndef HAVE_ATEXIT
+#ifdef HAVE_ON_EXIT
+#define        atexit(func)    on_exit(func, 0)
+#else
+#define        atexit(func)    (you must to resolve lack of atexit)
+#endif /* HAVE_ON_EXIT */
+#endif /* ! HAVE_ATEXIT */
+
+int krb_set_lifetime P((int));
+int kuserok P((AUTH_DAT *, char *));
+
+/*
+ * This is the private handle data
+ */
+struct krb4_handle {
+    security_handle_t sech;    /* MUST be first */
+    struct sockaddr_in peer;   /* host on other side */
+    char hostname[MAX_HOSTNAME_LENGTH+1];      /* human form of above */
+    char proto_handle[32];     /* protocol handle for this req */
+    int sequence;              /* last sequence number we received */
+    char inst[INST_SZ];                /* krb4 instance form of above */
+    char realm[REALM_SZ];      /* krb4 realm of this host */
+    unsigned long cksum;       /* cksum of the req packet we sent */
+    des_cblock session_key;    /* session key */
+
+    /*
+     * The rest is used for the async recvpkt/recvpkt_cancel
+     * interface.
+     */
+    void (*fn) P((void *, pkt_t *, security_status_t));
+                                       /* func to call when packet recvd */
+    void *arg;                         /* argument to pass function */
+    event_handle_t *ev_timeout;                /* timeout handle for recv */
+    TAILQ_ENTRY(krb4_handle) tq;       /* queue handle */
+};
+
+/*
+ * This is the internal security_stream data for krb4.
+ */
+struct krb4_stream {
+    security_stream_t secstr;          /* MUST be first */
+    struct krb4_handle *krb4_handle;   /* pointer into above */
+    int fd;                            /* io file descriptor */
+    int port;                          /* local port this is bound to */
+    int socket;                                /* fd for server-side accepts */
+    event_handle_t *ev_read;           /* read event handle */
+    char databuf[MAX_TAPE_BLOCK_BYTES];        /* read buffer */
+    void (*fn) P((void *, void *, int));       /* read event fn */
+    void *arg;                         /* arg for previous */
+};
+
+/*
+ * This is the tcp stream buffer size
+ */
+#define        STREAM_BUFSIZE  (MAX_TAPE_BLOCK_BYTES * 2)
+
+/*
+ * Interface functions
+ */
+static void krb4_connect P((const char *,
+    char *(*)(char *, void *),  
+    void (*)(void *, security_handle_t *, security_status_t), void *));
+static void krb4_accept P((int, int, void (*)(security_handle_t *, pkt_t *)));
+static void krb4_close P((void *));
+static int krb4_sendpkt P((void *, pkt_t *));
+static void krb4_recvpkt P((void *,
+    void (*)(void *, pkt_t *, security_status_t), void *, int));
+static void krb4_recvpkt_cancel P((void *));
+
+static void *krb4_stream_server P((void *));
+static int krb4_stream_accept P((void *));
+static void *krb4_stream_client P((void *, int));
+static void krb4_stream_close P((void *));
+static int krb4_stream_auth P((void *));
+static int krb4_stream_id P((void *));
+static int krb4_stream_write P((void *, const void *, size_t));
+static void krb4_stream_read P((void *, void (*)(void *, void *, int),
+    void *));
+static void krb4_stream_read_cancel P((void *));
+
+
+/*
+ * This is our interface to the outside world.
+ */
+const security_driver_t krb4_security_driver = {
+    "KRB4",
+    krb4_connect,
+    krb4_accept,
+    krb4_close,
+    krb4_sendpkt,
+    krb4_recvpkt,
+    krb4_recvpkt_cancel,
+    krb4_stream_server,
+    krb4_stream_accept,
+    krb4_stream_client,
+    krb4_stream_close,
+    krb4_stream_auth,
+    krb4_stream_id,
+    krb4_stream_write,
+    krb4_stream_read,
+    krb4_stream_read_cancel,
+};
+
+/*
+ * Cache the local hostname
+ */
+static char hostname[MAX_HOSTNAME_LENGTH+1];
+
+/*
+ * This is the dgram_t that we use to send and recv protocol packets
+ * over the net.  There is only one per process, so it lives globally
+ * here.
+ */
+static dgram_t netfd;
+
+/*
+ * This is a queue of outstanding async requests
+ */
+static struct {
+    TAILQ_HEAD(, krb4_handle) tailq;
+    int qlength;
+} handleq = {
+    TAILQ_HEAD_INITIALIZER(handleq.tailq), 0
+};
+
+/*
+ * Macros to add or remove krb4_handles from the above queue
+ */
+#define        handleq_add(kh) do {                    \
+    assert(handleq.qlength == 0 ? TAILQ_FIRST(&handleq.tailq) == NULL : 1); \
+    TAILQ_INSERT_TAIL(&handleq.tailq, kh, tq); \
+    handleq.qlength++;                         \
+} while (0)
+
+#define        handleq_remove(kh)      do {                    \
+    assert(handleq.qlength > 0);                       \
+    assert(TAILQ_FIRST(&handleq.tailq) != NULL);       \
+    TAILQ_REMOVE(&handleq.tailq, kh, tq);              \
+    handleq.qlength--;                                 \
+    assert((handleq.qlength == 0) ^ (TAILQ_FIRST(&handleq.tailq) != NULL)); \
+} while (0)
+
+#define        handleq_first()         TAILQ_FIRST(&handleq.tailq)
+#define        handleq_next(kh)        TAILQ_NEXT(kh, tq)
+       
+
+/*
+ * This is the event manager's handle for our netfd
+ */
+static event_handle_t *ev_netfd;
+
+/*
+ * This is a function that should be called if a new security_handle_t is
+ * created.  If NULL, no new handles are created.
+ * It is passed the new handle and the received pkt
+ */
+static void (*accept_fn) P((security_handle_t *, pkt_t *));
+
+
+/*
+ * This is a structure used in encoding the cksum in a mutual-auth
+ * transaction.  The checksum is placed in here first before encryption
+ * because encryption requires at least 8 bytes of data, and an unsigned
+ * long on most machines (32 bit ones) is 4 bytes.
+ */
+union mutual {
+    char pad[8];
+    unsigned long cksum;
+};
+
+/*
+ * Private functions
+ */
+static unsigned long krb4_cksum P((const char *));
+static void krb4_getinst P((const char *, char *, size_t));
+static void host2key P((const char *, const char *, des_cblock *));
+static void init P((void));
+static void inithandle P((struct krb4_handle *, struct hostent *, int,
+    const char *));
+static void get_tgt P((void));
+static void killtickets P((void));
+static void recvpkt_callback P((void *));
+static void recvpkt_timeout P((void *));
+static int recv_security_ok P((struct krb4_handle *, pkt_t *));
+static void stream_read_callback P((void *));
+static int net_write P((int, const void *, size_t));
+static int net_read P((int, void *, size_t, int));
+
+static int add_ticket P((struct krb4_handle *, const pkt_t *, dgram_t *));
+static void add_mutual_auth P((struct krb4_handle *, dgram_t *));
+static int check_ticket P((struct krb4_handle *, const pkt_t *,
+    const char *, unsigned long));
+static int check_mutual_auth P((struct krb4_handle *, const char *));
+
+static const char *pkthdr2str P((const struct krb4_handle *, const pkt_t *));
+static int str2pkthdr P((const char *, pkt_t *, char *, size_t, int *));
+
+static const char *bin2astr P((const unsigned char *, int));
+static void astr2bin P((const char *, unsigned char *, int *));
+
+static void encrypt_data P((void *, int, des_cblock *));
+static void decrypt_data P((void *, int, des_cblock *));
 
 #define HOSTNAME_INSTANCE inst
 
 static char *ticketfilename = NULL;
 
-int krb4_auth = 0;
-int kencrypt = 0;
-des_cblock session_key;
-uint32_t auth_cksum;           /* was 'long' on 32-bit platforms */
-
-void krb4_killtickets(void)
+static void
+killtickets(void)
 {
-    if(ticketfilename != NULL)
+    if (ticketfilename != NULL)
        unlink(ticketfilename);
     amfree(ticketfilename);
 }
 
-void kerberos_service_init()
+/*
+ * Setup some things about krb4.  This should only be called once.
+ */
+static void
+init()
 {
-    int rc;
-    char hostname[MAX_HOSTNAME_LENGTH+1], inst[256], realm[256];
-#if defined(HAVE_PUTENV)
-    char *tkt_env = NULL;
-#endif
-    char uid_str[NUM_STR_SIZE];
-    char pid_str[NUM_STR_SIZE];
+    char tktfile[256];
+    int port;
+    static int beenhere = 0;
 
-    gethostname(hostname, sizeof(hostname)-1);
-    hostname[sizeof(hostname)-1] = '\0';
+    if (beenhere)
+       return;
+    beenhere = 1;
 
-    if(ticketfilename == NULL)
-       atexit(krb4_killtickets);
+    gethostname(hostname, sizeof(hostname) - 1);
+    hostname[sizeof(hostname) - 1] = '\0';
 
-    host2krbname(hostname, inst, realm);
+    if (atexit(killtickets) < 0)
+       error("could not setup krb4 exit handler: %s", strerror(errno));
 
     /*
      * [XXX] It could be argued that if KRBTKFILE is set outside of amanda,
@@ -71,581 +293,1429 @@ void kerberos_service_init()
      * This file also needs to be removed so that no extra tickets are
      * hanging around.
      */
-    ap_snprintf(uid_str, sizeof(uid_str), "%ld", (long)getuid());
-    ap_snprintf(pid_str, sizeof(pid_str), "%ld", (long)getpid());
-    ticketfilename = newvstralloc(ticketfilename,
-                                 "/tmp/tkt",
-                                 uid_str, "-", pid_str,
-                                 ".amanda",
-                                 NULL);
+    snprintf(tktfile, sizeof(tktfile), "/tmp/tkt%ld-%ld.amanda",
+       (long)getuid(), (long)getpid());
+    ticketfilename = stralloc(tktfile);
+    unlink(ticketfilename);
     krb_set_tkt_string(ticketfilename);
 #if defined(HAVE_PUTENV)
-    tkt_env = stralloc2("KRBTKFILE=", ticketfilename);
-    putenv(tkt_env);
-    amfree(tkt_env);
+    {
+       char *tkt_env = stralloc2("KRBTKFILE=", ticketfilename);
+       putenv(tkt_env);
+    }
 #else
-    setenv("KRBTKFILE",ticketfilename,1);
+    setenv("KRBTKFILE", ticketfile, 1);
 #endif
 
+    dgram_zero(&netfd);
+    dgram_bind(&netfd, &port);
+}
+
+/*
+ * Get a ticket granting ticket and stuff it in the cache
+ */
+static void
+get_tgt()
+{
+    char realm[REALM_SZ];
+    int rc;
+
+    strncpy(realm, krb_realmofhost(hostname), sizeof(realm) - 1);
+    realm[sizeof(realm) - 1] = '\0';
+
     rc = krb_get_svc_in_tkt(SERVER_HOST_PRINCIPLE, SERVER_HOST_INSTANCE,
-                           realm, "krbtgt", realm, TICKET_LIFETIME,
-                           SERVER_HOST_KEY_FILE);
-    if(rc) error("could not get krbtgt for %s.%s@%s from %s: %s",
-                SERVER_HOST_PRINCIPLE, SERVER_HOST_INSTANCE, realm,
-                SERVER_HOST_KEY_FILE, krb_err_txt[rc]);
+       realm, "krbtgt", realm, TICKET_LIFETIME, SERVER_HOST_KEY_FILE);
+
+    if (rc != 0) {
+       error("could not get krbtgt for %s.%s@%s from %s: %s",
+           SERVER_HOST_PRINCIPLE, SERVER_HOST_INSTANCE, realm,
+           SERVER_HOST_KEY_FILE, krb_err_txt[rc]);
+    }
 
     krb_set_lifetime(TICKET_LIFETIME);
 }
 
 
-uint32_t kerberos_cksum(str)
-char *str;
+/*
+ * krb4 version of a security handle allocator.  Logically sets
+ * up a network "connection".
+ */
+static void
+krb4_connect(hostname, conf_fn, fn, arg)
+    const char *hostname;
+    char *(*conf_fn) P((char *, void *));
+    void (*fn) P((void *, security_handle_t *, security_status_t));
+    void *arg;
 {
-    des_cblock seed;
+    struct krb4_handle *kh;
+    char handle[32];
+    struct servent *se;
+    struct hostent *he;
+    int port;
 
-    memset(seed, 0, sizeof(seed));
-    return quad_cksum(str, NULL, strlen(str), 1, seed);
-}
+    assert(hostname != NULL);
 
-struct hostent *host2krbname(alias, inst, realm)
-char *alias, *inst, *realm;
-{
-    struct hostent *hp;
-    char *s, *d, *krb_realmofhost();
-    char saved_hostname[1024];
+    /*
+     * Make sure we're initted
+     */
+    init();
 
-    if((hp = gethostbyname(alias)) == 0) return 0;
+    kh = alloc(sizeof(*kh));
+    security_handleinit(&kh->sech, &krb4_security_driver);
 
-    /* get inst name: like krb_get_phost, but avoid multiple gethostbyname */
+    if ((he = gethostbyname(hostname)) == NULL) {
+       security_seterror(&kh->sech,
+           "%s: could not resolve hostname", hostname);
+       (*fn)(arg, &kh->sech, S_ERROR);
+       return;
+    }
+    if ((se = getservbyname(KAMANDA_SERVICE_NAME, "udp")) == NULL)
+       port = htons(KAMANDA_SERVICE_DEFAULT);
+    else
+       port = se->s_port;
+    snprintf(handle, sizeof(handle), "%ld", (long)time(NULL));
+    inithandle(kh, he, port, handle);
+    (*fn)(arg, &kh->sech, S_OK);
+}
 
-    for(s = hp->h_name, d = inst; *s && *s != '.'; s++, d++)
-       *d = isupper(*s)? tolower(*s) : *s;
-    *d = '\0';
+/*
+ * Setup to handle new incoming connections
+ */
+static void
+krb4_accept(in, out, fn)
+    int in, out;
+    void (*fn) P((security_handle_t *, pkt_t *));
+{
 
     /*
-     * It isn't safe to pass hp->h_name to krb_realmofhost, since
-     * it might use gethostbyname internally.
+     * Make sure we're initted
      */
-    bzero(saved_hostname, sizeof(saved_hostname));
-    strncpy(saved_hostname, hp->h_name, sizeof(saved_hostname)-1);
+    init();
 
-    /* get realm name: krb_realmofhost always returns *something* */
-    strcpy(realm, krb_realmofhost(saved_hostname));
+    /*
+     * We assume that in and out both point to the same socket
+     */
+    dgram_socket(&netfd, in);
+
+    /*
+     * Assign the function and return.  When they call recvpkt later,
+     * the recvpkt callback will call this function when it discovers
+     * new incoming connections
+     */
+    accept_fn = fn;
 
-    return hp;
+    if (ev_netfd == NULL)
+       ev_netfd = event_register(netfd.socket, EV_READFD,
+           recvpkt_callback, NULL);
 }
 
-void encrypt_data(data, length, key)
-void *data;
-int length;
-des_cblock key;
+/*
+ * Given a hostname and a port, setup a krb4_handle
+ */
+static void
+inithandle(kh, he, port, handle)
+    struct krb4_handle *kh;
+    struct hostent *he;
+    int port;
+    const char *handle;
 {
-    des_key_schedule sched;
 
-    des_key_sched(key, sched);
-    des_pcbc_encrypt(data, data, length, sched, key, DES_ENCRYPT);
-}
+    /*
+     * Get the instance and realm for this host
+     * (krb_realmofhost always returns something)
+     */
+    krb4_getinst(he->h_name, kh->inst, sizeof(kh->inst));
+    strncpy(kh->realm, krb_realmofhost(he->h_name), sizeof(kh->realm) - 1);
+    kh->realm[sizeof(kh->realm) - 1] = '\0';
 
+    /*
+     * Save a copy of the hostname
+     */
+    strncpy(kh->hostname, he->h_name, sizeof(kh->hostname) - 1);
+    kh->hostname[sizeof(kh->hostname) - 1] = '\0';
 
-void decrypt_data(data, length, key)
-void *data;
-int length;
-des_cblock key;
-{
-    des_key_schedule sched;
+    /*
+     * We have no checksum or session key at this point
+     */
+    kh->cksum = 0;
+    memset(kh->session_key, 0, sizeof(kh->session_key));
 
-    des_key_sched(key, sched);
-    des_pcbc_encrypt(data, data, length, sched, key, DES_DECRYPT);
+    /*
+     * Setup our peer info.  We don't do anything with the sequence yet,
+     * so just leave it at 0.
+     */
+    kh->peer.sin_family = AF_INET;
+    kh->peer.sin_port = port;
+    kh->peer.sin_addr = *(struct in_addr *)he->h_addr;
+    strncpy(kh->proto_handle, handle, sizeof(kh->proto_handle) - 1);
+    kh->proto_handle[sizeof(kh->proto_handle) - 1] = '\0';
+    kh->sequence = 0;
+    kh->fn = NULL;
+    kh->arg = NULL;
+    kh->ev_timeout = NULL;
 }
 
-
 /*
- * struct timeval is a host structure, and may not be used in
- * protocols, because members are defined as 'long', rather than
- * uint32_t.
+ * frees a handle allocated by the above
  */
-typedef struct net_tv {
-  int32_t tv_sec;
-  int32_t tv_usec;
-} net_tv;
+static void
+krb4_close(inst)
+    void *inst;
+{
 
-int kerberos_handshake(fd, key)
-int fd;
-des_cblock key;
+    krb4_recvpkt_cancel(inst);
+    amfree(inst);
+}
+
+/*
+ * Transmit a packet.  Add security information first.
+ */
+static int
+krb4_sendpkt(cookie, pkt)
+    void *cookie;
+    pkt_t *pkt;
 {
-    int rc;
-    struct timeval local;
-    net_tv localenc, remote, rcvlocal;
-    struct timezone tz;
-    char *strerror();
-    char *d;
-    int l, n, s;
+    struct krb4_handle *kh = cookie;
+
+    assert(kh != NULL);
+    assert(pkt != NULL);
 
     /*
-     * There are two mutual authentication transactions going at once:
-     * one in which we prove the to peer that we are the legitimate
-     * party, and one in which the peer proves to us that that they
-     * are legitimate.
-     *
-     * In addition to protecting against spoofing, this exchange
-     * ensures that the two peers have the same keys, protecting
-     * against having data encrypted with one key and decrypted with
-     * another on the backup tape.
+     * Initialize this datagram
      */
+    dgram_zero(&netfd);
 
-    gettimeofday(&local, &tz);
+    /*
+     * Add the header to the packet
+     */
+    dgram_cat(&netfd, pkthdr2str(kh, pkt));
 
-    /* 
-     * Convert time to  network order and sizes, encrypt,  and send to
-     * peer as the first step in  the peer proving to us that they are
-     * legitimate.
-     */
-    localenc.tv_sec = (int32_t) local.tv_sec;
-    localenc.tv_usec = (int32_t) local.tv_usec;
-    localenc.tv_sec = htonl(localenc.tv_sec);
-    localenc.tv_usec = htonl(localenc.tv_usec);
-    assert(sizeof(localenc) == 8);
-    encrypt_data(&localenc, sizeof localenc, key);
-
-    d = (char *)&localenc;
-    for(l = 0, n = sizeof(localenc); l < n; l += s) {
-       if((s = write(fd, d+l, n-l)) < 0) {
-           error("kerberos_handshake write error: [%s]", strerror(errno));
-       }
+    /*
+     * Add the security info.  This depends on which kind of packet we're
+     * sending.
+     */
+    switch (pkt->type) {
+    case P_REQ:
+       /*
+        * Requests get sent with a ticket embedded in the header.  The
+        * checksum is generated from the contents of the body.
+        */
+       if (add_ticket(kh, pkt, &netfd) < 0)
+           return (-1);
+       break;
+    case P_REP:
+       /*
+        * Replies get sent with a mutual authenticator added.  The
+        * mutual authenticator is the encrypted checksum from the
+        * ticket + 1
+        */
+       add_mutual_auth(kh, &netfd);
+       break;
+    case P_ACK:
+    case P_NAK:
+    default:
+       /*
+        * The other types have no security stuff added for krb4.
+        * Shamefull.
+        */
+       break;
     }
 
     /*
-     * Read block from peer and decrypt.  This is the first step in us
-     * proving to the peer that we are legitimate.
+     * Add the body, and send it
      */
-    d = (char *)&remote;
-    assert(sizeof(remote) == 8);
-    for(l = 0, n = sizeof(remote); l < n; l += s) {
-       if((s = read(fd, d+l, n-l)) < 0) {
-           error("kerberos_handshake read error: [%s]", strerror(errno));
-       }
-    }
-    if(l != n) {
-       error("kerberos_handshake read error: [short read]");
+    dgram_cat(&netfd, pkt->body);
+    if (dgram_send_addr(kh->peer, &netfd) != 0) {
+       security_seterror(&kh->sech,
+           "send %s to %s failed: %s", pkt_type2str(pkt->type),
+           kh->hostname, strerror(errno));
+       return (-1);
     }
+    return (0);
+}
 
-    decrypt_data(&remote, sizeof remote, key);
+/*
+ * Set up to receive a packet asyncronously, and call back when
+ * it has been read.
+ */
+static void
+krb4_recvpkt(cookie, fn, arg, timeout)
+    void *cookie, *arg;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    int timeout;
+{
+    struct krb4_handle *kh = cookie;
 
-    /* XXX do timestamp checking here */
+    assert(netfd.socket >= 0);
+    assert(kh != NULL);
 
     /*
-     * Add 1.000001 seconds to the peer's timestamp, leaving it in
-     * network order, re-encrypt and send back.
+     * We register one event handler for our network fd which takes
+     * care of all of our async requests.  When all async requests
+     * have either been satisfied or cancelled, we unregister our
+     * network event handler.
      */
-    remote.tv_sec = ntohl(remote.tv_sec);
-    remote.tv_usec = ntohl(remote.tv_usec);
-    remote.tv_sec += 1;
-    remote.tv_usec += 1;
-    remote.tv_sec = htonl(remote.tv_sec);
-    remote.tv_usec = htonl(remote.tv_usec);
-
-    encrypt_data(&remote, sizeof remote, key);
-
-    d = (char *)&remote;
-    for(l = 0, n = sizeof(remote); l < n; l += s) {
-       if((s = write(fd, d+l, n-l)) < 0) {
-           error("kerberos_handshake write2 error: [%s]", strerror(errno));
-       }
+    if (ev_netfd == NULL) {
+       assert(handleq.qlength == 0);
+       ev_netfd = event_register(netfd.socket, EV_READFD,
+           recvpkt_callback, NULL);
     }
 
     /*
-     * Read the peers reply, decrypt, convert to host order, and
-     * verify that the peer was able to add 1.000001 seconds, thus
-     * showing that it knows the DES key.
+     * Multiple recvpkt calls override previous ones
+     * If kh->fn is NULL then it is not in the queue.
      */
-    d = (char *)&rcvlocal;
-    for(l = 0, n = sizeof(rcvlocal); l < n; l += s) {
-       if((s = read(fd, d+l, n-l)) < 0) {
-           error("kerberos_handshake read2 error: [%s]", strerror(errno));
-       }
+    if (kh->fn == NULL)
+       handleq_add(kh);
+    if (kh->ev_timeout != NULL)
+       event_release(kh->ev_timeout);
+    if (timeout < 0)
+       kh->ev_timeout = NULL;
+    else
+       kh->ev_timeout = event_register(timeout, EV_TIME, recvpkt_timeout, kh);
+    kh->fn = fn;
+    kh->arg = arg;
+}
+
+/*
+ * Remove a async receive request from the queue
+ * If it is the last one to be removed, then remove the event handler
+ * for our network fd.
+ */
+static void
+krb4_recvpkt_cancel(cookie)
+    void *cookie;
+{
+    struct krb4_handle *kh = cookie;
+
+    assert(kh != NULL);
+
+    if (kh->fn != NULL) {
+       handleq_remove(kh);
+       kh->fn = NULL;
+       kh->arg = NULL;
+    }
+    if (kh->ev_timeout != NULL)
+       event_release(kh->ev_timeout);
+    kh->ev_timeout = NULL;
+
+    if (handleq.qlength == 0 && accept_fn == NULL &&
+       ev_netfd != NULL) {
+       event_release(ev_netfd);
+       ev_netfd = NULL;
+    }
+}
+
+/*
+ * Create the server end of a stream.  For krb4, this means setup a tcp
+ * socket for receiving a connection.
+ */
+static void *
+krb4_stream_server(h)
+    void *h;
+{
+    struct krb4_handle *kh = h;
+    struct krb4_stream *ks;
+
+    assert(kh != NULL);
+
+    ks = alloc(sizeof(*ks));
+    security_streaminit(&ks->secstr, &krb4_security_driver);
+    ks->socket = stream_server(&ks->port, STREAM_BUFSIZE, STREAM_BUFSIZE);
+    if (ks->socket < 0) {
+       security_seterror(&kh->sech,
+           "can't create server stream: %s", strerror(errno));
+       amfree(ks);
+       return (NULL);
     }
-    if(l != n) {
-       error("kerberos_handshake read2 error: [short read]");
+    ks->fd = -1;
+    ks->krb4_handle = kh;
+    ks->ev_read = NULL;
+    return (ks);
+}
+
+/*
+ * Accept an incoming connection on a stream_server socket
+ */
+static int
+krb4_stream_accept(s)
+    void *s;
+{
+    struct krb4_stream *ks = s;
+    struct krb4_handle *kh;
+
+    assert(ks != NULL);
+    kh = ks->krb4_handle;
+    assert(kh != NULL);
+    assert(ks->socket >= 0);
+    assert(ks->fd == -1);
+
+    ks->fd = stream_accept(ks->socket, 30, -1, -1);
+    if (ks->fd < 0) {
+       security_stream_seterror(&ks->secstr,
+           "can't accept new stream connection: %s", strerror(errno));
+       return (-1);
     }
+    return (0);
+}
 
-    decrypt_data(&rcvlocal, sizeof rcvlocal, key);
+/*
+ * Return a connected stream.
+ */
+static void *
+krb4_stream_client(h, id)
+    void *h;
+    int id;
+{
+    struct krb4_handle *kh = h;
+    struct krb4_stream *ks;
 
-    rcvlocal.tv_sec = ntohl(rcvlocal.tv_sec);
-    rcvlocal.tv_usec = ntohl(rcvlocal.tv_usec);
+    assert(kh != NULL);
 
-    dbprintf(("handshake: %d %d %d %d\n",
-             local.tv_sec, local.tv_usec,
-             rcvlocal.tv_sec, rcvlocal.tv_usec));
+    if (id < 0) {
+       security_seterror(&kh->sech,
+           "%d: invalid security stream id", id);
+       return (NULL);
+    }
 
-    return (rcvlocal.tv_sec  == (int32_t) (local.tv_sec + 1)) &&
-          (rcvlocal.tv_usec == (int32_t) (local.tv_usec + 1));
+    ks = alloc(sizeof(*ks));
+    security_streaminit(&ks->secstr, &krb4_security_driver);
+    ks->fd = stream_client(kh->hostname, id, STREAM_BUFSIZE, STREAM_BUFSIZE,
+       &ks->port, 0);
+    if (ks->fd < 0) {
+       security_seterror(&kh->sech,
+           "can't connect stream to %s port %d: %s", kh->hostname, id,
+           strerror(errno));
+       amfree(ks);
+       return (NULL);
+    }
+
+    ks->socket = -1;   /* we're a client */
+    ks->krb4_handle = kh;
+    ks->ev_read = NULL;
+    return (ks);
 }
 
-des_cblock *host2key(hostname)
-char *hostname;
+/*
+ * Close and unallocate resources for a stream.
+ */
+static void
+krb4_stream_close(s)
+    void *s;
 {
-    static des_cblock key;
-    char inst[256], realm[256];
-    CREDENTIALS cred;
+    struct krb4_stream *ks = s;
 
-    if(host2krbname(hostname, inst, realm))
-       krb_get_cred(CLIENT_HOST_PRINCIPLE, CLIENT_HOST_INSTANCE, realm,&cred);
+    assert(ks != NULL);
 
-    memcpy(key, cred.session, sizeof key);
-    return &key;
+    if (ks->fd != -1)
+       aclose(ks->fd);
+    if (ks->socket != -1)
+       aclose(ks->socket);
+    krb4_stream_read_cancel(ks);
+    amfree(ks);
 }
 
-int check_mutual_authenticator(key, pkt, p)
-des_cblock *key;
-pkt_t *pkt;
-proto_t *p;
+/*
+ * Authenticate a stream
+ *
+ * XXX this whole thing assumes the size of struct timeval is consistent,
+ * which is may not be!  We need to extract the network byte order data
+ * into byte arrays and send those.
+ */
+static int
+krb4_stream_auth(s)
+    void *s;
 {
-    char *astr = NULL;
-    union {
-       char pad[8];
-       uint32_t i;
-    } mutual;
-    int len;
-    char *s, *fp;
-    int ch;
+    struct krb4_stream *ks = s;
+    struct krb4_handle *kh;
+    int fd;
+    struct timeval local, enc;
+    struct timezone tz;
 
-    if(pkt->security == NULL) {
-       fprintf(stderr," pkt->security is NULL\n");
-       return 0;
-    }
+    assert(ks != NULL);
+    assert(ks->fd >= 0);
+
+    fd = ks->fd;
+    kh = ks->krb4_handle;
+
+    /* make sure we're open */
+    assert(fd >= 0);
 
-    s = pkt->security;
-    ch = *s++;
+    /* make sure our timeval is what we're expecting, see above */
+    assert(sizeof(struct timeval) == 8);
 
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-        fprintf(stderr,"pkt->security is actually %s\n", pkt->security);
-       return 0;
+    /*
+     * Get the current time, put it in network byte order, encrypt it
+     * and present it to the other side.
+     */
+    gettimeofday(&local, &tz);
+    enc.tv_sec = htonl(local.tv_sec);
+    enc.tv_usec = htonl(local.tv_usec);
+    encrypt_data(&enc, sizeof(enc), &kh->session_key);
+    if (net_write(fd, &enc, sizeof(enc)) < 0) {
+       security_stream_seterror(&ks->secstr,
+           "krb4 stream handshake write error: %s", strerror(errno));
+       return (-1);
     }
-    fp = s-1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    if(strcmp(fp, "MUTUAL-AUTH") != 0) {
-       s[-1] = ch;
-        fprintf(stderr,"pkt->security is actually %s\n", pkt->security);
-       return 0;
+
+    /*
+     * Read back the other side's presentation.  Increment the seconds
+     * and useconds by one.  Reencrypt, and present to the other side.
+     * Timeout in 10 seconds.
+     */
+    if (net_read(fd, &enc, sizeof(enc), 10) < 0) {
+       security_stream_seterror(&ks->secstr,
+           "krb4 stream handshake read error: %s", strerror(errno));
+       return (-1);
+    }
+    decrypt_data(&enc, sizeof(enc), &kh->session_key);
+    /* XXX do timestamp checking here */
+    enc.tv_sec = htonl(ntohl(enc.tv_sec) + 1);
+    enc.tv_usec = htonl(ntohl(enc.tv_usec) + 1);
+    encrypt_data(&enc, sizeof(enc), &kh->session_key);
+
+    if (net_write(fd, &enc, sizeof(enc)) < 0) {
+       security_stream_seterror(&ks->secstr,
+           "krb4 stream handshake write error: %s", strerror(errno));
+       return (-1);
     }
-    s[-1] = ch;
 
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-        fprintf(stderr,"pkt->security is actually %s\n", pkt->security);
-       return 0;
+    /*
+     * Read back the other side's processing of our data.
+     * If they incremented it properly, then succeed.
+     * Timeout in 10 seconds.
+     */
+    if (net_read(fd, &enc, sizeof(enc), 10) < 0) {
+       security_stream_seterror(&ks->secstr,
+           "krb4 stream handshake read error: %s", strerror(errno));
+       return (-1);
     }
-    astr = s-1;
-    while(ch && ch != '\n') ch = *s++;
-    s[-1] = '\0';
+    decrypt_data(&enc, sizeof(enc), &kh->session_key);
+    if (ntohl(enc.tv_sec)  == local.tv_sec + 1 &&
+       ntohl(enc.tv_usec) == local.tv_usec + 1)
+           return (0);
+
+    security_stream_seterror(&ks->secstr,
+       "krb4 handshake failed: sent %ld,%ld - recv %ld,%ld",
+           (long)(local.tv_sec + 1), (long)(local.tv_usec + 1),
+           (long)ntohl(enc.tv_sec), (long)ntohl(enc.tv_usec));
+    return (-1);
+}
 
-    /* XXX - goddamn it this is a worm-hole */
-    astr2bin(astr, (unsigned char *)mutual.pad, &len);
+/*
+ * Returns the stream id for this stream.  This is just the local
+ * port.
+ */
+static int
+krb4_stream_id(s)
+    void *s;
+{
+    struct krb4_stream *ks = s;
 
-    s[-1] = ch;
+    assert(ks != NULL);
 
-    decrypt_data(&mutual, len, *key);
-    mutual.i = ntohl(mutual.i);
-    return mutual.i == p->auth_cksum + 1;
+    return (ks->port);
 }
 
-char *get_krb_security(str, host_inst, realm, cksum)
-char *str;
-char *host_inst, *realm;
-uint32_t *cksum;
+/*
+ * Write a chunk of data to a stream.  Blocks until completion.
+ */
+static int
+krb4_stream_write(s, buf, size)
+    void *s;
+    const void *buf;
+    size_t size;
 {
-    KTEXT_ST ticket;
-    int rc;
-    char inst[INST_SZ];
+    struct krb4_stream *ks = s;
+    struct krb4_handle *kh = ks->krb4_handle;
 
-    *cksum = kerberos_cksum(str);
+    assert(ks != NULL);
+    assert(kh != NULL);
 
-#if CLIENT_HOST_INSTANCE == HOSTNAME_INSTANCE
-#undef HOSTNAME_INSTANCE
-#define HOSTNAME_INSTANCE host_inst
-#endif
+    if (net_write(ks->fd, buf, size) < 0) {
+       security_stream_seterror(&ks->secstr,
+           "write error on stream %d: %s", ks->fd, strerror(errno));
+       return (-1);
+    }
+    return (0);
+}
+
+/*
+ * Submit a request to read some data.  Calls back with the given
+ * function and arg when completed.
+ */
+static void
+krb4_stream_read(s, fn, arg)
+    void *s, *arg;
+    void (*fn) P((void *, void *, int));
+{
+    struct krb4_stream *ks = s;
+
+    assert(ks != NULL);
 
     /*
-     * the instance must be in writable memory of size INST_SZ
-     * krb_mk_req might change it
+     * Only one read request can be active per stream.
      */
-    strncpy(inst, CLIENT_HOST_INSTANCE, sizeof(inst) - 1);
-    inst[sizeof(inst) - 1] = '\0';
-    if((rc = krb_mk_req(&ticket, CLIENT_HOST_PRINCIPLE, inst, realm, *cksum))) {
-       if(rc == NO_TKT_FIL) {
-           /* It's been kdestroyed.  Get a new one and try again */
-           kerberos_service_init();
-           rc = krb_mk_req(&ticket, CLIENT_HOST_PRINCIPLE, 
-                           CLIENT_HOST_INSTANCE, realm, *cksum);
-       }
-       if(rc) return NULL;
+    if (ks->ev_read != NULL)
+       event_release(ks->ev_read);
+
+    ks->ev_read = event_register(ks->fd, EV_READFD, stream_read_callback, ks);
+    ks->fn = fn;
+    ks->arg = arg;
+}
+
+/*
+ * Cancel a previous stream read request.  It's ok if we didn't have a read
+ * scheduled.
+ */
+static void
+krb4_stream_read_cancel(s)
+    void *s;
+{
+    struct krb4_stream *ks = s;
+
+    assert(ks != NULL);
+
+    if (ks->ev_read != NULL) {
+       event_release(ks->ev_read);
+       ks->ev_read = NULL;
     }
-    return stralloc2("SECURITY TICKET ",
-                    bin2astr((unsigned char *)ticket.dat, ticket.length));
 }
 
+/*
+ * Callback for krb4_stream_read
+ */
+static void
+stream_read_callback(arg)
+    void *arg;
+{
+    struct krb4_stream *ks = arg;
+    int n;
+
+    assert(ks != NULL);
+    assert(ks->fd != -1);
+
+    /*
+     * Remove the event first, and then call the callback.
+     * We remove it first because we don't want to get in their
+     * way if they reschedule it.
+     */
+    krb4_stream_read_cancel(ks);
+    n = read(ks->fd, ks->databuf, sizeof(ks->databuf));
+    if (n < 0)
+       security_stream_seterror(&ks->secstr,
+           strerror(errno));
+    (*ks->fn)(ks->arg, ks->databuf, n);
+}
 
-int krb4_security_ok(addr, str, cksum, errstr)
-struct sockaddr_in *addr;
-char *str;
-uint32_t cksum;
-char **errstr;
+/*
+ * The callback for recvpkt() for the event handler
+ * Determines if this packet is for this security handle,
+ * and does the real callback if so.
+ */
+static void
+recvpkt_callback(cookie)
+    void *cookie;
 {
-    KTEXT_ST ticket;
-    AUTH_DAT auth;
-    char *ticket_str, *user, inst[INST_SZ], hname[256];
-    struct passwd *pwptr;
-    int myuid, rc;
-    char *s;
-    int ch;
+    char handle[32];
+    struct sockaddr_in peer;
+    pkt_t pkt;
+    int sequence;
+    struct krb4_handle *kh;
+    struct hostent *he;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    void *arg;
 
-    /* extract the ticket string from the message */
+    assert(cookie == NULL);
 
-    s = str;
-    ch = *s++;
+    /*
+     * Find the handle that this packet is associated with.  We
+     * need to peek at the packet to see what is in it, but we
+     * want to save the actual reading for later.
+     */
+    dgram_zero(&netfd);
+    if (dgram_recv(&netfd, 0, &peer) < 0)
+       return;
+    if (str2pkthdr(netfd.cur, &pkt, handle, sizeof(handle), &sequence) < 0)
+       return;
 
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       *errstr = newstralloc(*errstr, "[bad krb4 security line]");
-       return 0;
-    }
-#define sc "TICKET"
-    if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
-       *errstr = newstralloc(*errstr, "[bad krb4 security line]");
-       return 0;
+    for (kh = handleq_first(); kh != NULL; kh = handleq_next(kh)) {
+       if (strcmp(kh->proto_handle, handle) == 0 &&
+           memcmp(&kh->peer.sin_addr, &peer.sin_addr,
+           sizeof(peer.sin_addr)) == 0 &&
+           kh->peer.sin_port == peer.sin_port) {
+           kh->sequence = sequence;
+
+           /*
+            * We need to cancel the recvpkt request before calling
+            * the callback because the callback may reschedule us.
+            */
+           fn = kh->fn;
+           arg = kh->arg;
+           krb4_recvpkt_cancel(kh);
+           if (recv_security_ok(kh, &pkt) < 0)
+               (*fn)(arg, NULL, S_ERROR);
+           else
+               (*fn)(arg, &pkt, S_OK);
+           return;
+       }
     }
-    s += sizeof(sc)-1;
-    ch = s[-1];
-#undef sc
-    skip_whitespace(s, ch);
-    ticket_str = s - 1;
-    skip_line(s, ch);
-    s[-1] = '\0';
+    /*
+     * If we didn't find a handle, then check for a new incoming packet.
+     * If no accept handler was setup, then just return.
+     */
+    if (accept_fn == NULL)
+       return;
 
-    /* convert to binary ticket */
+    he = gethostbyaddr((void *)&peer.sin_addr, sizeof(peer.sin_addr), AF_INET);
+    if (he == NULL)
+       return;
+    kh = alloc(sizeof(*kh));
+    security_handleinit(&kh->sech, &krb4_security_driver);
+    inithandle(kh, he, peer.sin_port, handle);
 
-    astr2bin(ticket_str, (unsigned char *)ticket.dat, &ticket.length);
+    /*
+     * Check the security of the packet.  If it is bad, then pass NULL
+     * to the accept function instead of a packet.
+     */
+    if (recv_security_ok(kh, &pkt) < 0)
+       (*accept_fn)(&kh->sech, NULL);
+    else
+       (*accept_fn)(&kh->sech, &pkt);
+}
 
-    /* consult kerberos server */
+/*
+ * This is called when a handle times out before receiving a packet.
+ */
+static void
+recvpkt_timeout(cookie)
+    void *cookie;
+{
+    struct krb4_handle *kh = cookie;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    void *arg;
 
-#if CLIENT_HOST_INSTANCE == HOSTNAME_INSTANCE
-    if (gethostname(hname, sizeof(hname)) < 0) {
-       *errstr = newvstralloc(*errstr,
-           "[kerberos error: can't get hostname: ", strerror(errno), "}",
-           NULL);
-       return 0;
-    }
-#undef HOSTNAME_INSTANCE
-#define HOSTNAME_INSTANCE krb_get_phost(hname)
-#endif
+    assert(kh != NULL);
 
+    assert(kh->ev_timeout != NULL);
+    fn = kh->fn;
+    arg = kh->arg;
+    krb4_recvpkt_cancel(kh);
+    (*fn)(arg, NULL, S_TIMEOUT);
+}
+
+/*
+ * Add a ticket to the message
+ */
+static int
+add_ticket(kh, pkt, msg)
+    struct krb4_handle *kh;
+    const pkt_t *pkt;
+    dgram_t *msg;
+{
+    char inst[INST_SZ];
+    KTEXT_ST ticket;
+    char *security;
+    int rc;
+
+    kh->cksum = krb4_cksum(pkt->body);
+#if CLIENT_HOST_INSTANCE == HOSTNAME_INSTANCE
     /*
-     * the instance must be in writable memory of size INST_SZ
-     * krb_rd_req might change it.
+     * User requested that all instances be based on the target
+     * hostname.
+     */
+    strncpy(inst, kh->inst, sizeof(inst) - 1);
+#else
+    /*
+     * User requested a fixed instance.
      */
     strncpy(inst, CLIENT_HOST_INSTANCE, sizeof(inst) - 1);
+#endif
     inst[sizeof(inst) - 1] = '\0';
-    rc = krb_rd_req(&ticket, CLIENT_HOST_PRINCIPLE, inst,
-                   addr->sin_addr.s_addr, &auth, CLIENT_HOST_KEY_FILE);
-    if(rc) {
-       *errstr = newvstralloc(*errstr,
-                              "[kerberos error: ", krb_err_txt[rc], "]",
-                              NULL);
-       return 0;
+
+    /*
+     * Get a ticket with the user-defined service and instance,
+     * and using the checksum of the body of the request packet.
+     */
+    rc = krb_mk_req(&ticket, CLIENT_HOST_PRINCIPLE, inst, kh->realm,
+       kh->cksum);
+    if (rc == NO_TKT_FIL) {
+       /* It's been kdestroyed.  Get a new one and try again */
+       get_tgt();
+       rc = krb_mk_req(&ticket, CLIENT_HOST_PRINCIPLE, inst, kh->realm,
+           kh->cksum);
+    }
+    if (rc != 0) {
+       security_seterror(&kh->sech,
+           "krb_mk_req failed: %s (%d)", error_message(rc), rc);
+       return (-1);
     }
+    /*
+     * We now have the ticket.  Put it into the packet, and send
+     * it.
+     */
+    security = vstralloc("SECURITY TICKET ",
+       bin2astr(ticket.dat, ticket.length), "\n", NULL);
+    dgram_cat(msg, security);
+    amfree(security);
 
-    /* verify checksum */
+    return (0);
+}
 
-    dbprintf(("msg checksum %d auth checksum %d\n", 
-             cksum, auth.checksum));
+/*
+ * Add the mutual authenticator.  This is the checksum from
+ * the req, + 1
+ */
+static void
+add_mutual_auth(kh, msg)
+    struct krb4_handle *kh;
+    dgram_t *msg;
+{
+    union mutual mutual;
+    char *security;
+
+    assert(kh != NULL);
+    assert(msg != NULL);
+    assert(kh->cksum != 0);
+    assert(kh->session_key[0] != '\0');
+
+    memset(&mutual, 0, sizeof(mutual));
+    mutual.cksum = htonl(kh->cksum + 1);
+    encrypt_data(&mutual, sizeof(mutual), &kh->session_key);
+
+    security = vstralloc("SECURITY MUTUAL-AUTH ",
+       bin2astr(mutual.pad, sizeof(mutual.pad)), "\n", NULL);
+    dgram_cat(msg, security);
+    amfree(security);
+}
+
+/*
+ * Check the security of a received packet.  Returns negative on error
+ * or security violation and otherwise returns 0 and fills in the
+ * passed packet.
+ */
+static int
+recv_security_ok(kh, pkt)
+    struct krb4_handle *kh;
+    pkt_t *pkt;
+{
+    char *tok, *security, *body;
+    unsigned long cksum;
 
-    if(cksum != auth.checksum) {
-       *errstr = newstralloc(*errstr, "[kerberos error: checksum mismatch]");
-       dbprintf(("checksum error: exp %d got %d\n", 
-                 auth.checksum, cksum));
-       return 0;
+    assert(kh != NULL);
+    assert(pkt != NULL);
+
+    /*
+     * Set this preemptively before we mangle the body.
+     */
+    security_seterror(&kh->sech,
+       "bad %s SECURITY line from %s: '%s'", pkt_type2str(pkt->type),
+       kh->hostname, pkt->body);
+
+
+    /*
+     * The first part of the body should be the security info.  Deal with it.
+     * We only need to do this on a few packet types.
+     *
+     * First, parse the SECURITY line in the packet, if it exists.
+     * Increment the cur pointer past it to the data section after
+     * parsing is finished.
+     */
+    if (strncmp(pkt->body, "SECURITY", sizeof("SECURITY") - 1) == 0) {
+       tok = strtok(pkt->body, " ");
+       assert(strcmp(tok, "SECURITY") == 0);
+       /* security info goes until the newline */
+       security = strtok(NULL, "\n");
+       body = strtok(NULL, "");
+       /*
+        * If the body is f-ked, then try to recover.
+        */
+       if (body == NULL) {
+           if (security != NULL)
+               body = security + strlen(security) + 2;
+           else
+               body = pkt->body;
+       }
+    } else {
+       security = NULL;
+       body = pkt->body;
     }
 
-    /* save key/cksum for mutual auth and dump encryption */
+    /*
+     * Get a checksum of the non-security parts of the body 
+     */
+    cksum = krb4_cksum(body);
 
-    memcpy(session_key, auth.session, sizeof(session_key));
-    auth_cksum = auth.checksum;
+    /*
+     * Now deal with the data we did (or didn't) parse above
+     */
+    switch (pkt->type) {
+    case P_REQ:
+       /*
+        * Request packets have a ticket after the security tag
+        * Get the ticket, make sure the checksum agrees with the
+        * checksum of the request we sent.
+        *
+        * Must look like: SECURITY TICKET [ticket str]
+        */
+
+       /* there must be some security info */
+       if (security == NULL)
+           return (-1);
+
+       /* second word must be TICKET */
+       if ((tok = strtok(security, " ")) == NULL)
+           return (-1);
+       if (strcmp(tok, "TICKET") != 0) {
+           security_seterror(&kh->sech,
+               "REQ SECURITY line parse error, expecting TICKET, got %s", tok);
+           return (-1);
+       }
 
-    /* lookup our local user name */
+       /* the third word is the encoded ticket */
+       if ((tok = strtok(NULL, "")) == NULL)
+           return (-1);
+       if (check_ticket(kh, pkt, tok, cksum) < 0)
+           return (-1);
+
+       /* we're good to go */
+       break;
+
+    case P_REP:
+       /*
+        * Reply packets check the mutual authenticator for this host.
+        *
+        * Must look like: SECURITY MUTUAL-AUTH [mutual auth str]
+        */
+       if (security == NULL)
+           return (-1);
+       if ((tok = strtok(security, " ")) == NULL)
+           return (-1);
+       if (strcmp(tok, "MUTUAL-AUTH") != 0)  {
+           security_seterror(&kh->sech,
+               "REP SECURITY line parse error, expecting MUTUAL-AUTH, got %s",
+               tok);
+           return (-1);
+       }
+       if ((tok = strtok(NULL, "")) == NULL)
+           return (-1);
+       if (check_mutual_auth(kh, tok) < 0)
+           return (-1);
+
+    case P_ACK:
+    case P_NAK:
+    default:
+       /*
+        * These packets have no security.  They should, but such
+        * is life.  We can't change it without breaking compatibility.
+        *
+        * XXX Should we complain if argc > 0? (ie, some security info was
+        * sent?)
+        */
+       break;
+
+    }
 
-#ifdef FORCE_USERID
     /*
-     * if FORCE_USERID is set, then we want to check the uid that we're
-     * forcing ourselves to.  Since we'll need root access to grab at the
-     * srvtab file, we're actually root, although we'll be changing into
-     * CLIENT_LOGIN once we're done the kerberos authentication.
+     * If there is security info at the front of the packet, we need
+     * to shift the rest of the data up and nuke it.
      */
-    if((pwptr = getpwnam(CLIENT_LOGIN)) == NULL)
-        error("error [getpwnam(%s) fails]", CLIENT_LOGIN);
+    if (body != pkt->body)
+       memmove(pkt->body, body, strlen(body) + 1);
+    return (0);
+}
+
+/*
+ * Check the ticket in a REQ packet for authenticity
+ */
+static int
+check_ticket(kh, pkt, ticket_str, cksum)
+    struct krb4_handle *kh;
+    const pkt_t *pkt;
+    const char *ticket_str;
+    unsigned long cksum;
+{
+    char inst[INST_SZ];
+    KTEXT_ST ticket;
+    AUTH_DAT auth;
+    struct passwd *pwd;
+    char *user;
+    int rc;
+
+    assert(kh != NULL);
+    assert(pkt != NULL);
+    assert(ticket_str != NULL);
+
+    ticket.length = sizeof(ticket.dat);
+    astr2bin(ticket_str, ticket.dat, &ticket.length);
+    assert(ticket.length > 0);
+
+    /* get a copy of the instance into writable memory */
+#if CLIENT_HOST_INSTANCE == HOSTNAME_INSTANCE
+    strncpy(inst, krb_get_phost(hostname), sizeof(inst) - 1);
 #else
-    myuid = getuid();
-    if((pwptr = getpwuid(myuid)) == NULL)
-        error("error [getpwuid(%d) fails]", myuid);
+    strncpy(inst, CLIENT_HOST_INSTANCE, sizeof(inst) - 1);
 #endif
+    inst[sizeof(inst) - 1] = '\0';
 
-    /* check the .klogin file */
+    /* get the checksum out of the ticket */
+    rc = krb_rd_req(&ticket, CLIENT_HOST_PRINCIPLE, inst,
+       kh->peer.sin_addr.s_addr, &auth, CLIENT_HOST_KEY_FILE);
+    if (rc != 0) {
+       security_seterror(&kh->sech,
+           "krb_rd_req failed for %s: %s (%d)", kh->hostname,
+           error_message(rc), rc);
+       return (-1);
+    }
+
+    /* verify and save the checksum and session key */
+    if (auth.checksum != cksum) {
+       security_seterror(&kh->sech,
+           "krb4 checksum mismatch for %s (remote=%lu, local=%lu)",
+           kh->hostname, (long)auth.checksum, cksum);
+       return (-1);
+    }
+    kh->cksum = cksum;
+    memcpy(kh->session_key, auth.session, sizeof(kh->session_key));
 
     /*
-     * some implementations of kerberos will call one of the getpw()
-     * routines (getpwuid(), I think), which overwrites the value of 
-     * pwptr->pw_name if the user you want to check disagrees with
-     * who has the current uid.  (as in the case when we're still running
-     * as root, and we have FORCE_USERID set).
+     * If FORCE_USERID is set, then we need to specifically
+     * check the userid we're forcing ourself to.  Otherwise,
+     * just check the login we're currently setuid to.
      */
-    user = stralloc(pwptr->pw_name);
+#ifdef FORCE_USERID
+    if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL)
+       error("error [getpwnam(%s) fails]", CLIENT_LOGIN);
+#else
+    if ((pwd = getpwuid(getuid())) == NULL)
+       error("error  [getpwuid(%d) fails]", getuid());
+#endif
+
+    /* save the username in case it's overwritten */
+    user = stralloc(pwd->pw_name);
 
-    if(kuserok(&auth, user)) {
-       *errstr = newvstralloc(*errstr,
-                              "[",
-                              "access as ", user, " not allowed from ",
-                              auth.pname, ".", auth.pinst, "@", auth.prealm,
-                              "]", NULL);
-       dbprintf(("kuserok check failed: %s\n", *errstr));
+    /* check the klogin file */
+    if (kuserok(&auth, user)) {
+       security_seterror(&kh->sech,
+           "access as %s not allowed from %s.%s@%s", user, auth.pname,
+           auth.pinst, auth.prealm);
        amfree(user);
-       return 0;
+       return (-1);
     }
     amfree(user);
 
-    dbprintf(("krb4 security check passed\n"));
-    return 1;
+    /* it's good */
+    return (0);
+}
+
+/*
+ * Verify that the packet received is secure by verifying that it has
+ * the same checksum as our request + 1.
+ */
+static int
+check_mutual_auth(kh, mutual_auth_str)
+    struct krb4_handle *kh;
+    const char *mutual_auth_str;
+{
+    union mutual mutual;
+    int len;
+
+    assert(kh != NULL);
+    assert(mutual_auth_str != NULL);
+    assert(kh->inst[0] != '\0');
+    /* we had better have a checksum from a request we sent */
+    assert(kh->cksum != 0);
+
+    /* convert the encoded string into binary data */
+    len = sizeof(mutual);
+    astr2bin(mutual_auth_str, (unsigned char *)&mutual, &len);
+
+    /* unencrypt the string using the key in the ticket file */
+    host2key(kh->hostname, kh->inst, &kh->session_key);
+    decrypt_data(&mutual, len, &kh->session_key);
+    mutual.cksum = ntohl(mutual.cksum);
+
+    /* the data must be the same as our request cksum + 1 */
+    if (mutual.cksum != kh->cksum + 1) {
+       security_seterror(&kh->sech,
+           "krb4 checksum mismatch from %s (remote=%lu, local=%lu)",
+           kh->hostname, mutual.cksum, kh->cksum + 1);
+       return (-1);
+    }
+
+    return (0);
 }
 
-/* ---------------- */
+/*
+ * Convert a pkt_t into a header string for our packet
+ */
+static const char *
+pkthdr2str(kh, pkt)
+    const struct krb4_handle *kh;
+    const pkt_t *pkt;
+{
+    static char retbuf[256];
+
+    assert(kh != NULL);
+    assert(pkt != NULL);
 
-/* XXX - I'm getting astrs with the high bit set in the debug output!?? */
+    snprintf(retbuf, sizeof(retbuf), "Amanda %d.%d %s HANDLE %s SEQ %d\n",
+       VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
+       kh->proto_handle, kh->sequence);
 
-#define hex_digit(d)   ("0123456789ABCDEF"[(d)])
-#define unhex_digit(h) (((h) - '0') > 9? ((h) - 'A' + 10) : ((h) - '0'))
+    /* check for truncation.  If only we had asprintf()... */
+    assert(retbuf[strlen(retbuf) - 1] == '\n');
 
-char *bin2astr(buf, len)
-unsigned char *buf;
-int len;
+    return (retbuf);
+}
+
+/*
+ * Parses out the header line in 'str' into the pkt and handle
+ * Returns negative on parse error.
+ */
+static int
+str2pkthdr(origstr, pkt, handle, handlesize, sequence)
+    const char *origstr;
+    pkt_t *pkt;
+    char *handle;
+    size_t handlesize;
+    int *sequence;
 {
-    char *str, *q;
-    unsigned char *p;
-    int slen, i, needs_quote;
+    char *str;
+    const char *tok;
 
-    /* first pass, calculate string len */
+    assert(origstr != NULL);
+    assert(pkt != NULL);
 
-    slen = needs_quote = 0; p = buf;
-    if(*p == '"') needs_quote = 1;     /* special case */
-    for(i=0;i<len;i++) {
-       if(!isgraph(*p)) needs_quote = 1;
-       if(isprint(*p) && *p != '$' && *p != '"')
-           slen += 1;
-       else
-           slen += 3;
-       p++;
-    }
-    if(needs_quote) slen += 2;
+    str = stralloc(origstr);
+
+    /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
+
+    /* Read in "Amanda" */
+    if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
+       goto parse_error;
+
+    /* nothing is done with the major/minor numbers currently */
+    if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
+       goto parse_error;
+
+    /* Read in the packet type */
+    if ((tok = strtok(NULL, " ")) == NULL)
+       goto parse_error;
+    pkt_init(pkt, pkt_str2type(tok), "");
+    if (pkt->type == (pktype_t)-1)
+       goto parse_error;
 
-    /* 2nd pass, allocate string and fill it in */
+    /* Read in "HANDLE" */
+    if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
+       goto parse_error;
 
-    str = (char *)alloc(slen+1);
+    /* parse the handle */
+    if ((tok = strtok(NULL, " ")) == NULL)
+       goto parse_error;
+    strncpy(handle, tok, handlesize - 1);
+    handle[handlesize - 1] = '\0';
+
+    /* Read in "SEQ" */
+    if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)
+       goto parse_error;
+
+    /* parse the sequence number */
+    if ((tok = strtok(NULL, "\n")) == NULL)
+       goto parse_error;
+    *sequence = atoi(tok);
+
+    /* Save the body, if any */
+    if ((tok = strtok(NULL, "")) != NULL)
+       pkt_cat(pkt, tok);
+
+    amfree(str);
+    return (0);
+
+parse_error:
+#if 0 /* XXX we have no way of passing this back up */
+    security_seterror(&kh->sech,
+       "parse error in packet header : '%s'", origstr);
+#endif
+    amfree(str);
+    return (-1);
+}
+
+static void
+host2key(hostname, inst, key)
+    const char *hostname, *inst;
+    des_cblock *key;
+{
+    char realm[256];
+    CREDENTIALS cred;
+
+    strncpy(realm, krb_realmofhost((char *)hostname), sizeof(realm) - 1);
+    realm[sizeof(realm) - 1] = '\0';
+#if CLIENT_HOST_INSTANCE != HOSTNAME_INSTANCE
+    inst = CLIENT_HOST_INSTANCE
+#endif
+    krb_get_cred(CLIENT_HOST_PRINCIPLE, (char *)inst, realm, &cred);
+    memcpy(key, cred.session, sizeof(des_cblock));
+}
+
+
+/*
+ * Convert a chunk of data into a string.
+ */
+static const char *
+bin2astr(buf, len)
+    const unsigned char *buf;
+    int len;
+{
+    static const char tohex[] = "0123456789ABCDEF";
+    static char *str = NULL;
+    char *q;
+    const unsigned char *p;
+    int slen, i;
+
+    /*
+     * calculate output string len
+     * We quote everything, so each input byte == 3 output chars, plus
+     * two more for quotes
+     */
+    slen = (len * 3) + 2;
+
+    /* allocate string and fill it in */
+    if (str != NULL)
+       amfree(str);
+    str = alloc(slen + 1);
     p = buf;
     q = str;
-    if(needs_quote) *q++ = '"';
-    for(i=0;i<len;i++) {
-       if(isprint(*p) && *p != '$' && *p != '"')
-           *q++ = *p++;
-       else {
-           *q++ = '$';
-           *q++ = hex_digit((*p >> 4) & 0xF);
-           *q++ = hex_digit(*p & 0xF);
-           p++;
-       }
+    *q++ = '"';
+    for (i = 0; i < len; i++) {
+       *q++ = '$';
+       *q++ = tohex[(*p >> 4) & 0xF];
+       *q++ = tohex[*p & 0xF];
+       p++;
     }
-    if(needs_quote) *q++ = '"';
+    *q++ = '"';
     *q = '\0';
-    if(q-str != slen)
-       printf("bin2str: hmmm.... calculated %d got %d\n",
-              slen, q-str);
-    return str;
+
+    /* make sure we didn't overrun our allocated buffer */
+    assert(q - str == slen);
+
+    return (str);
 }
 
-void astr2bin(astr, buf, lenp)
-char *astr;
-unsigned char *buf;
-int  *lenp;
+/*
+ * Convert an encoded string into a block of data bytes
+ */
+static void
+astr2bin(astr, buf, lenp)
+    const char *astr;
+    unsigned char *buf;
+    int *lenp;
 {
-    char *p;
+    const char *p;
     unsigned char *q;
+#define fromhex(h)     (isdigit((int)h) ? (h) - '0' : (h) - 'A' + 10)
 
-    p = astr; q = buf;
+    /*
+     * Skip leading quote, if any
+     */
+    if (*astr == '"')
+       astr++;
 
-    if(*p != '"') {
-       /* strcpy, but without the null */
-       while(*p) *q++ = *p++;
-       *lenp = q-buf;
-       return;
+    /*
+     * Run through the string.  Anything starting with a $ is a three
+     * char representation of this byte.  Everything else is literal.
+     */
+    for (p = astr, q = buf; *p != '"' && *p != '\0'; ) {
+       if (*p != '$') {
+           *q++ = *p++;
+       } else {
+           *q++ = (fromhex(p[1]) << 4) + fromhex(p[2]);
+            p += 3;
+       }
+       if (q - buf >= *lenp)
+           break;
     }
+    *lenp = q - buf;
+}
 
-    p++;
-    while(*p != '"') {
-       if(*p != '$')
-           *q++ = *p++;
-       else {
-           *q++ = (unhex_digit(p[1]) << 4) + unhex_digit(p[2]);
-            p  += 3;
+static unsigned long
+krb4_cksum(str)
+    const char *str;
+{
+    des_cblock seed;
+
+    memset(seed, 0, sizeof(seed));
+    /*
+     * The first arg is an unsigned char * in some krb4 implementations,
+     * and in others, it's a des_cblock *.  Just make it void here
+     * to shut them all up.
+     */
+    return (quad_cksum((void *)str, NULL, strlen(str), 1, &seed));
+}
+
+static void
+krb4_getinst(hname, inst, size)
+    const char *hname;
+    char *inst;
+    size_t size;
+{
+
+    /*
+     * Copy the first part of the hostname up to the first '.' into
+     * the buffer provided.  Leave room for a NULL.
+     */
+    while (size > 1 && *hname != '\0' && *hname != '.') {
+       *inst++ = isupper((int)*hname) ? tolower((int)*hname) : *hname;
+       hname++;
+       size--;
+    }
+    *inst = '\0';
+}
+
+static void
+encrypt_data(data, length, key)
+    void *data;
+    int length;
+    des_cblock *key;
+{
+    des_key_schedule sched;
+
+    /*
+     * First arg is des_cblock * in some places, and just des_cblock in
+     * others.  Since des_cblock is a char array, they are equivalent.
+     * Just cast it to void * to keep both compilers quiet.  typedefing
+     * arrays should be outlawed.
+     */
+    des_key_sched((void *)key, sched);
+    des_pcbc_encrypt(data, data, length, sched, key, DES_ENCRYPT);
+}
+
+
+static void
+decrypt_data(data, length, key)
+    void *data;
+    int length;
+    des_cblock *key;
+{
+    des_key_schedule sched;
+
+    des_key_sched((void *)key, sched);
+    des_pcbc_encrypt(data, data, length, sched, key, DES_DECRYPT);
+}
+
+/*
+ * like write(), but always writes out the entire buffer.
+ */
+static int
+net_write(fd, vbuf, size)
+    int fd;
+    const void *vbuf;
+    size_t size;
+{
+    const char *buf = vbuf;    /* so we can do ptr arith */
+    int n;
+
+    while (size > 0) {
+       n = write(fd, buf, size);
+       if (n < 0)
+           return (-1);
+       buf += n;
+       size -= n;
+    }
+    return (0);
+}
+
+/*
+ * Like read(), but waits until the entire buffer has been filled.
+ */
+static int
+net_read(fd, vbuf, size, timeout)
+    int fd;
+    void *vbuf;
+    size_t size;
+    int timeout;
+{
+    char *buf = vbuf;  /* ptr arith */
+    int n, neof = 0;
+    fd_set readfds;
+    struct timeval tv;
+
+    while (size > 0) {
+       FD_ZERO(&readfds);
+       FD_SET(fd, &readfds);
+       tv.tv_sec = timeout;
+       tv.tv_usec = 0;
+       switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {
+       case 0:
+           errno = ETIMEDOUT;
+           /* FALLTHROUGH */
+       case -1:
+           return (-1);
+       case 1:
+           assert(FD_ISSET(fd, &readfds));
+           break;
+       default:
+           assert(0);
+           break;
+       }
+       n = read(fd, buf, size);
+       if (n < 0)
+           return (-1);
+       /* we only tolerate so many eof's */
+       if (n == 0 && ++neof > 1024) {
+           errno = EIO;
+           return (-1);
        }
+       buf += n;
+       size -= n;
     }
-    if(p-astr+1 != strlen(astr))
-       printf("astr2bin: hmmm... short inp exp %d got %d\n",
-              strlen(astr), p-astr+1);
-    *lenp = q-buf;
+    return (0);
 }
 
+#if 0
 /* -------------------------- */
 /* debug routines */
 
-void
+static void
 print_hex(str,buf,len)
-char *str;
-unsigned char *buf;
+const char *str;
+const unsigned char *buf;
 int len;
 {
     int i;
 
-    printf("%s:", str);
+    dbprintf(("%s:", str));
     for(i=0;i<len;i++) {
-       if(i%25 == 0) putchar('\n');
-       printf(" %02X", buf[i]);
+       if(i%25 == 0) dbprintf(("\n"));
+       dbprintf((" %02X", buf[i]));
     }
-    putchar('\n');
+    dbprintf(("\n"));
 }
 
-void
+static void
 print_ticket(str, tktp)
-char *str;
+const char *str;
 KTEXT tktp;
 {
-    int i;
-    printf("%s: length %d chk %lX\n", str, tktp->length, tktp->mbz);
+    dbprintf(("%s: length %d chk %lX\n", str, tktp->length, tktp->mbz));
     print_hex("ticket data", tktp->dat, tktp->length);
     fflush(stdout);
 }
 
-void
+static void
 print_auth(authp)
 AUTH_DAT *authp;
 {
     printf("\nAuth Data:\n");
     printf("  Principal \"%s\" Instance \"%s\" Realm \"%s\"\n",
           authp->pname, authp->pinst, authp->prealm);
-    printf("  cksum %d life %d keylen %d\n", authp->checksum,
+    printf("  cksum %d life %d keylen %ld\n", authp->checksum,
           authp->life, sizeof(authp->session));
     print_hex("session key", authp->session, sizeof(authp->session));
     fflush(stdout);
 }
 
-void
+static void
 print_credentials(credp)
 CREDENTIALS *credp;
 {
@@ -657,3 +1727,8 @@ CREDENTIALS *credp;
     print_hex("ticket", credp->ticket_st.dat, credp->ticket_st.length);
     fflush(stdout);
 }
+#endif
+
+#else
+void krb4_security_dummy (void) {}
+#endif /* KRB4_SECURITY */
diff --git a/common-src/krb4-security.h b/common-src/krb4-security.h
deleted file mode 100644 (file)
index d56cb6b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1993 University of Maryland
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
- */
-/*
- * krb4-security.h - definitions for kerberos helper module
- */
-#ifndef KRB4_SECURITY_H
-#define KRB4_SECURITY_H
-
-#include "amanda.h"
-#include "protocol.h"
-
-/* KerberosIV function prototypes (which should be in krb.h) */
-#ifdef KERBEROSIV_MISSING_PROTOTYPES /* XXX autoconf */
-char *krb_get_phost P((char *hostname));
-#endif
-
-/* Amanda krb4 function prototypes */
-void kerberos_service_init P((void));
-uint32_t kerberos_cksum P((char *str));
-struct hostent *host2krbname P((char *alias, char *inst, char *realm));
-char *bin2astr P((unsigned char *buf, int len));
-void astr2bin P((char *astr, unsigned char *buf, int  *lenp));
-void encrypt_data P((void *data, int length, des_cblock key));
-void decrypt_data P((void *data, int length, des_cblock key));
-int kerberos_handshake P((int fd, des_cblock key));
-des_cblock *host2key P((char *hostp));
-int check_mutual_authenticator P((des_cblock *key, pkt_t *pkt, proto_t *p));
-extern char *get_krb_security P((char *str,
-                                char *host_inst, char *realm,
-                                uint32_t *cksum));
-
-extern int krb4_auth;
-extern int kencrypt;
-extern des_cblock session_key;
-extern uint32_t auth_cksum;
-
-#endif
diff --git a/common-src/krb5-security.c b/common-src/krb5-security.c
new file mode 100644 (file)
index 0000000..e1e78a0
--- /dev/null
@@ -0,0 +1,2233 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+
+/*
+ * $Id: krb5-security.c,v 1.12 2006/02/21 04:13:55 ktill Exp $
+ *
+ * krb5-security.c - kerberos V5 security module
+ */
+
+#include "config.h"
+#ifdef KRB5_SECURITY
+#include "amanda.h"
+#include "arglist.h"
+#include "event.h"
+#include "packet.h"
+#include "queue.h"
+#include "security.h"
+#include "stream.h"
+#include "version.h"
+
+#define        BROKEN_MEMORY_CCACHE
+
+#ifdef BROKEN_MEMORY_CCACHE
+/*
+ * If you don't have atexit() or on_exit(), you could just consider
+ * making atexit() empty and clean up your ticket files some other
+ * way
+ */
+#ifndef HAVE_ATEXIT
+#ifdef HAVE_ON_EXIT
+#define atexit(func)    on_exit(func, 0)
+#else
+#define atexit(func)    (you must to resolve lack of atexit)
+#endif  /* HAVE_ON_EXIT */
+#endif  /* ! HAVE_ATEXIT */
+#endif
+
+#ifndef KRB5_HEIMDAL_INCLUDES
+#include <gssapi/gssapi_generic.h>
+#else
+#include <gssapi/gssapi.h>
+#endif
+#include <krb5.h>
+
+#ifndef KRB5_ENV_CCNAME
+#define        KRB5_ENV_CCNAME "KRB5CCNAME"
+#endif
+
+/*#define      KRB5_DEBUG*/
+
+#ifdef KRB5_DEBUG
+#define        k5printf(x)     dbprintf(x)
+#else
+#define        k5printf(x)
+#endif
+
+/*
+ * consider undefining when kdestroy() is fixed.  The current version does
+ * not work under krb5-1.2.4 in rh7.3, perhaps others.
+ */
+#define KDESTROY_VIA_UNLINK    1
+
+/*
+ * Define this if you want all network traffic encrypted.  This will
+ * extract a serious performance hit.
+ *
+ * It would be nice if we could do this on a filesystem-by-filesystem basis.
+ */
+/*#define      AMANDA_KRB5_ENCRYPT*/
+
+/*
+ * Where the keytab lives, if defined.  Otherwise it expects something in the
+ * config file.
+ */
+/* #define AMANDA_KEYTAB       "/.amanda-v5-keytab" */
+
+/*
+ * The name of the principal we authenticate with, if defined.  Otherwise
+ * it expects something in the config file.
+ */
+/* #define     AMANDA_PRINCIPAL        "service/amanda" */
+
+/*
+ * The lifetime of our tickets in seconds.  This may or may not need to be
+ * configurable.
+ */
+#define        AMANDA_TKT_LIFETIME     (12*60*60)
+
+/*
+ * The name of the service in /etc/services.  This probably shouldn't be
+ * configurable.
+ */
+#define        AMANDA_KRB5_SERVICE_NAME        "k5amanda"
+
+/*
+ * The default port to use if above entry in /etc/services doesn't exist
+ */
+#define        AMANDA_KRB5_DEFAULT_PORT        10082
+
+/*
+ * The timeout in seconds for each step of the GSS negotiation phase
+ */
+#define        GSS_TIMEOUT                     30
+
+/*
+ * The largest buffer we can send/receive.
+ */
+#define        AMANDA_MAX_TOK_SIZE             (MAX_TAPE_BLOCK_BYTES * 4)
+
+/*
+ * Magic values for krb5_conn->handle
+ */
+#define        H_EOF   -1              /* this connection has been shut down */
+
+/*
+ * This is the tcp stream buffer size
+ */
+#define        KRB5_STREAM_BUFSIZE     (MAX_TAPE_BLOCK_BYTES * 2)
+
+/*
+ * This is the max number of outgoing connections we can have at once.
+ * planner/amcheck/etc will open a bunch of connections as it tries
+ * to contact everything.  We need to limit this to avoid blowing
+ * the max number of open file descriptors a process can have.
+ */
+#define        AMANDA_KRB5_MAXCONN     40
+
+/*
+ * This is a frame read off of the connection.  Each frame has an
+ * associated handle and a gss_buffer which contains a len,value pair.
+ */
+struct krb5_frame {
+    int handle;                                /* proto handle */
+    gss_buffer_desc tok;               /* token */
+    TAILQ_ENTRY(krb5_frame) tq;                /* queue handle */
+};
+
+/*
+ * This is a krb5 connection to a host.  We should only have
+ * one connection per host.
+ */
+struct krb5_conn {
+    int fd;                                    /* tcp connection */
+    struct {                                   /* buffer read() calls */
+       char buf[KRB5_STREAM_BUFSIZE];          /* buffer */
+       size_t left;                    /* unread data */
+       ssize_t size;                   /* size of last read */
+    } readbuf;
+    enum { unauthed, authed } state;
+    event_handle_t *ev_read;                   /* read (EV_READFD) handle */
+    int ev_read_refcnt;                                /* number of readers */
+    char hostname[MAX_HOSTNAME_LENGTH+1];      /* human form of above */
+    char *errmsg;                              /* error passed up */
+    gss_ctx_id_t gss_context;                  /* GSSAPI context */
+    int refcnt;                                        /* number of handles using */
+    TAILQ_HEAD(, krb5_frame) frameq;           /* queue of read frames */
+    TAILQ_ENTRY(krb5_conn) tq;                 /* queue handle */
+};
+
+
+struct krb5_stream;
+
+/*
+ * This is the private handle data.
+ */
+struct krb5_handle {
+    security_handle_t sech;            /* MUST be first */
+    char *hostname;                    /* ptr to kc->hostname */
+    struct krb5_stream *ks;            /* virtual stream we xmit over */
+
+    union {
+       void (*recvpkt) P((void *, pkt_t *, security_status_t));
+                                       /* func to call when packet recvd */
+       void (*connect) P((void *, security_handle_t *, security_status_t));
+                                       /* func to call when connected */
+    } fn;
+    void *arg;                         /* argument to pass function */
+    event_handle_t *ev_wait;           /* wait handle for connects */
+    char *(*conf_fn) P((char *, void *)); /* used to get config info */
+    event_handle_t *ev_timeout;                /* timeout handle for recv */
+};
+
+/*
+ * This is the internal security_stream data for krb5.
+ */
+struct krb5_stream {
+    security_stream_t secstr;          /* MUST be first */
+    struct krb5_conn *kc;              /* physical connection */
+    int handle;                                /* protocol handle */
+    event_handle_t *ev_read;           /* read (EV_WAIT) event handle */
+    void (*fn) P((void *, void *, int));       /* read event fn */
+    void *arg;                         /* arg for previous */
+};
+
+/*
+ * Interface functions
+ */
+static int krb5_sendpkt P((void *, pkt_t *));
+static int krb5_stream_accept P((void *));
+static int krb5_stream_auth P((void *));
+static int krb5_stream_id P((void *));
+static int krb5_stream_write P((void *, const void *, size_t));
+static void *krb5_stream_client P((void *, int));
+static void *krb5_stream_server P((void *));
+static void krb5_accept P((int, int,
+    void (*)(security_handle_t *, pkt_t *)));
+static void krb5_close P((void *));
+static void krb5_connect P((const char *,
+    char *(*)(char *, void *),
+    void (*)(void *, security_handle_t *, security_status_t), void *));
+static void krb5_recvpkt P((void *,
+    void (*)(void *, pkt_t *, security_status_t), void *, int));
+static void krb5_recvpkt_cancel P((void *));
+static void krb5_stream_close P((void *));
+static void krb5_stream_read P((void *, void (*)(void *, void *, int),
+    void *));
+static void krb5_stream_read_cancel P((void *));
+
+/*
+ * This is our interface to the outside world.
+ */
+const security_driver_t krb5_security_driver = {
+    "krb5",
+    krb5_connect,
+    krb5_accept,
+    krb5_close,
+    krb5_sendpkt,
+    krb5_recvpkt,
+    krb5_recvpkt_cancel,
+    krb5_stream_server,
+    krb5_stream_accept,
+    krb5_stream_client,
+    krb5_stream_close,
+    krb5_stream_auth,
+    krb5_stream_id,
+    krb5_stream_write,
+    krb5_stream_read,
+    krb5_stream_read_cancel,
+};
+
+/*
+ * Cache the local hostname
+ */
+static char hostname[MAX_HOSTNAME_LENGTH+1];
+
+/*
+ * This is a queue of open connections
+ */
+static struct {
+    TAILQ_HEAD(, krb5_conn) tailq;
+    int qlength;
+} connq = {
+    TAILQ_HEAD_INITIALIZER(connq.tailq), 0
+};
+#define        connq_first()           TAILQ_FIRST(&connq.tailq)
+#define        connq_next(kc)          TAILQ_NEXT(kc, tq)
+#define        connq_append(kc)        do {                                    \
+    TAILQ_INSERT_TAIL(&connq.tailq, kc, tq);                           \
+    connq.qlength++;                                                   \
+} while (0)
+#define        connq_remove(kc)        do {                                    \
+    assert(connq.qlength > 0);                                         \
+    TAILQ_REMOVE(&connq.tailq, kc, tq);                                        \
+    connq.qlength--;                                                   \
+} while (0)
+
+static int newhandle = 1;
+
+/*
+ * This is a function that should be called if a new security_handle_t is
+ * created.  If NULL, no new handles are created.
+ * It is passed the new handle and the received pkt
+ */
+static void (*accept_fn) P((security_handle_t *, pkt_t *));
+
+/*
+ * Local functions
+ */
+static void init P((void));
+#ifdef BROKEN_MEMORY_CCACHE
+static void cleanup P((void));
+#endif
+static const char *get_tgt P((char *, char *));
+static void open_callback P((void *));
+static void connect_callback P((void *));
+static void connect_timeout P((void *));
+static int send_token P((struct krb5_conn *, int, const gss_buffer_desc *));
+static int recv_token P((struct krb5_conn *, int *, gss_buffer_desc *, int));
+static void recvpkt_callback P((void *, void *, ssize_t));
+static void recvpkt_timeout P((void *));
+static void stream_read_callback P((void *));
+static int gss_server P((struct krb5_conn *));
+static int gss_client P((struct krb5_handle *));
+static const char *gss_error P((OM_uint32, OM_uint32));
+
+#ifdef AMANDA_KRB5_ENCRYPT
+static int kdecrypt P((struct krb5_stream *, gss_buffer_desc *,
+    gss_buffer_desc *));
+static int kencrypt P((struct krb5_stream *, gss_buffer_desc *,
+    gss_buffer_desc *));
+#endif
+static struct krb5_conn *conn_get P((const char *));
+static void conn_put P((struct krb5_conn *));
+static void conn_read P((struct krb5_conn *));
+static void conn_read_cancel P((struct krb5_conn *));
+static void conn_read_callback P((void *));
+static int conn_run_frameq P((struct krb5_conn *, struct krb5_stream *));
+static int net_writev P((int, struct iovec *, int));
+static ssize_t net_read P((struct krb5_conn *, void *, size_t, int));
+static int net_read_fillbuf P((struct krb5_conn *, int));
+static char *krb5_checkuser(char *, char *, char *);
+static void parse_pkt P((pkt_t *, const void *, size_t));
+
+
+/*
+ * krb5 version of a security handle allocator.  Logically sets
+ * up a network "connection".
+ */
+static void
+krb5_connect(hostname, conf_fn, fn, arg)
+    const char *hostname;
+    char *(*conf_fn) P((char *, void *));
+    void (*fn) P((void *, security_handle_t *, security_status_t));
+    void *arg;
+{
+    struct krb5_handle *kh;
+    struct hostent *he;
+    struct servent *se;
+    int port, fd;
+    const char *err;
+    char *keytab_name = NULL;
+    char *principal_name = NULL;
+
+    assert(hostname != NULL);
+
+    k5printf(("krb5_connect: %s\n", hostname));
+
+    /*
+     * Make sure we're initted
+     */
+    init();
+
+    kh = alloc(sizeof(*kh));
+    security_handleinit(&kh->sech, &krb5_security_driver);
+    kh->hostname = NULL;
+    kh->ks = NULL;
+    kh->ev_wait = NULL;
+    kh->ev_timeout = NULL;
+
+#ifdef AMANDA_KEYTAB
+    keytab_name = AMANDA_KEYTAB;
+#else
+    if(conf_fn) {
+       keytab_name = conf_fn("krb5keytab", arg);
+    }
+#endif
+#ifdef AMANDA_PRINCIPAL
+    principal_name = AMANDA_PRINCIPAL;
+#else
+    if(conf_fn) {
+       principal_name = conf_fn("krb5principal", arg);
+    }
+#endif
+
+    if ((err = get_tgt(keytab_name, principal_name)) != NULL) {
+       security_seterror(&kh->sech, "%s: could not get TGT: %s",
+           hostname, err);
+       (*fn)(arg, &kh->sech, S_ERROR);
+       return;
+    }
+
+    if ((he = gethostbyname(hostname)) == NULL) {
+       security_seterror(&kh->sech,
+           "%s: could not resolve hostname", hostname);
+       (*fn)(arg, &kh->sech, S_ERROR);
+       return;
+    }
+    kh->fn.connect = fn;
+    kh->conf_fn = conf_fn;
+    kh->arg = arg;
+    kh->hostname = stralloc(he->h_name);
+    kh->ks = krb5_stream_client(kh, newhandle++);
+
+    if (kh->ks == NULL)
+       goto error;
+
+    fd = kh->ks->kc->fd;
+
+    if (fd < 0) {
+       /*
+        * We need to open a new connection.  See if we have too
+        * many connections open.
+        */
+       if (connq.qlength > AMANDA_KRB5_MAXCONN) {
+           k5printf(("krb5_connect: too many conections (%d), delaying %s\n",
+               connq.qlength, kh->hostname));
+           krb5_stream_close(kh->ks);
+           kh->ev_wait = event_register((event_id_t)open_callback,
+               EV_WAIT, open_callback, kh);
+           return;
+       }
+
+       if ((se = getservbyname(AMANDA_KRB5_SERVICE_NAME, "tcp")) == NULL)
+           port = htons(AMANDA_KRB5_DEFAULT_PORT);
+       else
+           port = se->s_port;
+
+       /*
+        * Get a non-blocking socket.
+        */
+       fd = stream_client(kh->hostname, ntohs(port), KRB5_STREAM_BUFSIZE,
+           KRB5_STREAM_BUFSIZE, NULL, 1);
+       if (fd < 0) {
+           security_seterror(&kh->sech,
+               "can't connect to %s:%d: %s", hostname, ntohs(port),
+               strerror(errno));
+           goto error;
+       }
+       kh->ks->kc->fd = fd;
+    }
+    /*
+     * The socket will be opened async so hosts that are down won't
+     * block everything.  We need to register a write event
+     * so we will know when the socket comes alive.
+     * We also register a timeout.
+     */
+    kh->ev_wait = event_register(fd, EV_WRITEFD, connect_callback, kh);
+    kh->ev_timeout = event_register(GSS_TIMEOUT, EV_TIME, connect_timeout, kh);
+
+    return;
+
+error:
+    (*fn)(arg, &kh->sech, S_ERROR);
+}
+
+/*
+ * Called when there are not too many connections open such that
+ * we can open more.
+ */
+static void
+open_callback(cookie)
+    void *cookie;
+{
+    struct krb5_handle *kh = cookie;
+
+    event_release(kh->ev_wait);
+
+    k5printf(("krb5: open_callback: possible connections available, retry %s\n",
+       kh->hostname));
+    krb5_connect(kh->hostname, kh->conf_fn, kh->fn.connect, kh->arg);
+    amfree(kh->hostname);
+    amfree(kh);
+}
+
+/*
+ * Called when a tcp connection is finished connecting and is ready
+ * to be authenticated.
+ */
+static void
+connect_callback(cookie)
+    void *cookie;
+{
+    struct krb5_handle *kh = cookie;
+
+    event_release(kh->ev_wait);
+    kh->ev_wait = NULL;
+    event_release(kh->ev_timeout);
+    kh->ev_timeout = NULL;
+
+    if (kh->ks->kc->state == unauthed) {
+       if (gss_client(kh) < 0) {
+           (*kh->fn.connect)(kh->arg, &kh->sech, S_ERROR);
+           return;
+       }
+       kh->ks->kc->state = authed;
+    }
+    assert(kh->ks->kc->gss_context != GSS_C_NO_CONTEXT);
+
+    (*kh->fn.connect)(kh->arg, &kh->sech, S_OK);
+}
+
+/*
+ * Called if a connection times out before completion.
+ */
+static void
+connect_timeout(cookie)
+    void *cookie;
+{
+    struct krb5_handle *kh = cookie;
+
+    event_release(kh->ev_wait);
+    kh->ev_wait = NULL;
+    event_release(kh->ev_timeout);
+    kh->ev_timeout = NULL;
+
+    (*kh->fn.connect)(kh->arg, &kh->sech, S_TIMEOUT);
+}
+
+/*
+ * Setup to handle new incoming connections
+ */
+static void
+krb5_accept(in, out, fn)
+    int in, out;
+    void (*fn) P((security_handle_t *, pkt_t *));
+{
+    struct sockaddr_in sin;
+    size_t len;
+    struct krb5_conn *kc;
+    struct hostent *he;
+
+    /*
+     * Make sure we're initted
+     */
+    init();
+
+    len = sizeof(sin);
+    if (getpeername(in, (struct sockaddr *)&sin, &len) < 0)
+       return;
+    he = gethostbyaddr((void *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET);
+    if (he == NULL)
+       return;
+
+    kc = conn_get(he->h_name);
+    kc->fd = in;
+    if (gss_server(kc) < 0)
+       error("gss_server failed: %s\n", kc->errmsg);
+    kc->state = authed;
+    accept_fn = fn;
+    conn_read(kc);
+}
+
+/*
+ * Locate an existing connection to the given host, or create a new,
+ * unconnected entry if none exists.  The caller is expected to check
+ * for the lack of a connection (kc->fd == -1) and set one up.
+ */
+static struct krb5_conn *
+conn_get(hostname)
+    const char *hostname;
+{
+    struct krb5_conn *kc;
+
+    k5printf(("krb5: conn_get: %s\n", hostname));
+
+    for (kc = connq_first(); kc != NULL; kc = connq_next(kc)) {
+       if (strcasecmp(hostname, kc->hostname) == 0)
+           break;
+    }
+
+    if (kc != NULL) {
+       kc->refcnt++;
+       k5printf(("krb5: conn_get: exists, refcnt to %s is now %d\n",
+           kc->hostname, kc->refcnt));
+       return (kc);
+    }
+
+    k5printf(("krb5: conn_get: creating new handle\n"));
+    /*
+     * We can't be creating a new handle if we are the client
+     */
+    assert(accept_fn == NULL);
+    kc = alloc(sizeof(*kc));
+    kc->fd = -1;
+    kc->readbuf.left = 0;
+    kc->readbuf.size = 0;
+    kc->state = unauthed;
+    kc->ev_read = NULL;
+    strncpy(kc->hostname, hostname, sizeof(kc->hostname) - 1);
+    kc->hostname[sizeof(kc->hostname) - 1] = '\0';
+    kc->errmsg = NULL;
+    kc->gss_context = GSS_C_NO_CONTEXT;
+    /*
+     * [XXX] this is set to 2 in order to force the connection to stay
+     * open and process more protocol requests.  (basically consistant
+     * with bsd-security.c, and theoretically krb4-security.c.   This
+     * needs to be addressed in a cleaner way.
+     */
+    kc->refcnt = 2;
+    TAILQ_INIT(&kc->frameq);
+    connq_append(kc);
+    return (kc);
+}
+
+/*
+ * Delete a reference to a connection, and close it if it is the last
+ * reference.
+ */
+static void
+conn_put(kc)
+    struct krb5_conn *kc;
+{
+    OM_uint32 min_stat;
+    struct krb5_frame *kf;
+
+    assert(kc->refcnt > 0);
+    if (--kc->refcnt > 0) {
+       k5printf(("krb5: conn_put: decrementing refcnt for %s to %d\n",
+           kc->hostname, kc->refcnt));
+       return;
+    }
+    k5printf(("krb5: conn_put: closing connection to %s\n", kc->hostname));
+    if (kc->fd != -1)
+       aclose(kc->fd);
+    if (kc->ev_read != NULL)
+       event_release(kc->ev_read);
+    if (kc->errmsg != NULL)
+       amfree(kc->errmsg);
+    gss_delete_sec_context(&min_stat, &kc->gss_context, GSS_C_NO_BUFFER);
+    while ((kf = TAILQ_FIRST(&kc->frameq)) != NULL) {
+       TAILQ_REMOVE(&kc->frameq, kf, tq);
+       if (kf->tok.value != NULL)
+           amfree(kf->tok.value);
+       amfree(kf);
+    }
+    connq_remove(kc);
+    amfree(kc);
+    /* signal that a connection is available */
+    event_wakeup((event_id_t)open_callback);
+}
+
+/*
+ * Turn on read events for a conn.  Or, increase a refcnt if we are
+ * already receiving read events.
+ */
+static void
+conn_read(kc)
+    struct krb5_conn *kc;
+{
+
+    if (kc->ev_read != NULL) {
+       kc->ev_read_refcnt++;
+       k5printf(("krb5: conn_read: incremented refcnt to %d for %s\n",
+           kc->ev_read_refcnt, kc->hostname));
+       return;
+    }
+    k5printf(("krb5: conn_read registering event handler for %s\n",
+       kc->hostname));
+    kc->ev_read = event_register(kc->fd, EV_READFD, conn_read_callback, kc);
+    kc->ev_read_refcnt = 1;
+}
+
+static void
+conn_read_cancel(kc)
+    struct krb5_conn *kc;
+{
+
+    if (--kc->ev_read_refcnt > 0) {
+       k5printf(("krb5: conn_read_cancel: decremented refcnt to %d for %s\n",
+           kc->ev_read_refcnt, kc->hostname));
+       return;
+    }
+    k5printf(("krb5: conn_read_cancel: releasing event handler for %s\n",
+       kc->hostname));
+    event_release(kc->ev_read);
+    kc->ev_read = NULL;
+}
+
+/*
+ * frees a handle allocated by the above
+ */
+static void
+krb5_close(inst)
+    void *inst;
+{
+    struct krb5_handle *kh = inst;
+
+    assert(kh != NULL);
+
+    k5printf(("krb5: closing handle to %s\n", kh->hostname));
+
+    if (kh->ks != NULL) {
+       /* This may be null if we get here on an error */
+       krb5_recvpkt_cancel(kh);
+       security_stream_close(&kh->ks->secstr);
+    }
+    amfree(kh->hostname);
+    amfree(kh);
+}
+
+/*
+ * Transmit a packet.  Encrypt first.
+ */
+static int
+krb5_sendpkt(cookie, pkt)
+    void *cookie;
+    pkt_t *pkt;
+{
+    struct krb5_handle *kh = cookie;
+    gss_buffer_desc tok;
+    int rval;
+    unsigned char c, *buf;
+
+    assert(kh != NULL);
+    assert(pkt != NULL);
+
+    k5printf(("krb5: sendpkt: enter\n"));
+
+    if (pkt->body[0] == '\0') {
+       c = (unsigned char)pkt->type;
+       tok.length = 1;
+       tok.value = &c;
+    } else {
+       tok.length = strlen(pkt->body) + 2;
+       tok.value = alloc(tok.length);
+       buf = tok.value;
+       *buf++ = (unsigned char)pkt->type;
+       strncpy(buf, pkt->body, tok.length - 2);
+       buf[tok.length - 2] = '\0';
+    }
+
+    k5printf(("krb5: sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n",
+       pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body));
+
+    rval = krb5_stream_write(kh->ks, tok.value, tok.length);
+    if (rval < 0)
+       security_seterror(&kh->sech, security_stream_geterror(&kh->ks->secstr));
+    if (tok.length > 1)
+       amfree(tok.value);
+    return (rval);
+}
+
+/*
+ * Set up to receive a packet asyncronously, and call back when
+ * it has been read.
+ */
+static void
+krb5_recvpkt(cookie, fn, arg, timeout)
+    void *cookie, *arg;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    int timeout;
+{
+    struct krb5_handle *kh = cookie;
+
+    assert(kh != NULL);
+
+    k5printf(("krb5: recvpkt registered for %s\n", kh->hostname));
+
+    /*
+     * Reset any pending timeout on this handle
+     */
+    if (kh->ev_timeout != NULL)
+       event_release(kh->ev_timeout);
+
+    /*
+     * Negative timeouts mean no timeout
+     */
+    if (timeout < 0)
+       kh->ev_timeout = NULL;
+    else
+       kh->ev_timeout = event_register(timeout, EV_TIME, recvpkt_timeout, kh);
+
+    kh->fn.recvpkt = fn;
+    kh->arg = arg;
+    krb5_stream_read(kh->ks, recvpkt_callback, kh);
+}
+
+/*
+ * Remove a async receive request from the queue
+ */
+static void
+krb5_recvpkt_cancel(cookie)
+    void *cookie;
+{
+    struct krb5_handle *kh = cookie;
+
+    k5printf(("krb5: cancelling recvpkt for %s\n", kh->hostname));
+
+    assert(kh != NULL);
+
+    krb5_stream_read_cancel(kh->ks);
+    if (kh->ev_timeout != NULL) {
+       event_release(kh->ev_timeout);
+       kh->ev_timeout = NULL;
+    }
+}
+
+/*
+ * This is called when a handle is woken up because data read off of the
+ * net is for it.
+ */
+static void
+recvpkt_callback(cookie, buf, bufsize)
+    void *cookie, *buf;
+    ssize_t bufsize;
+{
+    pkt_t pkt;
+    struct krb5_handle *kh = cookie;
+
+    assert(kh != NULL);
+
+    /*
+     * We need to cancel the recvpkt request before calling
+     * the callback because the callback may reschedule us.
+     */
+    krb5_recvpkt_cancel(kh);
+
+    switch (bufsize) {
+    case 0:
+       security_seterror(&kh->sech,
+           "EOF on read from %s", kh->hostname);
+       (*kh->fn.recvpkt)(kh->arg, NULL, S_ERROR);
+       return;
+    case -1:
+       security_seterror(&kh->sech, security_stream_geterror(&kh->ks->secstr));
+       (*kh->fn.recvpkt)(kh->arg, NULL, S_ERROR);
+       return;
+    default:
+       parse_pkt(&pkt, buf, bufsize);
+       k5printf(("krb5: received %s pkt (%d) from %s, contains:\n\n\"%s\"\n\n",
+           pkt_type2str(pkt.type), pkt.type, kh->hostname, pkt.body));
+       (*kh->fn.recvpkt)(kh->arg, &pkt, S_OK);
+       return;
+    }
+}
+
+/*
+ * This is called when a handle times out before receiving a packet.
+ */
+static void
+recvpkt_timeout(cookie)
+    void *cookie;
+{
+    struct krb5_handle *kh = cookie;
+
+    assert(kh != NULL);
+
+    k5printf(("krb5: recvpkt timeout for %s\n", kh->hostname));
+
+    krb5_recvpkt_cancel(kh);
+    (*kh->fn.recvpkt)(kh->arg, NULL, S_TIMEOUT);
+}
+
+/*
+ * Create the server end of a stream.  For krb5, this means setup a stream
+ * object and allocate a new handle for it.
+ */
+static void *
+krb5_stream_server(h)
+    void *h;
+{
+    struct krb5_handle *kh = h;
+    struct krb5_stream *ks;
+
+    assert(kh != NULL);
+
+    ks = alloc(sizeof(*ks));
+    security_streaminit(&ks->secstr, &krb5_security_driver);
+    ks->kc = conn_get(kh->hostname);
+    /*
+     * Stream should already be setup!
+     */
+    if (ks->kc->fd < 0) {
+       conn_put(ks->kc);
+       amfree(ks);
+       security_seterror(&kh->sech, "lost connection");
+       return (NULL);
+    }
+    /*
+     * so as not to conflict with the amanda server's handle numbers,
+     * we start at 5000 and work down
+     */
+    ks->handle = 5000 - newhandle++;
+    ks->ev_read = NULL;
+    k5printf(("krb5: stream_server: created stream %d\n", ks->handle));
+    return (ks);
+}
+
+/*
+ * Accept an incoming connection on a stream_server socket
+ * Nothing needed for krb5.
+ */
+static int
+krb5_stream_accept(s)
+    void *s;
+{
+
+    return (0);
+}
+
+/*
+ * Return a connected stream.  For krb5, this means setup a stream
+ * with the supplied handle.
+ */
+static void *
+krb5_stream_client(h, id)
+    void *h;
+    int id;
+{
+    struct krb5_handle *kh = h;
+    struct krb5_stream *ks;
+
+    assert(kh != NULL);
+
+    if (id <= 0) {
+       security_seterror(&kh->sech,
+           "%d: invalid security stream id", id);
+       return (NULL);
+    }
+
+    ks = alloc(sizeof(*ks));
+    security_streaminit(&ks->secstr, &krb5_security_driver);
+    ks->handle = id;
+    ks->ev_read = NULL;
+    ks->kc = conn_get(kh->hostname);
+
+    k5printf(("krb5: stream_client: connected to stream %d\n", id));
+
+    return (ks);
+}
+
+/*
+ * Close and unallocate resources for a stream.
+ */
+static void
+krb5_stream_close(s)
+    void *s;
+{
+    struct krb5_stream *ks = s;
+
+    assert(ks != NULL);
+
+    k5printf(("krb5: stream_close: closing stream %d\n", ks->handle));
+
+    krb5_stream_read_cancel(ks);
+    conn_put(ks->kc);
+    amfree(ks);
+}
+
+/*
+ * Authenticate a stream
+ * Nothing needed for krb5.  The tcp connection is authenticated
+ * on startup.
+ */
+static int
+krb5_stream_auth(s)
+    void *s;
+{
+
+    return (0);
+}
+
+/*
+ * Returns the stream id for this stream.  This is just the local
+ * port.
+ */
+static int
+krb5_stream_id(s)
+    void *s;
+{
+    struct krb5_stream *ks = s;
+
+    assert(ks != NULL);
+
+    return (ks->handle);
+}
+
+/*
+ * Write a chunk of data to a stream.  Blocks until completion.
+ */
+static int
+krb5_stream_write(s, buf, size)
+    void *s;
+    const void *buf;
+    size_t size;
+{
+    struct krb5_stream *ks = s;
+    gss_buffer_desc tok;
+#ifdef AMANDA_KRB5_ENCRYPT
+    gss_buffer_desc enctok;
+    OM_uint32 min_stat;
+#endif
+    int rc;
+
+    assert(ks != NULL);
+
+    k5printf(("krb5: stream_write: writing %d bytes to %s:%d\n", size,
+       ks->kc->hostname, ks->handle));
+
+    tok.length = size;
+    tok.value = (void *)buf;   /* safe to discard const */
+#ifdef AMANDA_KRB5_ENCRYPT
+    if (kencrypt(ks, &tok, &enctok) < 0)
+       return (-1);
+    rc = send_token(ks->kc, ks->handle, &enctok);
+#else
+    rc = send_token(ks->kc, ks->handle, &tok);
+#endif
+    if (rc < 0)
+       security_stream_seterror(&ks->secstr, ks->kc->errmsg);
+#ifdef AMANDA_KRB5_ENCRYPT
+    gss_release_buffer(&min_stat, &enctok);
+#endif
+    return (rc);
+}
+
+/*
+ * Submit a request to read some data.  Calls back with the given
+ * function and arg when completed.
+ */
+static void
+krb5_stream_read(s, fn, arg)
+    void *s, *arg;
+    void (*fn) P((void *, void *, int));
+{
+    struct krb5_stream *ks = s;
+
+    assert(ks != NULL);
+
+    /*
+     * Only one read request can be active per stream.
+     */
+    ks->fn = fn;
+    ks->arg = arg;
+
+    /*
+     * First see if there's any queued frames for this stream.
+     * If so, we're done.
+     */
+    if (conn_run_frameq(ks->kc, ks) > 0)
+       return;
+
+    if (ks->ev_read == NULL) {
+       ks->ev_read = event_register((event_id_t)ks->kc, EV_WAIT,
+           stream_read_callback, ks);
+       conn_read(ks->kc);
+    }
+}
+
+/*
+ * Cancel a previous stream read request.  It's ok if we didn't have a read
+ * scheduled.
+ */
+static void
+krb5_stream_read_cancel(s)
+    void *s;
+{
+    struct krb5_stream *ks = s;
+
+    assert(ks != NULL);
+
+    if (ks->ev_read != NULL) {
+       event_release(ks->ev_read);
+       ks->ev_read = NULL;
+       conn_read_cancel(ks->kc);
+    }
+}
+
+/*
+ * Callback for krb5_stream_read
+ */
+static void
+stream_read_callback(arg)
+    void *arg;
+{
+    struct krb5_stream *ks = arg;
+
+    assert(ks != NULL);
+
+    k5printf(("krb5: stream_read_callback: handle %d\n", ks->handle));
+
+    conn_run_frameq(ks->kc, ks);
+}
+
+/*
+ * Run down a list of queued frames for a krb5_conn, and if we find one
+ * that matches the passed handle, fire the read event.  Only
+ * process one frame.
+ *
+ * Returns 1 if a frame was found and processed.
+ */
+static int
+conn_run_frameq(kc, ks)
+    struct krb5_conn *kc;
+    struct krb5_stream *ks;
+{
+    struct krb5_frame *kf, *nextkf;
+    gss_buffer_desc *enctok, *dectok;
+#ifdef AMANDA_KRB5_ENCRYPT
+    OM_uint32 min_stat;
+    gss_buffer_desc tok;
+#endif
+
+    /*
+     * Iterate through all of the frames in the queue.  If one
+     * is for us, process it.  If we hit an EOF frame, shut down.
+     * Stop after processing one frame, because we are only supposed
+     * to return one read request.
+     */
+    for (kf = TAILQ_FIRST(&kc->frameq); kf != NULL; kf = nextkf) {
+       nextkf = TAILQ_NEXT(kf, tq);
+
+       if (kf->handle != ks->handle && kf->handle != H_EOF) {
+           k5printf(("krb5: conn_frameq_run: not for us (handle %d)\n",
+               kf->handle));
+           continue;
+       }
+       /*
+        * We want all listeners to see the EOF, so never remove it.
+        * It will get cleaned up when the connection is closed
+        * in conn_put().
+        */
+       if (kf->handle != H_EOF)
+           TAILQ_REMOVE(&kc->frameq, kf, tq);
+
+       /*
+        * Remove the event first, and then call the callback.
+        * We remove it first because we don't want to get in their
+        * way if they reschedule it.
+        */
+       krb5_stream_read_cancel(ks);
+
+       enctok = &kf->tok;
+
+       if (enctok->length == 0) {
+           assert(kf->handle == H_EOF);
+           k5printf(("krb5: stream_read_callback: EOF\n"));
+           (*ks->fn)(ks->arg, NULL, 0);
+           return (1); /* stop after EOF */
+       }
+
+#ifdef AMANDA_KRB5_ENCRYPT
+       dectok = &tok;
+       if (kdecrypt(ks, enctok, &tok) < 0) {
+           k5printf(("krb5: stream_read_callback: kdecrypt error\n"));
+           (*ks->fn)(ks->arg, NULL, -1);
+       } else
+#else
+       dectok = enctok;
+#endif
+       {
+           k5printf(("krb5: stream_read_callback: read %d bytes from %s:%d\n",
+               dectok->length, ks->kc->hostname, ks->handle));
+           (*ks->fn)(ks->arg, dectok->value, dectok->length);
+#ifdef AMANDA_KRB5_ENCRYPT
+           gss_release_buffer(&min_stat, dectok);
+#endif
+       }
+       amfree(enctok->value);
+       amfree(kf);
+       return (1);             /* stop after one frame */
+    }
+    return (0);
+}
+
+/*
+ * The callback for the netfd for the event handler
+ * Determines if this packet is for this security handle,
+ * and does the real callback if so.
+ */
+static void
+conn_read_callback(cookie)
+    void *cookie;
+{
+    struct krb5_conn *kc = cookie;
+    struct krb5_handle *kh;
+    struct krb5_frame *kf;
+    pkt_t pkt;
+    gss_buffer_desc *dectok;
+    int rc;
+#ifdef AMANDA_KRB5_ENCRYPT
+    gss_buffer_desc tok;
+    OM_uint32 min_stat;
+#endif
+
+    assert(cookie != NULL);
+
+    k5printf(("krb5: conn_read_callback\n"));
+
+    kf = alloc(sizeof(*kf));
+    TAILQ_INSERT_TAIL(&kc->frameq, kf, tq);
+
+    /* Read the data off the wire.  If we get errors, shut down. */
+    rc = recv_token(kc, &kf->handle, &kf->tok, 5);
+    k5printf(("krb5: conn_read_callback: recv_token returned %d handle = %d\n",
+       rc, kf->handle));
+    if (rc <= 0) {
+       kf->tok.value = NULL;
+       kf->tok.length = 0;
+       kf->handle = H_EOF;
+       rc = event_wakeup((event_id_t)kc);
+       k5printf(("krb5: conn_read_callback: event_wakeup return %d\n", rc));
+       return;
+    }
+
+    /* If there are events waiting on this handle, we're done */
+    rc = event_wakeup((event_id_t)kc);
+    k5printf(("krb5: conn_read_callback: event_wakeup return %d\n", rc));
+    if (rc > 0)
+       return;
+
+    /*
+     * If there is no accept fn registered, then just leave the
+     * packet queued.  The caller may register a function later.
+     */
+    if (accept_fn == NULL) {
+       k5printf(("krb5: no accept_fn so leaving packet queued.\n"));
+       return;
+    }
+
+    kh = alloc(sizeof(*kh));
+    security_handleinit(&kh->sech, &krb5_security_driver);
+    kh->hostname = stralloc(kc->hostname);
+    kh->ks = krb5_stream_client(kh, kf->handle);
+    kh->ev_wait = NULL;
+    kh->ev_timeout = NULL;
+
+    TAILQ_REMOVE(&kc->frameq, kf, tq);
+    k5printf(("krb5: new connection\n"));
+#ifdef AMANDA_KRB5_ENCRYPT
+    dectok = &tok;
+    rc = kdecrypt(kh->ks, &kf->tok, dectok);
+#else
+    dectok = &kf->tok;
+#endif
+
+#ifdef AMANDA_KRB5_ENCRYPT
+    if (rc < 0) {
+       security_seterror(&kh->sech, security_geterror(&kh->ks->secstr));
+       (*accept_fn)(&kh->sech, NULL);
+    } else
+#endif
+    {
+       parse_pkt(&pkt, dectok->value, dectok->length);
+#ifdef AMANDA_KRB5_ENCRYPT
+       gss_release_buffer(&min_stat, dectok);
+#endif
+       (*accept_fn)(&kh->sech, &pkt);
+    }
+    amfree(kf->tok.value);
+    amfree(kf);
+
+    /*
+     * We can only accept one connection per process, since we're tcp
+     * based and run out of inetd.  So, delete our accept reference once
+     * we've gotten the first connection.
+     */
+
+    /*
+     * [XXX] actually, the protocol has been changed to have multiple
+     * requests in one session be possible.  By not resetting accept_fn,
+     * this will caused them to be properly processed.  this needs to be
+     * addressed in a much cleaner way.
+     */
+    if (accept_fn != NULL)
+       conn_put(kc);
+    /* accept_fn = NULL; */
+}
+
+/*
+ * Negotiate a krb5 gss context from the client end.
+ */
+static int
+gss_client(kh)
+    struct krb5_handle *kh;
+{
+    struct krb5_stream *ks = kh->ks;
+    struct krb5_conn *kc = ks->kc;
+    gss_buffer_desc send_tok, recv_tok;
+    OM_uint32 maj_stat, min_stat;
+    unsigned int ret_flags;
+    int rc, rval = -1;
+    gss_name_t gss_name;
+
+    k5printf(("gss_client\n"));
+
+    send_tok.value = vstralloc("host/", ks->kc->hostname, NULL);
+    send_tok.length = strlen(send_tok.value) + 1;
+    maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID,
+       &gss_name);
+    if (maj_stat != GSS_S_COMPLETE) {
+       security_seterror(&kh->sech, "can't import name %s: %s",
+           (char *)send_tok.value, gss_error(maj_stat, min_stat));
+       amfree(send_tok.value);
+       return (-1);
+    }
+    amfree(send_tok.value);
+    kc->gss_context = GSS_C_NO_CONTEXT;
+
+    /*
+     * Perform the context-establishement loop.
+     *
+     * Every generated token is stored in send_tok which is then
+     * transmitted to the server; every received token is stored in
+     * recv_tok (empty on the first pass) to be processed by
+     * the next call to gss_init_sec_context.
+     * 
+     * GSS-API guarantees that send_tok's length will be non-zero
+     * if and only if the server is expecting another token from us,
+     * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
+     * and only if the server has another token to send us.
+     */
+
+    for (recv_tok.length = 0;;) {
+       min_stat = 0;
+       maj_stat = gss_init_sec_context(&min_stat,
+           GSS_C_NO_CREDENTIAL,
+           &kc->gss_context,
+           gss_name,
+           GSS_C_NULL_OID,
+           GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG,
+           0, NULL,    /* no channel bindings */
+           (recv_tok.length == 0 ? GSS_C_NO_BUFFER : &recv_tok),
+           NULL,       /* ignore mech type */
+           &send_tok,
+           &ret_flags,
+           NULL);      /* ignore time_rec */
+
+       if (recv_tok.length != 0) {
+           amfree(recv_tok.value);
+           recv_tok.length = 0;
+       }
+
+       if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) {
+           security_seterror(&kh->sech,
+               "error getting gss context: %s",
+               gss_error(maj_stat, min_stat));
+           goto done;
+       }
+
+       /*
+        * Send back the response
+        */
+       if (send_tok.length != 0 && send_token(kc, ks->handle, &send_tok) < 0) {
+           security_seterror(&kh->sech, kc->errmsg);
+           gss_release_buffer(&min_stat, &send_tok);
+           goto done;
+       }
+       gss_release_buffer(&min_stat, &send_tok);
+
+       /*
+        * If we need to continue, then register for more packets
+        */
+       if (maj_stat != GSS_S_CONTINUE_NEEDED)
+           break;
+
+       if ((rc = recv_token(kc, NULL, &recv_tok, GSS_TIMEOUT)) <= 0) {
+           if (rc < 0)
+               security_seterror(&kh->sech,
+                   "recv error in gss loop: %s", kc->errmsg);
+           else
+               security_seterror(&kh->sech, "EOF in gss loop");
+           goto done;
+       }
+    }
+
+    rval = 0;
+done:
+    gss_release_name(&min_stat, &gss_name);
+    return (rval);
+}
+
+/*
+ * Negotiate a krb5 gss context from the server end.
+ */
+static int
+gss_server(kc)
+    struct krb5_conn *kc;
+{
+    OM_uint32 maj_stat, min_stat, ret_flags;
+    gss_buffer_desc send_tok, recv_tok;
+    gss_OID doid;
+    gss_name_t gss_name;
+    gss_cred_id_t gss_creds;
+    char *p, *realm, *msg;
+    uid_t euid;
+    int rc, rval = -1;
+    char errbuf[256];
+
+    k5printf(("gss_server\n"));
+
+    assert(kc != NULL);
+
+    /*
+     * We need to be root while in gss_acquire_cred() to read the host key
+     * out of the default keytab.  We also need to be root in
+     * gss_accept_context() thanks to the replay cache code.
+     */
+    euid = geteuid();
+    if (getuid() != 0) {
+       snprintf(errbuf, sizeof(errbuf),
+           "real uid is %ld, needs to be 0 to read krb5 host key",
+           (long)getuid());
+       goto out;
+    }
+    if (seteuid(0) < 0) {
+       snprintf(errbuf, sizeof(errbuf),
+           "can't seteuid to uid 0: %s", strerror(errno));
+       goto out;
+    }
+
+    send_tok.value = vstralloc("host/", hostname, NULL);
+    send_tok.length = strlen(send_tok.value) + 1;
+    for (p = send_tok.value; *p != '\0'; p++) {
+       if (isupper((int)*p))
+           *p = tolower(*p);
+    }
+    maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID,
+       &gss_name);
+    if (maj_stat != GSS_S_COMPLETE) {
+       seteuid(euid);
+       snprintf(errbuf, sizeof(errbuf),
+           "can't import name %s: %s", (char *)send_tok.value,
+           gss_error(maj_stat, min_stat));
+       amfree(send_tok.value);
+       goto out;
+    }
+    amfree(send_tok.value);
+
+    maj_stat = gss_acquire_cred(&min_stat, gss_name, 0,
+       GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &gss_creds, NULL, NULL);
+    if (maj_stat != GSS_S_COMPLETE) {
+       snprintf(errbuf, sizeof(errbuf),
+           "can't acquire creds for host key host/%s: %s", hostname,
+           gss_error(maj_stat, min_stat));
+       gss_release_name(&min_stat, &gss_name);
+       seteuid(euid);
+       goto out;
+    }
+    gss_release_name(&min_stat, &gss_name);
+
+    for (recv_tok.length = 0;;) {
+       if ((rc = recv_token(kc, NULL, &recv_tok, GSS_TIMEOUT)) <= 0) {
+           if (rc < 0) {
+               snprintf(errbuf, sizeof(errbuf),
+                   "recv error in gss loop: %s", kc->errmsg);
+               amfree(kc->errmsg);
+           } else
+               snprintf(errbuf, sizeof(errbuf), "EOF in gss loop");
+           goto out;
+       }
+
+       maj_stat = gss_accept_sec_context(&min_stat, &kc->gss_context,
+           gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS,
+           &gss_name, &doid, &send_tok, &ret_flags, NULL, NULL);
+
+       if (maj_stat != GSS_S_COMPLETE &&
+           maj_stat != GSS_S_CONTINUE_NEEDED) {
+           snprintf(errbuf, sizeof(errbuf),
+               "error accepting context: %s", gss_error(maj_stat, min_stat));
+           amfree(recv_tok.value);
+           goto out;
+       }
+       amfree(recv_tok.value);
+
+       if (send_tok.length > 0 && send_token(kc, 0, &send_tok) < 0) {
+           strncpy(errbuf, kc->errmsg, sizeof(errbuf) - 1);
+           errbuf[sizeof(errbuf) - 1] = '\0';
+           amfree(kc->errmsg);
+           gss_release_buffer(&min_stat, &send_tok);
+           goto out;
+       }
+       gss_release_buffer(&min_stat, &send_tok);
+
+
+       /*
+        * If we need to get more from the client, then register for
+        * more packets.
+        */
+       if (maj_stat != GSS_S_CONTINUE_NEEDED)
+           break;
+    }
+
+    maj_stat = gss_display_name(&min_stat, gss_name, &send_tok, &doid);
+    if (maj_stat != GSS_S_COMPLETE) {
+       snprintf(errbuf, sizeof(errbuf),
+           "can't display gss name: %s", gss_error(maj_stat, min_stat));
+       gss_release_name(&min_stat, &gss_name);
+       goto out;
+    }
+    gss_release_name(&min_stat, &gss_name);
+
+    /* get rid of the realm */
+    if ((p = strchr(send_tok.value, '@')) == NULL) {
+       snprintf(errbuf, sizeof(errbuf),
+           "malformed gss name: %s", (char *)send_tok.value);
+       amfree(send_tok.value);
+       goto out;
+    }
+    *p = '\0';
+    realm = ++p;
+
+    /* 
+     * If the principal doesn't match, complain
+     */
+    if ((msg = krb5_checkuser(kc->hostname, send_tok.value, realm)) != NULL) {
+       snprintf(errbuf, sizeof(errbuf),
+           "access not allowed from %s: %s", (char *)send_tok.value, msg);
+       amfree(send_tok.value);
+       goto out;
+    }
+    amfree(send_tok.value);
+
+    rval = 0;
+out:
+    seteuid(euid);
+    if (rval != 0)
+       kc->errmsg = stralloc(errbuf);
+    k5printf(("gss_server returning %d\n", rval));
+    return (rval);
+}
+
+/*
+ * Setup some things about krb5.  This should only be called once.
+ */
+static void
+init()
+{
+    static int beenhere = 0;
+    struct hostent *he;
+    char *p;
+    int krb5_setenv P((const char *, const char *, int));
+
+    if (beenhere)
+       return;
+    beenhere = 1;
+
+#ifndef BROKEN_MEMORY_CCACHE
+    krb5_setenv(KRB5_ENV_CCNAME, "MEMORY:amanda_ccache", 1);
+#else
+    /*
+     * MEMORY ccaches seem buggy and cause a lot of internal heap
+     * corruption.  malloc has been known to core dump.  This behavior
+     * has been witnessed in Cygnus' kerbnet 1.2, MIT's krb V 1.0.5 and
+     * MIT's krb V -current as of 3/17/1999.
+     *
+     * We just use a lame ccache scheme with a uid suffix.
+     */
+    atexit(cleanup);
+    {
+       char ccache[64];
+       snprintf(ccache, sizeof(ccache), "FILE:/tmp/amanda_ccache.%ld.%ld",
+           (long)geteuid(), (long)getpid());
+       krb5_setenv(KRB5_ENV_CCNAME, ccache, 1);
+    }
+#endif
+
+    gethostname(hostname, sizeof(hostname) - 1);
+    hostname[sizeof(hostname) - 1] = '\0';
+    /*
+     * In case it isn't fully qualified, do a DNS lookup.
+     */
+    if ((he = gethostbyname(hostname)) != NULL)
+       strncpy(hostname, he->h_name, sizeof(hostname) - 1);
+
+    /*
+     * Lowercase the results.  We assume all host/ principals will be
+     * lowercased.
+     */
+    for (p = hostname; *p != '\0'; p++) {
+       if (isupper((int)*p))
+           *p = tolower(*p);
+    }
+}
+
+#ifdef BROKEN_MEMORY_CCACHE
+static void
+cleanup()
+{
+#ifdef KDESTROY_VIA_UNLINK
+    char ccache[64];
+    snprintf(ccache, sizeof(ccache), "/tmp/amanda_ccache.%ld.%ld",
+        (long)geteuid(), (long)getpid());
+    unlink(ccache);
+#else
+    kdestroy();
+#endif
+}
+#endif
+
+/*
+ * Get a ticket granting ticket and stuff it in the cache
+ */
+static const char *
+get_tgt(keytab_name, principal_name)
+       char *keytab_name, *principal_name;
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_principal client = NULL, server = NULL;
+    krb5_creds creds;
+    krb5_keytab keytab = NULL;
+    krb5_ccache ccache;
+    krb5_timestamp now;
+    krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME };
+    static char *error = NULL;
+
+    if (error != NULL) {
+       amfree(error);
+       error = NULL;
+    }
+
+    if ((ret = krb5_init_context(&context)) != 0) {
+       error = vstralloc("error initializing krb5 context: ",
+           error_message(ret), NULL);
+       return (error);
+    }
+
+    krb5_init_ets(context);
+
+    if(!keytab_name) {
+        error = vstralloc("error  -- no krb5 keytab defined", NULL);
+        return(error);
+    }
+
+    if(!principal_name) {
+        error = vstralloc("error  -- no krb5 principal defined", NULL);
+        return(error);
+    }
+
+    /*
+     * Resolve keytab file into a keytab object
+     */
+    if ((ret = krb5_kt_resolve(context, keytab_name, &keytab)) != 0) {
+       error = vstralloc("error resolving keytab ", keytab, ": ",
+           error_message(ret), NULL);
+       return (error);
+    }
+
+    /*
+     * Resolve the amanda service held in the keytab into a principal
+     * object
+     */
+    ret = krb5_parse_name(context, principal_name, &client);
+    if (ret != 0) {
+       error = vstralloc("error parsing ", principal_name, ": ",
+           error_message(ret), NULL);
+       return (error);
+    }
+
+    ret = krb5_build_principal_ext(context, &server,
+       krb5_princ_realm(context, client)->length,
+       krb5_princ_realm(context, client)->data,
+       tgtname.length, tgtname.data,
+       krb5_princ_realm(context, client)->length,
+       krb5_princ_realm(context, client)->data,
+       0);
+    if (ret != 0) {
+       error = vstralloc("error while building server name: ",
+           error_message(ret), NULL);
+       return (error);
+    }
+
+    ret = krb5_timeofday(context, &now);
+    if (ret != 0) {
+       error = vstralloc("error getting time of day: ", error_message(ret),
+           NULL);
+       return (error);
+    }
+
+    memset(&creds, 0, sizeof(creds));
+    creds.times.starttime = 0;
+    creds.times.endtime = now + AMANDA_TKT_LIFETIME;
+
+    creds.client = client;
+    creds.server = server;
+
+    /*
+     * Get a ticket for the service, using the keytab
+     */
+    ret = krb5_get_in_tkt_with_keytab(context, 0, NULL, NULL, NULL,
+       keytab, 0, &creds, 0);
+
+    if (ret != 0) {
+       error = vstralloc("error getting ticket for ", principal_name,
+           ": ", error_message(ret), NULL);
+       goto cleanup2;
+    }
+
+    if ((ret = krb5_cc_default(context, &ccache)) != 0) {
+       error = vstralloc("error initializing ccache: ", error_message(ret),
+           NULL);
+       goto cleanup;
+    }
+    if ((ret = krb5_cc_initialize(context, ccache, client)) != 0) {
+       error = vstralloc("error initializing ccache: ", error_message(ret),
+           NULL);
+       goto cleanup;
+    }
+    if ((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) {
+       error = vstralloc("error storing creds in ccache: ",
+           error_message(ret), NULL);
+       /* FALLTHROUGH */
+    }
+    krb5_cc_close(context, ccache);
+cleanup:
+    krb5_free_cred_contents(context, &creds);
+cleanup2:
+#if 0
+    krb5_free_principal(context, client);
+    krb5_free_principal(context, server);
+#endif
+    krb5_free_context(context);
+    return (error);
+}
+
+/*
+ * get rid of tickets
+ */
+kdestroy()
+{
+    krb5_context context;
+    krb5_ccache ccache;
+
+    if ((krb5_init_context(&context)) != 0) {
+       return;
+    }
+    if ((krb5_cc_default(context, &ccache)) != 0) {
+       goto cleanup;
+    }
+
+    krb5_cc_destroy(context, ccache);
+    krb5_cc_close(context, ccache);
+
+cleanup:
+     krb5_free_context(context);
+     return;
+}
+
+static void
+parse_pkt(pkt, buf, bufsize)
+    pkt_t *pkt;
+    const void *buf;
+    size_t bufsize;
+{
+    const unsigned char *bufp = buf;
+
+    k5printf(("krb5: parse_pkt: parsing buffer of %d bytes\n", bufsize));
+
+    pkt->type = (pktype_t)*bufp++;
+    bufsize--;
+
+    if (bufsize == 0) {
+       pkt->body[0] = '\0';
+    } else {
+       if (bufsize > sizeof(pkt->body) - 1)
+           bufsize = sizeof(pkt->body) - 1;
+       memcpy(pkt->body, bufp, bufsize);
+       pkt->body[sizeof(pkt->body) - 1] = '\0';
+    }
+
+    k5printf(("krb5: parse_pkt: %s (%d): \"%s\"\n", pkt_type2str(pkt->type),
+       pkt->type, pkt->body));
+}
+
+
+/*
+ * Formats an error from the gss api
+ */
+static const char *
+gss_error(major, minor)
+    OM_uint32 major, minor;
+{
+    static gss_buffer_desc msg;
+    OM_uint32 min_stat, msg_ctx;
+
+    if (msg.length > 0)
+       gss_release_buffer(&min_stat, &msg);
+
+    msg_ctx = 0;
+    if (major == GSS_S_FAILURE)
+       gss_display_status(&min_stat, minor, GSS_C_MECH_CODE, GSS_C_NULL_OID,
+           &msg_ctx, &msg);
+    else
+       gss_display_status(&min_stat, major, GSS_C_GSS_CODE, GSS_C_NULL_OID,
+           &msg_ctx, &msg);
+    return ((const char *)msg.value);
+}
+
+/*
+ * Transmits a gss_buffer_desc over a krb5_handle, adding
+ * the necessary headers to allow the remote end to decode it.
+ * Encryption must be done by the caller.
+ */
+static int
+send_token(kc, handle, tok)
+    struct krb5_conn *kc;
+    int handle;
+    const gss_buffer_desc *tok;
+{
+    OM_uint32 netlength, nethandle;
+    struct iovec iov[3];
+
+    k5printf(("krb5: send_token: writing %d bytes to %s\n", tok->length,
+       kc->hostname));
+
+    if (tok->length > AMANDA_MAX_TOK_SIZE) {
+       kc->errmsg = newvstralloc(kc->errmsg, "krb5 write error to ",
+           kc->hostname, ": token too large", NULL);
+       return (-1);
+    }
+
+    /*
+     * Format is:
+     *   32 bit length (network byte order)
+     *   32 bit handle (network byte order)
+     *   data
+     */
+    netlength = htonl(tok->length);
+    iov[0].iov_base = (void *)&netlength;
+    iov[0].iov_len = sizeof(netlength);
+
+    nethandle = htonl(handle);
+    iov[1].iov_base = (void *)&nethandle;
+    iov[1].iov_len = sizeof(nethandle);
+
+    iov[2].iov_base = (void *)tok->value;
+    iov[2].iov_len = tok->length;
+
+    if (net_writev(kc->fd, iov, 3) < 0) {
+       kc->errmsg = newvstralloc(kc->errmsg, "krb5 write error to ",
+           kc->hostname, ": ", strerror(errno), NULL);
+       return (-1);
+    }
+    return (0);
+}
+
+static int
+recv_token(kc, handle, gtok, timeout)
+    struct krb5_conn *kc;
+    int *handle;
+    gss_buffer_desc *gtok;
+    int timeout;
+{
+    OM_uint32 netint;
+
+    assert(kc->fd >= 0);
+    assert(gtok != NULL);
+
+    k5printf(("krb5: recv_token: reading from %s\n", kc->hostname));
+
+    switch (net_read(kc, &netint, sizeof(netint), timeout)) {
+    case -1:
+       kc->errmsg = newvstralloc(kc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       k5printf(("krb5 recv_token error return: %s\n", kc->errmsg));
+       return (-1);
+    case 0:
+       gtok->length = 0;
+       return (0);
+    default:
+       break;
+    }
+    gtok->length = ntohl(netint);
+
+    if (gtok->length > AMANDA_MAX_TOK_SIZE) {
+       kc->errmsg = newstralloc(kc->errmsg, "recv error: buffer too large");
+       k5printf(("krb5 recv_token error return: %s\n", kc->errmsg));
+       return (-1);
+    }
+
+    switch (net_read(kc, &netint, sizeof(netint), timeout)) {
+    case -1:
+       kc->errmsg = newvstralloc(kc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       k5printf(("krb5 recv_token error return: %s\n", kc->errmsg));
+       return (-1);
+    case 0:
+       gtok->length = 0;
+       return (0);
+    default:
+       break;
+    }
+    if (handle != NULL)
+       *handle = ntohl(netint);
+
+    gtok->value = alloc(gtok->length);
+    switch (net_read(kc, gtok->value, gtok->length, timeout)) {
+    case -1:
+       kc->errmsg = newvstralloc(kc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       k5printf(("krb5 recv_token error return: %s\n", kc->errmsg));
+       amfree(gtok->value);
+       return (-1);
+    case 0:
+       amfree(gtok->value);
+       gtok->length = 0;
+       break;
+    default:
+       break;
+    }
+
+    k5printf(("krb5: recv_token: read %d bytes from %s\n", gtok->length,
+       kc->hostname));
+    return (gtok->length);
+}
+
+#ifdef AMANDA_KRB5_ENCRYPT
+static int
+kencrypt(ks, tok, enctok)
+    struct krb5_stream *ks;
+    gss_buffer_desc *tok, *enctok;
+{
+    int conf_state;
+    OM_uint32 maj_stat, min_stat;
+
+    assert(ks->kc->gss_context != GSS_C_NO_CONTEXT);
+    maj_stat = gss_seal(&min_stat, ks->kc->gss_context, 1,
+       GSS_C_QOP_DEFAULT, tok, &conf_state, enctok);
+    if (maj_stat != GSS_S_COMPLETE || conf_state == 0) {
+       security_stream_seterror(&ks->secstr,
+           "krb5 encryption failed to %s: %s",
+           ks->kc->hostname, gss_error(maj_stat, min_stat));
+       return (-1);
+    }
+    return (0);
+}
+
+static int
+kdecrypt(ks, enctok, tok)
+    struct krb5_stream *ks;
+    gss_buffer_desc *enctok, *tok;
+{
+    OM_uint32 maj_stat, min_stat;
+    int conf_state, qop_state;
+
+    k5printf(("krb5: kdecrypt: decrypting %d bytes\n", enctok->length));
+
+    assert(ks->kc->gss_context != GSS_C_NO_CONTEXT);
+    maj_stat = gss_unseal(&min_stat, ks->kc->gss_context, enctok, tok,
+       &conf_state, &qop_state);
+    if (maj_stat != GSS_S_COMPLETE) {
+       security_stream_seterror(&ks->secstr, "krb5 decrypt error from %s: %s",
+           ks->kc->hostname, gss_error(maj_stat, min_stat));
+       return (-1);
+    }
+    return (0);
+}
+#endif
+
+/*
+ * Writes out the entire iovec
+ */
+static int
+net_writev(fd, iov, iovcnt)
+    int fd, iovcnt;
+    struct iovec *iov;
+{
+    int delta, n, total;
+
+    assert(iov != NULL);
+
+    total = 0;
+    while (iovcnt > 0) {
+       /*
+        * Write the iovec
+        */
+       total += n = writev(fd, iov, iovcnt);
+       if (n < 0)
+           return (-1);
+       if (n == 0) {
+           errno = EIO;
+           return (-1);
+       }
+       /*
+        * Iterate through each iov.  Figure out what we still need
+        * to write out.
+        */
+       for (; n > 0; iovcnt--, iov++) {
+           /* 'delta' is the bytes written from this iovec */
+           delta = n < iov->iov_len ? n : iov->iov_len;
+           /* subtract from the total num bytes written */
+           n -= delta;
+           assert(n >= 0);
+           /* subtract from this iovec */
+           iov->iov_len -= delta;
+           (char *)iov->iov_base += delta;
+           /* if this iovec isn't empty, run the writev again */
+           if (iov->iov_len > 0)
+               break;
+       }
+    }
+    return (total);
+}
+
+/*
+ * Like read(), but waits until the entire buffer has been filled.
+ */
+static ssize_t
+net_read(kc, vbuf, origsize, timeout)
+    struct krb5_conn *kc;
+    void *vbuf;
+    size_t origsize;
+    int timeout;
+{
+    char *buf = vbuf, *off;    /* ptr arith */
+    int nread;
+    size_t size = origsize;
+
+    while (size > 0) {
+       if (kc->readbuf.left == 0) {
+           if (net_read_fillbuf(kc, timeout) < 0)
+               return (-1);
+           if (kc->readbuf.size == 0)
+               return (0);
+       }
+       nread = min(kc->readbuf.left, size);
+       off = kc->readbuf.buf + kc->readbuf.size - kc->readbuf.left;
+       memcpy(buf, off, nread);
+
+       buf += nread;
+       size -= nread;
+       kc->readbuf.left -= nread;
+    }
+    return ((ssize_t)origsize);
+}
+
+/*
+ * net_read likes to do a lot of little reads.  Buffer it.
+ */
+static int
+net_read_fillbuf(kc, timeout)
+    struct krb5_conn *kc;
+    int timeout;
+{
+    fd_set readfds;
+    struct timeval tv;
+
+    FD_ZERO(&readfds);
+    FD_SET(kc->fd, &readfds);
+    tv.tv_sec = timeout;
+    tv.tv_usec = 0;
+    switch (select(kc->fd + 1, &readfds, NULL, NULL, &tv)) {
+    case 0:
+       errno = ETIMEDOUT;
+       /* FALLTHROUGH */
+    case -1:
+       return (-1);
+    case 1:
+       assert(FD_ISSET(kc->fd, &readfds));
+       break;
+    default:
+       assert(0);
+       break;
+    }
+    kc->readbuf.left = 0;
+    kc->readbuf.size = read(kc->fd, kc->readbuf.buf,
+       sizeof(kc->readbuf.buf));
+k5printf(("net_read_fillbuf: read %d characters w/ errno %d\n", kc->readbuf.size, errno));
+    if (kc->readbuf.size < 0)
+       return (-1);
+    kc->readbuf.left = kc->readbuf.size;
+    return (0);
+}
+
+/*
+ * hackish, but you can #undef AMANDA_PRINCIPAL here, and you can both
+ * hardcode a principal in your build and use the .k5amandahosts.  This is
+ * available because sites that run pre-releases of amanda 2.5.0 before 
+ * this feature was there do not behave this way...
+ */
+
+/*#undef AMANDA_PRINCIPAL*/
+
+/*
+ * check ~/.k5amandahosts to see if this principal is allowed in.  If it's
+ * hardcoded, then we don't check the realm
+ */
+static char *
+krb5_checkuser(host, name, realm)
+       char *host, *name, *realm;
+{
+#ifdef AMANDA_PRINCIPAL
+    if(strcmp(name, AMANDA_PRINCIPAL) == 0) {
+       return(NULL);
+    } else {
+       return(vstralloc("does not match compiled in default"));
+    }
+#else
+    struct passwd *pwd;
+    char *ptmp;
+    char *result = "generic error";    /* default is to not permit */
+    FILE *fp = NULL;
+    struct stat sbuf;
+    uid_t localuid;
+    char *line = NULL;
+    char *filehost = NULL, *fileuser = NULL, *filerealm = NULL;
+    char n1[NUM_STR_SIZE];
+    char n2[NUM_STR_SIZE];
+
+    assert( host != NULL);
+    assert( name != NULL);
+
+    if((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
+       result = vstralloc("can not find user ", CLIENT_LOGIN, NULL);
+    }
+    localuid = pwd->pw_uid;
+
+#ifdef USE_AMANDAHOSTS
+    ptmp = stralloc2(pwd->pw_dir, "/.k5amandahosts");
+#else
+    ptmp = stralloc2(pwd->pw_dir, "/.k5login");
+#endif
+
+    if(!ptmp) {
+       result = vstralloc("could not find home directory for ", CLIENT_LOGIN, NULL);
+       goto common_exit;
+   }
+
+   /*
+    * check to see if the ptmp file does nto exist.
+    */
+   if(access(ptmp, R_OK) == -1 && errno == ENOENT) {
+       /*
+        * in this case we check to see if the principal matches
+        * the destination user mimicing the .k5login functionality.
+        */
+        if(strcmp(name, CLIENT_LOGIN) != 0) {
+               result = vstralloc(name, " does not match ",
+                       CLIENT_LOGIN, NULL);
+               goto common_exit;
+       }
+       result = NULL;
+       goto common_exit;
+    }
+
+    k5printf(("opening ptmp: %s\n", (ptmp)?ptmp: "NULL!"));
+    if((fp = fopen(ptmp, "r")) == NULL) {
+       result = vstralloc("can not open ", ptmp, NULL);
+       goto common_exit;
+    }
+    k5printf(("opened ptmp\n"));
+
+    if (fstat(fileno(fp), &sbuf) != 0) {
+       result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL);
+       goto common_exit;
+
+    }
+
+    if (sbuf.st_uid != localuid) {
+       snprintf(n1, sizeof(n1), "%ld", (long) sbuf.st_uid);
+       snprintf(n2, sizeof(n2), "%ld", (long) localuid);
+       result = vstralloc(ptmp, ": ",
+           "owned by id ", n1,
+           ", should be ", n2,
+           NULL);
+       goto common_exit;
+    }
+    if ((sbuf.st_mode & 077) != 0) {
+       result = stralloc2(ptmp,
+           ": incorrect permissions; file must be accessible only by its owner");
+       goto common_exit;
+    }       
+
+    while((line = agets(fp)) != NULL) {
+#if defined(SHOW_SECURITY_DETAIL)                               /* { */
+       k5printf(("%s: processing line: <%s>\n", debug_prefix(NULL), line));
+#endif                                                          /* } */
+       /* if there's more than one column, then it's the host */
+       if( (filehost = strtok(line, " \t")) == NULL) {
+           amfree(line);
+           continue;
+       }
+
+       /*
+        * if there's only one entry, then it's a username and we have
+        * no hostname.  (so the principal is allowed from anywhere.
+        */
+       if((fileuser = strtok(NULL, " \t")) == NULL) {
+           fileuser = filehost;
+           filehost = NULL;
+       }
+
+       if(filehost && strcmp(filehost, host) != 0) {
+           amfree(line);
+           continue;
+       } else {
+               k5printf(("found a host match\n"));
+       }
+
+       if( (filerealm = strchr(fileuser, '@')) != NULL) {
+           *filerealm++ = '\0';
+       }
+
+       /*
+        * we have a match.  We're going to be a little bit insecure
+        * and indicate that the principal is correct but the realm is
+        * not if that's the case.  Technically we should say nothing
+        * and let the user figure it out, but it's helpful for debugging.
+        * You likely only get this far if you've turned on cross-realm auth
+        * anyway...
+        */
+       k5printf(("comparing %s %s\n", fileuser, name));
+       if(strcmp(fileuser, name) == 0) {
+               k5printf(("found a match!\n"));
+               if(realm && filerealm && (strcmp(realm, filerealm)!=0)) {
+                       amfree(line);
+                       continue;
+               }
+               result = NULL;
+               goto common_exit;
+       }
+
+       amfree(line);
+    }
+
+    result = vstralloc("no match in ", ptmp, NULL);
+
+common_exit:
+    if(fp)
+       afclose(fp);
+    if(line)
+       amfree(line);
+    return(result);
+#endif /* AMANDA_PRINCIPAL */
+}
+
+#else
+void krb5_security_dummy (void) {}
+#endif /* KRB5_SECURITY */
index f26fce234f1607dc02ea48cad47712640f26b9f6..fbe0c22007211943a79996c1f6e5d5633b7be971 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: match.c,v 1.10.4.1.4.1.2.4.2.2 2004/12/21 14:20:20 martinea Exp $
+ * $Id: match.c,v 1.21 2005/10/11 01:17:00 vectro Exp $
  *
  * functions for checking and matching regular expressions
  */
@@ -500,9 +500,7 @@ char *glob, *host;
 int match_disk(glob, disk)
 char *glob, *disk;
 {
-    int i;
-    i = match_word(glob, disk, '/');
-    return i;
+    return match_word(glob, disk, '/');
 }
 
 int match_datestamp(dateexp, datestamp)
@@ -565,3 +563,65 @@ char *dateexp, *datestamp;
        }
     }
 }
+
+
+int match_level(levelexp, level)
+char *levelexp, *level;
+{
+    char *dash;
+    size_t len, len_suffix;
+    int len_prefix;
+    char lowend[100], highend[100];
+    char mylevelexp[100];
+    int match_exact;
+
+    if(strlen(levelexp) >= 100 || strlen(levelexp) < 1) {
+       error("Illegal level expression %s",levelexp);
+    }
+   
+    if(levelexp[0] == '^') {
+       strncpy(mylevelexp, levelexp+1, strlen(levelexp)-1); 
+       mylevelexp[strlen(levelexp)-1] = '\0';
+    }
+    else {
+       strncpy(mylevelexp, levelexp, strlen(levelexp));
+       mylevelexp[strlen(levelexp)] = '\0';
+    }
+
+    if(mylevelexp[strlen(mylevelexp)] == '$') {
+       match_exact = 1;
+       mylevelexp[strlen(mylevelexp)] = '\0';
+    }
+    else
+       match_exact = 0;
+
+    if((dash = strchr(mylevelexp,'-'))) {
+       if(match_exact == 1) {
+           error("Illegal level expression %s",levelexp);
+       }
+       len = dash - mylevelexp;
+       len_suffix = strlen(dash) - 1;
+       len_prefix = len - len_suffix;
+
+       if(len_prefix < 0) {
+           error("Illegal level expression %s",levelexp);
+       }
+
+       dash++;
+       strncpy(lowend, mylevelexp, len);
+       lowend[len] = '\0';
+       strncpy(highend, mylevelexp, len_prefix);
+       strncpy(&(highend[len_prefix]), dash, len_suffix);
+       highend[len] = '\0';
+       return ((strncmp(level, lowend, strlen(lowend)) >= 0) &&
+               (strncmp(level, highend , strlen(highend))  <= 0));
+    }
+    else {
+       if(match_exact == 1) {
+           return (strcmp(level, mylevelexp) == 0);
+       }
+       else {
+           return (strncmp(level, mylevelexp, strlen(mylevelexp)) == 0);
+       }
+    }
+}
diff --git a/common-src/packet.c b/common-src/packet.c
new file mode 100644 (file)
index 0000000..32a2d31
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: packet.c,v 1.6 2004/02/13 14:00:35 martinea Exp $
+ *
+ * Routines for modifying the amanda protocol packet type
+ */
+#include "amanda.h"
+#include "arglist.h"
+#include "packet.h"
+
+/*
+ * Table of packet types and their printable forms
+ */
+static const struct {
+    const char name[5];
+    pktype_t type;
+} pktypes[] = {
+    { "REQ", P_REQ },
+    { "REP", P_REP },
+    { "PREP", P_PREP },
+    { "ACK", P_ACK },
+    { "NAK", P_NAK }
+};
+#define        NPKTYPES        (sizeof(pktypes) / sizeof(pktypes[0]))
+
+/*
+ * Initialize a packet
+ */
+printf_arglist_function2(void pkt_init, pkt_t *, pkt, pktype_t, type,
+    const char *, fmt)
+{
+    va_list argp;
+
+    assert(pkt != NULL);
+    assert(strcmp(pkt_type2str(type), "BOGUS") != 0);
+    assert(fmt != NULL);
+
+    pkt->type = type;
+
+    arglist_start(argp, fmt);
+    vsnprintf(pkt->body, sizeof(pkt->body), fmt, argp);
+    arglist_end(argp);
+}
+
+/*
+ * Append data to a packet
+ */
+printf_arglist_function1(void pkt_cat, pkt_t *, pkt, const char *, fmt)
+{
+    size_t len, bufsize;
+    va_list argp;
+
+    assert(pkt != NULL);
+    assert(fmt != NULL);
+
+    len = strlen(pkt->body);
+    assert(len < sizeof(pkt->body));
+
+    bufsize = sizeof(pkt->body) - len;
+    if (bufsize <= 0)
+       return;
+
+    arglist_start(argp, fmt);
+    vsnprintf(pkt->body + len, bufsize, fmt, argp);
+    arglist_end(argp);
+}
+
+/*
+ * Converts a string into a packet type
+ */
+pktype_t
+pkt_str2type(typestr)
+    const char *typestr;
+{
+    int i;
+
+    assert(typestr != NULL);
+
+    for (i = 0; i < NPKTYPES; i++)
+       if (strcmp(typestr, pktypes[i].name) == 0)
+           return (pktypes[i].type);
+    return ((pktype_t)-1);
+}
+
+/*
+ * Converts a packet type into a string
+ */
+const char *
+pkt_type2str(type)
+    pktype_t type;
+{
+    int i;
+
+    for (i = 0; i < NPKTYPES; i++)
+       if (pktypes[i].type == type)
+           return (pktypes[i].name);
+    return ("BOGUS");
+}
diff --git a/common-src/packet.h b/common-src/packet.h
new file mode 100644 (file)
index 0000000..fb12626
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: packet.h,v 1.6 2004/02/13 14:00:35 martinea Exp $
+ *
+ * interfaces for modifying amanda protocol packet type
+ */
+#ifndef PACKET_H
+#define PACKET_H
+
+/*
+ * We limit our body length to 50k.
+ */
+#define        MAX_PACKET      (50*1024)
+
+typedef enum { P_REQ = 0, P_REP = 1, P_PREP = 2, P_ACK = 3, P_NAK = 4 } pktype_t;
+typedef struct {
+    pktype_t type;                             /* type of packet */
+    char body[MAX_PACKET];                     /* body of packet */
+} pkt_t;
+
+/*
+ * Initialize a packet
+ */
+void pkt_init P((pkt_t *, pktype_t, const char *, ...))
+    __attribute__ ((format (printf, 3, 4)));
+
+/*
+ * Append data to a packet
+ */
+void pkt_cat P((pkt_t *, const char *, ...))
+    __attribute__ ((format (printf, 2, 3)));
+
+/*
+ * Convert the packet type to and from a string
+ */
+const char *pkt_type2str P((pktype_t));
+pktype_t pkt_str2type P((const char *));
+
+#endif /* PACKET_H */
index 8a8af5518f6b2a3cfe136cb002a1580288f48644..d960c97803a089b4bbceea7d4cb4f3f3ed5ff7f6 100644 (file)
@@ -5,6 +5,10 @@
 
 char skip_argument[1];
 
+/*
+ * this used to be a function in it's own write but became a wrapper around
+ * pipespawnv to eliminate redundancy...
+ */
 #ifdef STDC_HEADERS
 int pipespawn(char *prog, int pipedef, int *stdinfd, int *stdoutfd,
              int *stderrfd, ...)
@@ -17,165 +21,31 @@ va_dcl
 #endif
 {
     va_list ap;
-    int argc;
+    int argc = 0, pid, i;
     char **argv;
-    int pid, i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
-    char *passwdvar = NULL;
-    int *passwdfd = NULL;
-    char number[NUM_STR_SIZE];
-    char *arg;
-    char *e;
-    int ch;
-    char **env;
-    char **newenv;
 
-    /*
-     * Log the command line and count the args.
-     */
-    dbprintf(("%s: spawning %s in pipeline\n", debug_prefix_time(NULL), prog));
-    dbprintf(("%s: argument list:", debug_prefix(NULL)));
+    /* count args */
     arglist_start(ap, stderrfd);
-    if ((pipedef & PASSWD_PIPE) != 0) {
-       passwdvar = arglist_val(ap, char *);
-       passwdfd = arglist_val(ap, int *);
-    }
-    argc = 0;
-    while((arg = arglist_val(ap, char *)) != NULL) {
-       if (arg == skip_argument) {
-           continue;
-       }
+    while(arglist_val(ap, char *) != NULL) {
        argc++;
-       dbprintf((" "));
-       for(i = 0; (ch = arg[i]) != '\0' && isprint(ch) && ch != ' '; i++) {}
-       if(ch != '\0' || i == 0) {
-           dbprintf(("\""));
-       }
-       dbprintf(("%s", arg));
-       if(ch != '\0' || i == 0) {
-           dbprintf(("\""));
-       }
     }
     arglist_end(ap);
-    dbprintf(("\n"));
 
     /*
-     * Create the pipes
+     * Create the argument vector.
      */
-    if ((pipedef & STDIN_PIPE) != 0) {
-       if(pipe(inpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
-    }
-    if ((pipedef & STDOUT_PIPE) != 0) {
-       if(pipe(outpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
-    }
-    if ((pipedef & STDERR_PIPE) != 0) {
-       if(pipe(errpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
-    }
-    if ((pipedef & PASSWD_PIPE) != 0) {
-       if(pipe(passwdpipe) == -1) {
-           error("error [open pipe to %s: %s]", prog, strerror(errno));
-       }
+    arglist_start(ap, stderrfd);
+    argv = (char **)alloc((argc + 1) * sizeof(*argv));
+    i = 0;
+    while((argv[i] = arglist_val(ap, char *)) != NULL) {
+        if (argv[i] != skip_argument) {
+           i++;
+        }
     }
+    arglist_end(ap);
 
-    /*
-     * Fork and set up the return or run the program.
-     */
-    switch(pid = fork()) {
-    case -1:
-       e = strerror(errno);
-       error("error [fork %s: %s]", prog, e);
-    default:   /* parent process */
-       if ((pipedef & STDIN_PIPE) != 0) {
-           aclose(inpipe[0]);          /* close input side of pipe */
-           *stdinfd = inpipe[1];
-       }
-       if ((pipedef & STDOUT_PIPE) != 0) {
-           aclose(outpipe[1]);         /* close output side of pipe */
-           *stdoutfd = outpipe[0];
-       }
-       if ((pipedef & STDERR_PIPE) != 0) {
-           aclose(errpipe[1]);         /* close output side of pipe */
-           *stderrfd = errpipe[0];
-       }
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           aclose(passwdpipe[0]);      /* close input side of pipe */
-           *passwdfd = passwdpipe[1];
-       }
-       break;
-    case 0:            /* child process */
-       if ((pipedef & STDIN_PIPE) != 0) {
-           aclose(inpipe[1]);          /* close output side of pipe */
-       } else {
-           inpipe[0] = *stdinfd;
-       }
-       if ((pipedef & STDOUT_PIPE) != 0) {
-           aclose(outpipe[0]);         /* close input side of pipe */
-       } else {
-           outpipe[1] = *stdoutfd;
-       }
-       if ((pipedef & STDERR_PIPE) != 0) {
-           aclose(errpipe[0]);         /* close input side of pipe */
-       } else {
-           errpipe[1] = *stderrfd;
-       }
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           aclose(passwdpipe[1]);      /* close output side of pipe */
-       }
-
-       /*
-        * Shift the pipes to the standard file descriptors as requested.
-        */
-       if(dup2(inpipe[0], 0) == -1) {
-           error("error [spawn %s: dup2 in: %s]", prog, strerror(errno));
-       }
-       if(dup2(outpipe[1], 1) == -1) {
-           error("error [spawn %s: dup2 out: %s]", prog, strerror(errno));
-       }
-       if(dup2(errpipe[1], 2) == -1) {
-           error("error [spawn %s: dup2 err: %s]", prog, strerror(errno));
-       }
-
-       /*
-        * Create the argument vector.
-        */
-       arglist_start(ap, stderrfd);
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           passwdvar = arglist_val(ap, char *);
-           passwdfd = arglist_val(ap, int *);
-       }
-       argv = (char **)alloc((argc + 1) * sizeof(*argv));
-       i = 0;
-       while((argv[i] = arglist_val(ap, char *)) != NULL) {
-           if (argv[i] != skip_argument) {
-               i++;
-           }
-       }
-       arglist_end(ap);
-
-       /*
-        * Get the "safe" environment.  If we are sending a password to
-        * the child via a pipe, add the environment variable for that.
-        */
-       env = safe_env();
-       if ((pipedef & PASSWD_PIPE) != 0) {
-           for(i = 0; env[i] != NULL; i++) {}
-           newenv = (char **)alloc((i + 1 + 1) * sizeof(*newenv));
-           ap_snprintf(number, sizeof(number), "%d", passwdpipe[0]);
-           newenv[0] = vstralloc(passwdvar, "=", number, NULL);
-           for(i = 0; (newenv[i + 1] = env[i]) != NULL; i++) {}
-           env = newenv;
-       }
-
-       execve(prog, argv, env);
-       e = strerror(errno);
-       error("error [exec %s: %s]", prog, e);
-       /* NOTREACHED */
-    }
+    pid = pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd, NULL, NULL, argv);
+    amfree(argv);
     return pid;
 }
 
@@ -184,11 +54,21 @@ char *prog;
 int pipedef;
 int *stdinfd, *stdoutfd, *stderrfd;
 char **my_argv;
+{
+    return pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd,
+       NULL, NULL, my_argv);
+}
+
+int pipespawnv_passwd(prog, pipedef, stdinfd, stdoutfd, stderrfd, passwdvar, passwdfd, my_argv)
+char *prog;
+int pipedef;
+int *stdinfd, *stdoutfd, *stderrfd;
+char *passwdvar;
+int *passwdfd;
+char **my_argv;
 {
     int argc;
     int pid, i, inpipe[2], outpipe[2], errpipe[2], passwdpipe[2];
-    char *passwdvar = NULL;
-    int *passwdfd = NULL;
     char number[NUM_STR_SIZE];
     char **arg;
     char *e;
@@ -288,6 +168,9 @@ char **my_argv;
        } else {
            errpipe[1] = *stderrfd;
        }
+        if ((pipedef & PASSWD_PIPE) != 0) { 
+            aclose(passwdpipe[1]);      /* close output side of pipe */
+        }
 
        /*
         * Shift the pipes to the standard file descriptors as requested.
@@ -310,9 +193,10 @@ char **my_argv;
        if ((pipedef & PASSWD_PIPE) != 0) {
            for(i = 0; env[i] != NULL; i++) {}
            newenv = (char **)alloc((i + 1 + 1) * sizeof(*newenv));
-           ap_snprintf(number, sizeof(number), "%d", passwdpipe[0]);
+           snprintf(number, sizeof(number), "%d", passwdpipe[0]);
            newenv[0] = vstralloc(passwdvar, "=", number, NULL);
            for(i = 0; (newenv[i + 1] = env[i]) != NULL; i++) {}
+           amfree(env);
            env = newenv;
        }
 
index 4ef7d662e243699314ddb3f75cc77a435ba2c9ad..4a8a9e954ade9921a387a3a64df3b00f15dca882 100644 (file)
@@ -18,6 +18,10 @@ int pipespawn P((char *prog, int pipedef,
 int pipespawnv P((char *prog, int pipedef,
                  int *stdinfd, int *stdoutfd, int *stderrfd,
                  char **my_argv));
+int pipespawnv_passwd P((char *prog, int pipedef,
+                 int *stdinfd, int *stdoutfd, int *stderrfd,
+                 char *passwdvar, int *passwdfd,
+                 char **my_argv));
 
 
 #endif /* PIPESPAWN_H */
index e7fe14224f699695c926614fdb5e4d8a3d7666e4..4274e70b3a7a50244bbc1be700b4b014417f1cf9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: protocol.c,v 1.27.2.1.6.2.2.2 2004/04/14 13:24:17 martinea Exp $
+ * $Id: protocol.c,v 1.39 2006/02/28 16:36:13 martinea Exp $
  *
  * implements amanda protocol
  */
 #include "amanda.h"
+#include "event.h"
+#include "packet.h"
+#include "security.h"
 #include "protocol.h"
-#include "version.h"
-#ifdef KRB4_SECURITY
-#  include "krb4-security.h"
-#endif
-
-#define ACK_WAIT       10       /* time (secs) to wait for ACK - keep short */
-#define ACK_TRIES       3     /* # times we'll retry after ACK_WAIT timeout */
-#define REQ_TRIES       2   /* # times client can start over (reboot/crash) */
-
-#define DROP_DEAD_TIME (60*60)    /* If no reply in an hour, just forget it */
 
-#define MAX_HANDLES    4096
-#define OFS_DIGITS        3    /* log2(MAX_HANDLES)/4 */
+/*#define      PROTO_DEBUG*/
 
-proto_t *pending_head = NULL;
-proto_t *pending_tail = NULL;
-int pending_qlength = 0;
+/*
+ * Valid actions that can be passed to the state machine
+ */
+typedef enum {
+    A_START, A_TIMEOUT, A_ERROR, A_RCVDATA, A_CONTPEND, A_PENDING,
+    A_CONTINUE, A_FINISH, A_ABORT
+} action_t;
 
-int proto_socket = -1;
-int proto_global_seq = 0;
-#define relseq(s) (s-proto_global_seq)
+/*
+ * The current state type.  States are represented as function
+ * vectors.
+ */
+struct proto;
+typedef action_t (*pstate_t) P((struct proto *, action_t, pkt_t *));
 
-proto_t **proto_handle_table;
-proto_t **proto_next_handle;
-int proto_handles;
+/*
+ * This is a request structure that is wrapped around a packet while it
+ * is being passed through amanda.  It holds the timeouts, state, and handles
+ * for each request.
+ */
+typedef struct proto {
+    pstate_t state;                    /* current state of the request */
+    char *hostname;                    /* remote host */
+    const security_driver_t *security_driver;  /* for connect retries */
+    security_handle_t *security_handle;        /* network stream for this req */
+    time_t timeout;                    /* seconds for this timeout */
+    time_t repwait;                    /* seconds to wait for reply */
+    time_t origtime;                   /* orig start time of this request */
+    time_t curtime;                    /* time when this attempt started */
+    int connecttries;                  /* times we'll retry a connect */
+    int reqtries;                      /* times we'll resend a REQ */
+    int acktries;                      /* times we'll wait for an a ACK */
+    pkt_t req;                         /* the actual wire request */
+    protocol_sendreq_callback continuation; /* call when req dies/finishes */
+    void *datap;                       /* opaque cookie passed to above */
+    char *(*conf_fn) P((char *, void *));/* configuration function */
+} proto_t;
+
+#define        CONNECT_TRIES   3       /* num retries after connect errors */
+#define        CONNECT_WAIT    5       /* secs between connect attempts */
+#define ACK_WAIT       10      /* time (secs) to wait for ACK - keep short */
+#define ACK_TRIES      3       /* num retries after ACK_WAIT timeout */
+#define REQ_TRIES      2       /* num restarts (reboot/crash) */
+#define CURTIME        (time(0) - proto_init_time) /* time relative to start */
+
+/* if no reply in an hour, just forget it */
+#define        DROP_DEAD_TIME(t)       (CURTIME - (t) > (60 * 60))
+
+/* get the size of an array */
+#define        ASIZE(arr)      (sizeof(arr) / sizeof((arr)[0]))
 
-time_t proto_init_time;
-#define CURTIME        (time(0)-proto_init_time)
+/*
+ * Initialization time
+ */
+static time_t proto_init_time;
 
 /* local functions */
-static char *prnpstate P((pstate_t s));
-static char *prnaction P((action_t s));
-#ifdef PROTO_DEBUG
-static char *prnpktype P((pktype_t s));
-#endif
-static void pending_enqueue P((proto_t *newp));
-static proto_t *pending_dequeue P((void));
-static void pending_remove P((proto_t *p));
-static void alloc_handle P((proto_t *p));
-static void free_handle P((proto_t *p));
-static void hex P((char *str, int digits, unsigned int v));
-static int unhex P((char *str, int digits));
-static proto_t *handle2ptr P((char *str));
-static char *ptr2handle P((proto_t *p));
-static void eat_string P((dgram_t *msg, char *str));
-static int parse_integer P((dgram_t *msg));
-static char *parse_string P((dgram_t *msg));
-static char *parse_line P((dgram_t *msg));
-void parse_pkt_header P((pkt_t *pkt));
-static void setup_dgram P((proto_t *p, dgram_t *msg, 
-                          char *security, char *typestr));
-static void send_req P((proto_t *p));
-static void send_ack P((proto_t *p));
-static void send_ack_repl P((pkt_t *pkt));
-static void state_machine P((proto_t *p, action_t action, pkt_t *pkt));
-static void add_bsd_security P((proto_t *p));
-static int select_til P((time_t waketime));
-static int packet_arrived P((void));
-static void handle_incoming_packet P((void)); 
-
-
-/* -------------- */
-
-
-static char *prnpstate(s)
-pstate_t s;
-{
-    static char str[80];
-
-    switch(s) {
-    case S_BOGUS: return "S_BOGUS";
-    case S_STARTUP:  return "S_STARTUP";
-    case S_SENDREQ:  return "S_SENDREQ";
-    case S_ACKWAIT:  return "S_ACKWAIT";
-    case S_REPWAIT:  return "S_REPWAIT";
-    case S_SUCCEEDED:  return "S_SUCCEEDED";
-    case S_FAILED: return "S_FAILED";
-    default:
-       ap_snprintf(str, sizeof(str), "<bad state %d>", s);
-       return str;
-    }
-}
-
-static char *prnaction(s)
-action_t s;
-{
-    static char str[80];
-
-    switch(s) {
-    case A_BOGUS:  return "A_BOGUS";
-    case A_START:  return "A_START";
-    case A_TIMEOUT:  return "A_TIMEOUT";
-    case A_RCVDATA: return "A_RCVDATA";
-    default:
-       ap_snprintf(str, sizeof(str), "<bad action %d>", s);
-       return str;
-    }
-}
 
 #ifdef PROTO_DEBUG
-
-static char *prnpktype(s)
-pktype_t s;
-{
-    static char str[80];
-
-    switch(s) {
-    case P_BOGUS: return "P_BOGUS";
-    case P_REQ: return "P_REQ";
-    case P_REP: return "P_REP";
-    case P_PREP: return "P_PREP";
-    case P_ACK: return "P_ACK";
-    case P_NAK: return "P_NAK";
-    default:
-       ap_snprintf(str, sizeof(str), "<bad pktype %d>", s);
-       return str;
-    }
-}
-
+static const char *action2str P((action_t));
+static const char *pstate2str P((pstate_t));
 #endif
 
+static void connect_callback P((void *, security_handle_t *,
+    security_status_t));
+static void connect_wait_callback P((void *));
+static void recvpkt_callback P((void *, pkt_t *, security_status_t));
 
-void proto_init(socket, startseq, handles)
-int socket, startseq, handles;
-{
-    int i;
-
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: proto_init(socket %d, startseq %d, handles %d)\n",
-             debug_prefix_time(": protocol"),
-             socket,
-             startseq,
-             handles));
-#endif
-    if(socket < 0 || socket >= FD_SETSIZE) {
-       error("proto_init: socket %d out of range (0 .. %d)\n",
-             socket, FD_SETSIZE-1);
-    }
-    proto_socket = socket;
-    proto_global_seq = startseq;
-    proto_handles = handles;
-
-    proto_handle_table = alloc(proto_handles * sizeof(proto_t *));
-    malloc_mark(proto_handle_table);
-    proto_next_handle = proto_handle_table;
-    for(i = 0; i < proto_handles; i++)
-       proto_handle_table[i] = NULL;
-    proto_init_time = time(0);
-}
+static action_t s_sendreq P((proto_t *, action_t, pkt_t *));
+static action_t s_ackwait P((proto_t *, action_t, pkt_t *));
+static action_t s_repwait P((proto_t *, action_t, pkt_t *));
+static void state_machine P((proto_t *, action_t, pkt_t *));
 
+/*
+ * -------------------
+ * Interface functions
+ */
 
-static void pending_enqueue(newp)
-proto_t *newp;
+/*
+ * Initialize globals.
+ */
+void
+protocol_init()
 {
-    proto_t *curp;
-
-    /* common case shortcut: check if adding to end of list */
-
-    if(pending_tail && pending_tail->timeout <= newp->timeout)
-       curp = NULL;
-    else {
-       /* scan list for insert-sort */
-       curp = pending_head;
-       while(curp && curp->timeout <= newp->timeout)
-           curp = curp->next;
-    }
 
-    newp->next = curp;
-    if(curp) {
-       newp->prev = curp->prev;
-       curp->prev = newp;
-    }
-    else {
-       newp->prev = pending_tail;
-       pending_tail = newp;
-    }
-
-    if(newp->prev) newp->prev->next = newp;
-    else pending_head = newp;
-
-    pending_qlength++;
+    proto_init_time = time(NULL);
 }
 
-static proto_t *pending_dequeue()
+/*
+ * Generate a request packet, and submit it to the state machine
+ * for transmission.
+ */
+void
+protocol_sendreq(hostname, security_driver, conf_fn, req, repwait, continuation, datap)
+    const char *hostname;
+    const security_driver_t *security_driver;
+    char *(*conf_fn) P((char *, void *));
+    const char *req;
+    time_t repwait;
+    protocol_sendreq_callback continuation;
+    void *datap;
 {
     proto_t *p;
 
-    p = pending_head;
-    if(p) {
-       pending_head = p->next;
-       p->next = NULL;
-       if(pending_head) 
-           pending_head->prev = NULL;
-       else
-           pending_tail = NULL;
-       pending_qlength--;
-    }
-
-    return p;
-}
-
-static void pending_remove(p)
-proto_t *p;
-{
-    if(p->next) p->next->prev = p->prev;
-    else pending_tail = p->prev;
+    p = alloc(sizeof(proto_t));
+    p->state = s_sendreq;
+    p->hostname = stralloc(hostname);
+    p->security_driver = security_driver;
+    /* p->security_handle set in connect_callback */
+    p->repwait = repwait;
+    p->origtime = CURTIME;
+    /* p->curtime set in the sendreq state */
+    p->connecttries = CONNECT_TRIES;
+    p->reqtries = REQ_TRIES;
+    p->acktries = ACK_TRIES;
+    p->conf_fn = conf_fn;
+    pkt_init(&p->req, P_REQ, req);
+
+    /*
+     * These are here for the caller
+     * We call the continuation function after processing is complete.
+     * We pass the datap on through untouched.  It is here so the caller
+     * has a way to keep state with each request.
+     */
+    p->continuation = continuation;
+    p->datap = datap;
 
-    if(p->prev) p->prev->next = p->next;
-    else pending_head = p->next;
+#ifdef PROTO_DEBUG
+    dbprintf(("%s: security_connect: host %s -> p %X\n", 
+             debug_prefix_time(": protocol"), hostname, (int)p));
+#endif
 
-    p->prev = p->next = NULL;
-    pending_qlength--;
+    security_connect(p->security_driver, p->hostname, conf_fn, connect_callback, p);
 }
 
-/* -------- */
-
-#define PTR_CHARS    sizeof(proto_t *)             /* chars in a pointer */
-#define CHAR_DIGITS  2                             /* hex digits in a char */
-#define HANDLE_CHARS (OFS_DIGITS+1+PTR_CHARS*CHAR_DIGITS) /* "xxx-yyyyyyyy" */
-union handle_u {
-    unsigned char c[PTR_CHARS];
-    proto_t *p;
-} hu;
-
-static void alloc_handle(p)
-proto_t *p;
-{
-    int i;
-    proto_t **hp;
-
-    hp = proto_next_handle;
-    for(i = 0; i < proto_handles; i++) {
-       if(*hp == NULL) break;
-       hp++;
-       if(hp >= proto_handle_table + proto_handles)
-           hp = proto_handle_table;
-    }
-    if(i == proto_handles)
-       error("protocol out of handles");
-    p->handleofs = hp-proto_handle_table;
-    *hp = p;
-}
-
-static void free_handle(p)
-proto_t *p;
+/*
+ * This is a callback for security_connect.  After the security layer
+ * has initiated a connection to the given host, this will be called
+ * with a security_handle_t.
+ *
+ * On error, the security_status_t arg will reflect errors which can
+ * be had via security_geterror on the handle.
+ */
+static void
+connect_callback(cookie, security_handle, status)
+    void *cookie;
+    security_handle_t *security_handle;
+    security_status_t status;
 {
-    if(proto_handle_table[p->handleofs] == p)
-       proto_handle_table[p->handleofs] = NULL;
-    p->handleofs = -1;
-}
+    proto_t *p = cookie;
 
-static void hex(str, digits, v)
-char *str;
-int digits;
-unsigned int v;
-{
-    str = str + digits - 1;
+    assert(p != NULL);
+    p->security_handle = security_handle;
 
-    while(digits--) {
-       *str-- = "0123456789ABCDEF"[v % 16];
-       v /= 16;
-    }
-}
+#ifdef PROTO_DEBUG
+    dbprintf(("%s: connect_callback: p %X\n",
+             debug_prefix_time(": protocol"), (int)p));
+#endif
 
-static int unhex(str, digits)
-char *str;
-int digits;
-{
-    int d, v = 0;
+    switch (status) {
+    case S_OK:
+       state_machine(p, A_START, NULL);
+       break;
+
+    case S_TIMEOUT:
+       security_seterror(p->security_handle, "timeout during connect");
+       /* FALLTHROUGH */
+
+    case S_ERROR:
+       /*
+        * For timeouts or errors, retry a few times, waiting CONNECT_WAIT
+        * seconds between each attempt.  If they all fail, just return
+        * an error back to the caller.
+        */
+       if (--p->connecttries == 0) {
+           state_machine(p, A_ABORT, NULL);
+       } else {
+#ifdef PROTO_DEBUG
+    dbprintf(("%s: connect_callback: p %X: retrying %s\n",
+             debug_prefix_time(": protocol"), (int)p, p->hostname));
+#endif
+           security_close(p->security_handle);
+           /* XXX overload p->security handle to hold the event handle */
+           p->security_handle =
+               (security_handle_t *)event_register(CONNECT_WAIT, EV_TIME,
+               connect_wait_callback, p);
+       }
+       break;
 
-    while(*str && digits--) {
-       d = *str >= 'A'? *str - 'A' + 10 : *str - '0';
-       v = v * 16 + d;
-       str++;
+    default:
+       assert(0);
+       break;
     }
-    return v;
 }
 
-
-static proto_t *handle2ptr(str)
-char *str;
+/*
+ * This gets called when a host has been put on a wait queue because
+ * initial connection attempts failed.
+ */
+static void
+connect_wait_callback(cookie)
+    void *cookie;
 {
-    int ofs, i;
-
-    if(strlen(str) != HANDLE_CHARS)
-       return NULL;
-
-    ofs = unhex(str, OFS_DIGITS);
-    str += OFS_DIGITS;
-    if(ofs < 0 || ofs >= proto_handles)
-       return NULL;
+    proto_t *p = cookie;
 
-    if(*str++ != '-')
-       return NULL;
-
-    for(i=0; i < PTR_CHARS; i++) {
-       hu.c[i] = unhex(str, CHAR_DIGITS);
-       str += CHAR_DIGITS;
-    }
-
-    if(proto_handle_table[ofs] != hu.p)
-       return NULL;
-
-    return hu.p;
+    event_release((event_handle_t *)p->security_handle);
+    security_connect(p->security_driver, p->hostname, p->conf_fn,
+       connect_callback, p);
 }
 
 
-static char *ptr2handle(p)
-proto_t *p;
+/*
+ * Does a one pass protocol sweep.  Handles any incoming packets that 
+ * are waiting to be processed, and then deals with any pending
+ * requests that have timed out.
+ *
+ * Callers should periodically call this after they have submitted
+ * requests if they plan on doing a lot of work.
+ */
+void
+protocol_check()
 {
-    int i;
-    char *s;
-    static char hstr[HANDLE_CHARS+1];
-
-    assert(p->handleofs != -1 && proto_handle_table[p->handleofs] == p);
-
-    hu.p = p;
 
-    hex(hstr, OFS_DIGITS, p->handleofs);
-    s = &hstr[OFS_DIGITS];
-    *s++ = '-';
-
-    for(i=0;i<PTR_CHARS;i++) {
-       hex(s, CHAR_DIGITS, hu.c[i]);
-       s += CHAR_DIGITS;
-    }
-    *s = '\0';
-    return hstr;
+    /* arg == 1 means don't block */
+    event_loop(1);
 }
 
-/* -------- */
 
-jmp_buf parse_failed;
-char *parse_errmsg = NULL;
-
-static void eat_string(msg, str)
-dgram_t *msg;
-char *str;
-{
-    char *saved_str, *saved_msg;
-
-    /* eat leading whitespace */
-    while(isspace((int)(*msg->cur))) msg->cur++;
-
-    saved_msg = msg->cur;
-    saved_str = str;
-
-    /* eat any characters that match str */
-    while(*str && *msg->cur++ == *str++);
-
-    /* if we didn't eat all of str, we've failed */
-    if(*str) {
-       int len = strlen(saved_str);
-       char *tmp = NULL;
-       
-       tmp = alloc(len+1);
-       strncpy(tmp, saved_msg, len);
-       tmp[len] = '\0';
-       parse_errmsg = newvstralloc(parse_errmsg,
-                                   "expected \"", saved_str, "\",",
-                                   " got \"", tmp, "\"",
-                                   NULL);
-       amfree(tmp);
-       longjmp(parse_failed,1);
-    }
-}
-
-static int parse_integer(msg)
-dgram_t *msg;
+/*
+ * Does an infinite pass protocol sweep.  This doesn't return until all
+ * requests have been satisfied or have timed out.
+ *
+ * Callers should call this after they have finished submitting requests
+ * and are just waiting for all of the answers to come back.
+ */
+void
+protocol_run()
 {
-    int i = 0;
-    int sign = 1;
-
-    /* eat leading whitespace */
-    while(isspace((int)(*msg->cur))) msg->cur++;
-
-    /* handle negative values */
-    if(*msg->cur == '-') {
-       sign = -1;
-       msg->cur++;
-    }
 
-    /* must have at least one digit */
-    if(*msg->cur < '0' || *msg->cur > '9') {
-       char non_digit[2];
-
-       non_digit[0] = *msg->cur;
-       non_digit[1] = '\0';
-       parse_errmsg = newvstralloc(parse_errmsg,
-                                   "expected digit, got \"", non_digit, "\"",
-                                   NULL);
-       longjmp(parse_failed,1);
-    }
-
-    while(*msg->cur >= '0' && *msg->cur <= '9') {
-       i = i * 10 + (*msg->cur - '0');
-       msg->cur++;
-    }
-    return sign * i;
+    /* arg == 0 means block forever until no more events are left */
+    event_loop(0);
 }
 
-static char *parse_string(msg)
-dgram_t *msg;
-{
-    char *str;
-
-    /* eat leading whitespace */
-    while(isspace((int)(*msg->cur))) msg->cur++;
-
-    /* mark start of string */
-    str = msg->cur;
-
-    /* stop at whitespace (including newlines) or end-of-packet */
-    while(*msg->cur && !isspace((int)(*msg->cur))) msg->cur++;
 
-    /* empty fields not allowed */
-    if(msg->cur == str) {
-       parse_errmsg = newstralloc(parse_errmsg,
-                                  "expected string, got empty field");
-       longjmp(parse_failed,1);
-    }
-
-    /* mark end of string in the packet, but don't fall off the end of it */
-    if(*msg->cur) *msg->cur++ = '\0';
-
-    return str;
-}
-
-static char *parse_line(msg)
-dgram_t *msg;
-{
-    char *str;
-
-    /* eat leading whitespace */
-    while(isspace((int)(*msg->cur))) msg->cur++;
-
-    /* mark start of string */
-    str = msg->cur;
-
-    /* stop at end of line or end-of-packet */
-    while(*msg->cur && *msg->cur != '\n') msg->cur++;
-
-    /* empty fields not allowed */
-    if(msg->cur == str) {
-       parse_errmsg = newstralloc(parse_errmsg,
-                                  "expected string, got empty field");
-       longjmp(parse_failed,1);
-    }
-
-    /* mark end of string in the packet, but don't fall off the end of it */
-    if(*msg->cur) *msg->cur++ = '\0';
-
-    return str;
-}
+/*
+ * ------------------
+ * Internal functions
+ */
 
-void parse_pkt_header(pkt)
-pkt_t *pkt;
+/*
+ * The guts of the protocol.  This handles the many paths a request can
+ * make, including retrying the request and acknowledgements, and dealing
+ * with timeouts and successfull replies.
+ */
+static void
+state_machine(p, action, pkt)
+    proto_t *p;
+    action_t action;
+    pkt_t *pkt;
 {
-    dgram_t *msg;
-    char *typestr;
-
-    if(setjmp(parse_failed)) {
-/*     dbprintf(("%s: leftover:\n----\n%s----\n\n", errmsg, msg->cur)); */
-       pkt->type = P_BOGUS;
-       return;
-    }
-
-    msg = &pkt->dgram;
+    pstate_t curstate;
+    action_t retaction;
 
 #ifdef PROTO_DEBUG
-    dbprintf(("%s: parsing packet:\n-------\n%s-------\n\n",
-             debug_prefix_time(": protocol"),
-             msg->cur));
+       dbprintf(("%s: state_machine: initial: p %X action %s pkt %X\n",
+               debug_prefix_time(": protocol"),
+               (int)p, action2str(action), NULL));
 #endif
 
-    eat_string(msg, "Amanda");     pkt->version_major = parse_integer(msg);
-    eat_string(msg, ".");          pkt->version_minor = parse_integer(msg);
-    typestr = parse_string(msg);
-
-    if(strcmp(typestr, "REQ") == 0) pkt->type = P_REQ;
-    else if(strcmp(typestr, "REP") == 0) pkt->type = P_REP;
-    else if(strcmp(typestr, "PREP") == 0) pkt->type = P_PREP;
-    else if(strcmp(typestr, "ACK") == 0) pkt->type = P_ACK;
-    else if(strcmp(typestr, "NAK") == 0) pkt->type = P_NAK;
-    else pkt->type = P_BOGUS;
-
-    eat_string(msg, "HANDLE");     pkt->handle = parse_string(msg);
-    eat_string(msg, "SEQ");        pkt->sequence = parse_integer(msg);
-
-    eat_string(msg, "");
-#define sc "SECURITY "
-    if(strncmp(msg->cur, sc, sizeof(sc)-1) == 0) {
-       /* got security tag */
-       eat_string(msg, sc);
-#undef sc
-       pkt->security = parse_line(msg);
-    }
-    else pkt->security = NULL;
-
-    if(pkt->type == P_REQ) {
+    assert(p != NULL);
+    assert(action == A_RCVDATA || pkt == NULL);
+    assert(p->state != NULL);
 
-#ifdef KRB4_SECURITY
-        eat_string(msg, "");
-        pkt->cksum = kerberos_cksum(msg->cur);
+    for (;;) {
 #ifdef PROTO_DEBUG
-        dbprintf(("%s: parse_pkt/cksum %ld over \'%s\'\n\n",
+       dbprintf(("%s: state_machine: p %X state %s action %s\n",
                  debug_prefix_time(": protocol"),
-                 pkt->cksum,
-                 msg->cur)); 
-#endif
-        fflush(stdout);
-#endif
-       eat_string(msg, "SERVICE");     pkt->service = parse_string(msg);
-    }
-
-    eat_string(msg, "");
-    pkt->body = msg->cur;
-}
-
-static void setup_dgram(p, msg, security, typestr)
-proto_t *p;
-dgram_t *msg;
-char *security, *typestr;
-{
-    char *linebuf = NULL;
-    char major_str[NUM_STR_SIZE];
-    char minor_str[NUM_STR_SIZE];
-    char seq_str[NUM_STR_SIZE];
-
-    ap_snprintf(major_str, sizeof(major_str), "%d", VERSION_MAJOR);
-    ap_snprintf(minor_str, sizeof(minor_str), "%d", VERSION_MINOR);
-    ap_snprintf(seq_str, sizeof(seq_str), "%d", p->curseq);
-
-    dgram_zero(msg);
-    dgram_socket(msg,proto_socket);
-    linebuf = vstralloc("Amanda ", major_str, ".", minor_str,
-                       " ", typestr,
-                       " HANDLE ", ptr2handle(p),
-                       " SEQ ", seq_str,
-                       "\n",
-                       security ? security : "",
-                       security ? "\n" : "",
-                       NULL);
-    dgram_cat(msg, linebuf);
-    amfree(linebuf);
-}
-
-static void send_req(p)
-proto_t *p;
-{
-    dgram_t outmsg;
-
-    setup_dgram(p, &outmsg, p->security, "REQ");
-    dgram_cat(&outmsg, p->req);
-
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: send_req: len %d: packet:\n----\n%s----\n\n", 
-             debug_prefix_time(": protocol"),
-             outmsg.len,
-             outmsg.data));
-#endif
-
-    if(dgram_send_addr(p->peer, &outmsg))
-       fprintf(stderr,"send req failed: %s\n", strerror(errno));
-}
-
-static void send_ack(p)
-proto_t *p;
-{
-    dgram_t outmsg;
-
-    setup_dgram(p, &outmsg, NULL, "ACK");
-
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: send_ack: len %d: packet:\n----\n%s----\n\n", 
-             debug_prefix_time(": protocol"),
-             outmsg.len,
-             outmsg.data));
+                 (int)p, pstate2str(p->state), action2str(action)));
+       if (pkt != NULL) {
+           dbprintf(("%s: pkt: %s (t %d) orig REQ (t %d cur %d)\n",
+                     debug_prefix(": protocol"),
+                     pkt_type2str(pkt->type), (int)CURTIME,
+                     (int)p->origtime, (int)p->curtime));
+           dbprintf(("%s: pkt contents:\n-----\n%s-----\n",
+                     debug_prefix(": protocol"), pkt->body));
+       }
 #endif
 
-    if(dgram_send_addr(p->peer, &outmsg))
-       error("send ack failed: %s", strerror(errno));
-}
-
-static void send_ack_repl(pkt)
-pkt_t *pkt;
-{
-    dgram_t outmsg;
-    char *linebuf = NULL;
-    char major_str[NUM_STR_SIZE];
-    char minor_str[NUM_STR_SIZE];
-    char seq_str[NUM_STR_SIZE];
-
-    ap_snprintf(major_str, sizeof(major_str), "%d", VERSION_MAJOR);
-    ap_snprintf(minor_str, sizeof(minor_str), "%d", VERSION_MINOR);
-    ap_snprintf(seq_str, sizeof(seq_str), "%d", pkt->sequence);
-
-    dgram_zero(&outmsg);
-    dgram_socket(&outmsg,proto_socket);
-
-    linebuf = vstralloc("Amanda ", major_str, ".", minor_str,
-                       " ACK HANDLE ", pkt->handle,
-                       " SEQ ", seq_str,
-                       "\n", NULL);
-
-    dgram_cat(&outmsg, linebuf);
-    amfree(linebuf);
+       /*
+        * p->state is a function pointer to the current state a request
+        * is in.
+        *
+        * We keep track of the last state we were in so we can make
+        * sure states which return A_CONTINUE really have transitioned
+        * the request to a new state.
+        */
+       curstate = p->state;
+
+       if (action == A_ABORT)
+           /*
+            * If the passed action indicates a terminal error, then we
+            * need to move to abort right away.
+            */
+           retaction = A_ABORT;
+       else
+           /*
+            * Else we run the state and perform the action it
+            * requests.
+            */
+           retaction = (*curstate)(p, action, pkt);
 
 #ifdef PROTO_DEBUG
-    dbprintf(("%s: send_ack_repl: len %d: packet:\n----\n%s----\n\n", 
-             debug_prefix_time(": protocol"),
-             outmsg.len,
-             outmsg.data));
+       dbprintf(("%s: state_machine: p %X state %s returned %s\n",
+                 debug_prefix_time(": protocol"),
+                 (int)p, pstate2str(p->state), action2str(retaction)));
 #endif
 
-    if(dgram_send_addr(pkt->peer, &outmsg))
-       error("send ack failed: %s", strerror(errno));
-}
-
-
-static void state_machine(p, action, pkt)
-proto_t *p;
-action_t action;
-pkt_t *pkt;
-{
-
+       /*
+        * The state function is expected to return one of the following
+        * action_t's.
+        */
+       switch (retaction) {
+
+       /*
+        * Request is still waiting for more data off of the network.
+        * Setup to receive another pkt, and wait for the recv event
+        * to occur.
+        */
+       case A_CONTPEND:
+           (*p->continuation)(p->datap, pkt, p->security_handle);
+           /* FALLTHROUGH */
+
+       case A_PENDING:
 #ifdef PROTO_DEBUG
-    dbprintf(("%s: state_machine: p %X state %s action %s%s%s\n",
-             debug_prefix_time(": protocol"),
-             (int)p,
-             prnpstate(p->state),
-             prnaction(action),
-             pkt == NULL? "" : " pktype ",
-             pkt == NULL? "" : prnpktype(pkt->type)));
+           dbprintf(("%s: state_machine: p %X state %s: timeout %d\n",
+                     debug_prefix_time(": protocol"),
+                     (int)p, pstate2str(p->state), (int)p->timeout));
 #endif
+           /*
+            * Get the security layer to register a receive event for this
+            * security handle on our behalf.  Have it timeout in p->timeout
+            * seconds.
+            */
+           security_recvpkt(p->security_handle, recvpkt_callback, p,
+               p->timeout);
 
-    while(1) {
-       p->prevstate = p->state;
-       switch(p->state) {
-       case S_STARTUP: 
-           if(action != A_START) goto badaction;
-           p->origseq = p->curseq = proto_global_seq++;
-           p->reqtries = REQ_TRIES;
-           p->state = S_SENDREQ;
-           p->acktries = ACK_TRIES;
-           alloc_handle(p);
-           break;
-
-       case S_SENDREQ:
-           send_req(p);
-           p->curtime = CURTIME;
-           if(p->curseq == p->origseq) p->origtime = p->curtime;
-           p->timeout = time(0) + ACK_WAIT;
-           p->state = S_ACKWAIT;
-           pending_enqueue(p);
            return;
 
-       case S_ACKWAIT:
-           if(action == A_TIMEOUT) {
-               if(--p->acktries == 0) {
-                   p->state = S_FAILED;
-                   free_handle(p);
-                   p->continuation(p, NULL);
-                   amfree(p->req);
-                   amfree(p->security);
-                   amfree(p);
-                   return;
-               }
-               else {
-                   p->state = S_SENDREQ;
-                   break;
-               }
-           }
-           else if(action != A_RCVDATA)
-               goto badaction;
-
-           /* got the packet with the right handle, now check it */
-
+       /*
+        * Request has moved to another state.  Loop and run it again.
+        */
+       case A_CONTINUE:
+           assert(p->state != curstate);
 #ifdef PROTO_DEBUG
-           dbprintf((
-         "%s: RESPTIME p %X pkt %s (t %d s %d) orig (t %d s %d) cur (t %d s %d)\n",
-                   debug_prefix_time(": protocol"),
-                   (int)p, prnpktype(pkt->type), 
-                   (int)CURTIME, relseq(pkt->sequence),
-                   (int)p->origtime, relseq(p->origseq), 
-                   (int)p->curtime, relseq(p->curseq)));
+           dbprintf(("%s: state_machine: p %X: moved from %s to %s\n",
+                     debug_prefix_time(": protocol"),
+                     (unsigned int)p, pstate2str(curstate),
+                     pstate2str(p->state)));
 #endif
-
-           if(pkt->type == P_ACK) {
-               if(pkt->sequence != p->origseq)
-                   p->reqtries--;
-               p->state = S_REPWAIT;
-               p->timeout = time(0) + p->repwait;
-               pending_enqueue(p);
-               return;
-           }
-           else if(pkt->type == P_NAK) {
-               p->state = S_FAILED;
-               free_handle(p);
-               p->continuation(p, pkt);
-               amfree(p->req);
-               amfree(p->security);
-               amfree(p);
-               return;
-           }
-           else if(pkt->type == P_REP) {
-               /* no ack, just rep */
-               p->state = S_REPWAIT;
-               break;
-           }
-           else if(pkt->type == P_PREP) {
-               /* no ack, just rep */
-               p->state = S_REPWAIT;
-               break;
-           }
-           /* else unexpected packet, put back on queue */
-           pending_enqueue(p);
+           continue;
+
+       /*
+        * Request has failed in some way locally.  The security_handle will
+        * contain an appropriate error message via security_geterror().  Set
+        * pkt to NULL to indicate failure to the callback, and then
+        * fall through to the common finish code.
+        *
+        * Note that remote failures finish via A_FINISH, because they did
+        * complete successfully locally.
+        */
+       case A_ABORT:
+           pkt = NULL;
+           /* FALLTHROUGH */
+
+       /*
+        * Request has completed successfully.
+        * Free up resources the request has used, call the continuation
+        * function specified by the caller and quit.
+        */
+       case A_FINISH:
+           (*p->continuation)(p->datap, pkt, p->security_handle);
+           security_close(p->security_handle);
+           amfree(p->hostname);
+           amfree(p);
            return;
 
-       case S_REPWAIT:
-           if(action == A_TIMEOUT) {
-               if(p->reqtries == 0 || 
-                  (CURTIME - p->origtime > DROP_DEAD_TIME)) {
-                   p->state = S_FAILED;
-                   free_handle(p);
-                   p->continuation(p, NULL);
-                   amfree(p->req);
-                   amfree(p->security);
-                   amfree(p);
-                   return;
-               }
-               else {
-                   p->reqtries--;
-                   p->state = S_SENDREQ;
-                   p->acktries = ACK_TRIES;
-                   break;
-               }
-           }
-           else if(action != A_RCVDATA)
-               goto badaction;
-           /* got the packet with the right handle, now check it */
-           if(pkt->type != P_REP && pkt->type != P_PREP) {
-               pending_enqueue(p);
-               return;
-           }
-           if(pkt->type == P_REP) {
-               send_ack(p);
-               p->state = S_SUCCEEDED;
-               free_handle(p);
-               p->continuation(p, pkt);
-               amfree(p->req);
-               amfree(p->security);
-               amfree(p);
-               return;
-           }
-           else if(pkt->type == P_PREP) {
-               p->state = S_REPWAIT;
-               p->continuation(p, pkt);
-               pending_enqueue(p);
-               return;
-           }
-
        default:
-       badaction:
-           error("protocol error: no handler for state %s action %s\n",
-                 prnpstate(p->state), prnaction(action));
+           assert(0);
+           break;      /* in case asserts are turned off */
        }
+       /* NOTREACHED */
     }
+    /* NOTREACHED */
 }
 
-static void add_bsd_security(p)
-proto_t *p;
-{
-    p->security = get_bsd_security();
-}
-
-int make_request(hostname, port, req, datap, repwait, continuation)
-char *hostname;
-int port;
-char *req;
-void *datap;
-time_t repwait;
-void (*continuation) P((proto_t *p, pkt_t *pkt));
-{
+/*
+ * The request send state.  Here, the packet is actually transmitted
+ * across the network.  After setting up timeouts, the request
+ * moves to the acknowledgement wait state.  We return from the state
+ * machine at this point, and let the request be received from the network.
+ */
+static action_t
+s_sendreq(p, action, pkt)
     proto_t *p;
-    struct hostent *hp;
-
-
-    p = alloc(sizeof(proto_t));
-    p->state = S_STARTUP;
-    p->prevstate = S_STARTUP;
-    p->continuation = continuation;
-    p->req = req;
-    p->repwait = repwait;
-    p->datap = datap;
-
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: make_request: host %s -> p %X\n", 
-             debug_prefix_time(": protocol"),
-             hostname,
-             (int)p));
-#endif
-
-    if((hp = gethostbyname(hostname)) == 0) return -1;
-    memcpy(&p->peer.sin_addr, hp->h_addr, hp->h_length);
-    p->peer.sin_family = AF_INET;
-    p->peer.sin_port = htons(port);
-
-    add_bsd_security(p);
-
-    state_machine(p, A_START, NULL);
-    return 0;
-}
-
-#ifdef KRB4_SECURITY
+    action_t action;
+    pkt_t *pkt;
+{
 
-static int add_krb_security P((proto_t *p, char *host_inst, char *realm));
+    assert(p != NULL);
 
-static int add_krb_security(p, host_inst, realm)
-proto_t *p;
-char *host_inst, *realm;
-{
-    p->security = get_krb_security(p->req, host_inst, realm, &p->auth_cksum);
+    if (security_sendpkt(p->security_handle, &p->req) < 0) {
+       /* XXX should retry */
+       security_seterror(p->security_handle, "error sending REQ: %s",
+           security_geterror(p->security_handle));
+       return (A_ABORT);
+    }
 
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: add_krb_security() cksum: %lu: \'%s\'\n",
-             debug_prefix_time(": protocol"),
-             p->auth_cksum,
-             p->req));
-#endif
+    /*
+     * Remember when this request was first sent
+     */
+    p->curtime = CURTIME;
 
-    return p->security == NULL;
+    /*
+     * Move to the ackwait state
+     */
+    p->state = s_ackwait;
+    p->timeout = ACK_WAIT;
+    return (A_PENDING);
 }
 
-int make_krb_request(hostname, port, req, datap, repwait, continuation)
-char *hostname;
-int port;
-char *req;
-void *datap;
-time_t repwait;
-void (*continuation) P((proto_t *p, pkt_t *pkt));
-{
+/*
+ * The acknowledge wait state.  We can enter here two ways:
+ *
+ *  - the caller has received a packet, located the request for
+ *    that packet, and called us with an action of A_RCVDATA.
+ *    
+ *  - the caller has determined that a request has timed out,
+ *    and has called us with A_TIMEOUT.
+ *
+ * Here we process the acknowledgment, which usually means that
+ * the client has agreed to our request and is working on it.
+ * It will later send a reply when finished.
+ */
+static action_t
+s_ackwait(p, action, pkt)
     proto_t *p;
-    struct hostent *hp;
-    char inst[256], realm[256];
-    int rc;
-
-    p = alloc(sizeof(proto_t));
-    p->state = S_STARTUP;
-    p->prevstate = S_STARTUP;
-    p->continuation = continuation;
-    p->req = req;
-    p->repwait = repwait;
-    p->datap = datap;
-
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: make_krb_request: host %s -> p %X\n", 
-             debug_prefix_time(": protocol"),
-             hostname,
-             req, (int)p));
-#endif
+    action_t action;
+    pkt_t *pkt;
+{
 
-    if((hp = host2krbname(hostname, inst, realm)) == 0)
-       return -1;
-    memcpy(&p->peer.sin_addr, hp->h_addr, hp->h_length);
-    p->peer.sin_family = AF_INET;
-    p->peer.sin_port = htons(port);
+    assert(p != NULL);
 
-    if((rc = add_krb_security(p, inst, realm)))
-       return rc;
+    /*
+     * The timeout case.  If our retry count has gone to zero
+     * fail this request.  Otherwise, move to the send state
+     * to retry the request.
+     */
+    if (action == A_TIMEOUT) {
+       assert(pkt == NULL);
 
-    state_machine(p, A_START, NULL);
-    return 0;
-}
-
-#endif
+       if (--p->acktries == 0) {
+           security_seterror(p->security_handle, "timeout waiting for ACK");
+           return (A_ABORT);
+       }
 
-static int select_til(waketime) 
-time_t waketime;
-{
-    fd_set ready;
-    struct timeval to;
-    time_t waittime;
-    int rc;
-
-    waittime = waketime - time(0);
-    if(waittime < 0) waittime = 0;     /* just poll */
-
-    FD_ZERO(&ready);
-    FD_SET(proto_socket, &ready);
-    to.tv_sec = waittime;
-    to.tv_usec = 0;
-
-    rc = select(proto_socket+1, (SELECT_ARG_TYPE *)&ready, NULL, NULL, &to);
-    if(rc == -1) {
-       error("protocol socket select: %s", strerror(errno));
+       p->state = s_sendreq;
+       return (A_CONTINUE);
     }
-    return rc;
-}
 
-static int packet_arrived() 
-{
-    return select_til(0);
+    assert(action == A_RCVDATA);
+    assert(pkt != NULL);
+
+    /*
+     * The packet-received state.  Determine what kind of
+     * packet we received, and act based on the reply type.
+     */
+    switch (pkt->type) {
+
+    /*
+     * Received an ACK.  Everything's good.  The client is
+     * now working on the request.  We queue up again and
+     * wait for the reply.
+     */
+    case P_ACK:
+       p->state = s_repwait;
+       p->timeout = p->repwait;
+       return (A_PENDING);
+
+    /*
+     * Received a NAK.  The request failed, so free up the
+     * resources associated with it and return.
+     *
+     * This should NOT return A_ABORT because it is not a local failure.
+     */
+    case P_NAK:
+       return (A_FINISH);
+
+    /*
+     * The client skipped the ACK, and replied right away.
+     * Move to the reply state to handle it.
+     */
+    case P_REP:
+    case P_PREP:
+       p->state = s_repwait;
+       return (A_CONTINUE);
+
+    /*
+     * Unexpected packet.  Requeue this request and hope
+     * we get what we want later.
+     */
+    default:
+       return (A_PENDING);
+    }
 }
 
-static void handle_incoming_packet() 
-{
-    pkt_t inpkt;
+/*
+ * The reply wait state.  We enter here much like we do with s_ackwait.
+ */
+static action_t
+s_repwait(p, action, pkt)
     proto_t *p;
+    action_t action;
+    pkt_t *pkt;
+{
+    pkt_t ack;
+
+    /*
+     * Timeout waiting for a reply.
+     */
+    if (action == A_TIMEOUT) {
+       assert(pkt == NULL);
+
+       /*
+        * If we've blown our timeout limit, free up this packet and
+        * return.
+        */
+       if (p->reqtries == 0 || DROP_DEAD_TIME(p->origtime)) {
+           security_seterror(p->security_handle, "timeout waiting for REP");
+           return (A_ABORT);
+       }
 
-    dgram_zero(&inpkt.dgram);
-    dgram_socket(&inpkt.dgram, proto_socket);
-    if(dgram_recv(&inpkt.dgram, 0, &inpkt.peer) == -1) {
-#ifdef ECONNREFUSED
-       if(errno == ECONNREFUSED)
-           return;
-#endif
-#ifdef EAGAIN
-       if(errno == EAGAIN)
-           return;
-#endif
-       fprintf(stderr,"protocol packet receive: %s\n", strerror(errno));
+       /*
+        * We still have some tries left.  Resend the request.
+        */
+       p->reqtries--;
+       p->state = s_sendreq;
+       p->acktries = ACK_TRIES;
+       return (A_CONTINUE);
     }
 
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: got packet:\n----\n%s----\n\n",
-             debug_prefix_time(": protocol"),
-             inpkt.dgram.data));
-#endif
-
-    parse_pkt_header(&inpkt);
-    if(inpkt.type == P_BOGUS)
-       return;
-    if((p = handle2ptr(inpkt.handle)) == NULL) {
-       /* ack succeeded reps */
-       if(inpkt.type == P_REP)
-           send_ack_repl(&inpkt);
-       return;
+    assert(action == A_RCVDATA);
+
+    /*
+     * We've received some data.  If we didn't get a reply,
+     * requeue the packet and retry.  Otherwise, acknowledge
+     * the reply, cleanup this packet, and return.
+     */
+    if (pkt->type != P_REP && pkt->type != P_PREP)
+       return (A_PENDING);
+
+    if(pkt->type == P_REP) {
+       pkt_init(&ack, P_ACK, "");
+       if (security_sendpkt(p->security_handle, &ack) < 0) {
+           /* XXX should retry */
+           security_seterror(p->security_handle, "error sending ACK: %s",
+               security_geterror(p->security_handle));
+           return (A_ABORT);
+       }
+       return (A_FINISH);
+    }
+    else if(pkt->type == P_PREP) {
+       p->timeout = p->repwait - CURTIME + p->curtime + 1;
+       return (A_CONTPEND);
     }
 
-#ifdef PROTO_DEBUG
-    dbprintf(("%s: handle %s p %X got packet type %s\n",
-             debug_prefix_time(": protocol"),
-             inpkt.handle,
-             (int)p,
-             prnpktype(inpkt.type)));
-#endif
-
-    pending_remove(p);
-    state_machine(p, A_RCVDATA, &inpkt);
+    /* should never go here, shut up compiler warning */
+    return (A_FINISH);
 }
 
-
-
-void check_protocol()
+/*
+ * event callback that receives a packet
+ */
+static void
+recvpkt_callback(cookie, pkt, status)
+    void *cookie;
+    pkt_t *pkt;
+    security_status_t status;
 {
-    time_t curtime;
-    proto_t *p;
+    proto_t *p = cookie;
 
-    while(packet_arrived())
-       handle_incoming_packet();
+    assert(p != NULL);
 
-    curtime = time(0);
-    while(pending_head && curtime >= pending_head->timeout) {
-       p = pending_dequeue();
+    switch (status) {
+    case S_OK:
+       state_machine(p, A_RCVDATA, pkt);
+       break;
+    case S_TIMEOUT:
        state_machine(p, A_TIMEOUT, NULL);
+       break;
+    case S_ERROR:
+       state_machine(p, A_ABORT, NULL);
+       break;
+    default:
+       assert(0);
+       break;
     }
 }
 
+/*
+ * --------------
+ * Misc functions
+ */
 
-void run_protocol()
-{
-    time_t wakeup_time;
-    proto_t *p;
+#ifdef PROTO_DEBUG
+/*
+ * Convert a pstate_t into a printable form.
+ */
+static const char *
+pstate2str(pstate)
+    pstate_t pstate;
+{
+    static const struct {
+       pstate_t type;
+       const char name[12];
+    } pstates[] = {
+#define        X(s)    { s, stringize(s) }
+       X(s_sendreq),
+       X(s_ackwait),
+       X(s_repwait),
+#undef X
+    };
+    int i;
 
-    while(pending_head) {
-       wakeup_time = pending_head->timeout;
+    for (i = 0; i < ASIZE(pstates); i++)
+       if (pstate == pstates[i].type)
+           return (pstates[i].name);
+    return ("BOGUS PSTATE");
+}
 
-#ifdef PROTO_DEBUG
-       dbprintf(("%s: run_protocol: waiting %d secs for %d pending reqs\n",
-                 debug_prefix_time(": protocol"),
-                 (int)(wakeup_time - time(0)),
-                 pending_qlength));
-#endif
+/*
+ * Convert an action_t into a printable form
+ */
+static const char *
+action2str(action)
+    action_t action;
+{
+    static const struct {
+       action_t type;
+       const char name[12];
+    } actions[] = {
+#define        X(s)    { s, stringize(s) }
+       X(A_START),
+       X(A_TIMEOUT),
+       X(A_ERROR),
+       X(A_RCVDATA),
+       X(A_CONTPEND),
+       X(A_PENDING),
+       X(A_CONTINUE),
+       X(A_FINISH),
+       X(A_ABORT),
+#undef X
+    };
+    int i;
 
-       if(select_til(wakeup_time))
-           handle_incoming_packet();
-       else {
-           p = pending_dequeue();
-           state_machine(p, A_TIMEOUT, NULL);
-       }
-    }
+    for (i = 0; i < ASIZE(actions); i++)
+       if (action == actions[i].type)
+           return (actions[i].name);
+    return ("BOGUS ACTION");
 }
+#endif /* PROTO_DEBUG */
index 6fd886bcd0c6496414830ca84f17ca4ce2752307..d4116a9ce2e9aa3c16d00c98f1badaa437465e06 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: protocol.h,v 1.8.10.2.2.2 2004/04/29 20:47:22 martinea Exp $
+ * $Id: protocol.h,v 1.10 2003/04/26 02:02:18 kovert Exp $
  *
- * interfaces for amanda protocol
+ * server-side interfaces for amanda protocol state machine
  */
 #ifndef PROTOCOL_H
 #define PROTOCOL_H
 
-#include "amanda.h"
-#include "dgram.h"
-
-typedef enum {
-    S_BOGUS,
-    S_STARTUP, S_SENDREQ, S_ACKWAIT, S_REPWAIT, S_SUCCEEDED, S_FAILED
-} pstate_t;
-
-typedef enum { A_BOGUS, A_START, A_TIMEOUT, A_RCVDATA } action_t;
-
-typedef enum { P_BOGUS, P_REQ, P_REP, P_PREP, P_ACK, P_NAK } pktype_t;
-
-typedef struct {                       /* a predigested datagram */
-    pktype_t type;
-    struct sockaddr_in peer;
-    uint32_t cksum;
-    int version_major, version_minor;
-    int sequence;
-    char *handle;
-    char *service;
-    char *security;
-    char *body;
-    dgram_t dgram;
-} pkt_t;
-
-typedef struct proto_s {
-    pstate_t state;
-    pstate_t prevstate;
-    struct sockaddr_in peer;
-    time_t timeout;
-    time_t repwait;
-    time_t origtime, curtime;
-    int reqtries, acktries;
-    int origseq, curseq;
-    int handleofs;
-    char *security;
-    uint32_t auth_cksum;
-    char *req;                                 /* body of request msg */
-    void (*continuation) P((struct proto_s *, pkt_t *));
-    void *datap;
-    struct proto_s *prev,*next;
-} proto_t;
-
-void proto_init P((int sock, int startseq, int handles));
-int make_request P((char *hostname, int port, char *req, void *datap,
-                   time_t repwait, 
-                   void (*continuation) P((proto_t *p, pkt_t *pkt))
-                   ));
-
-void check_protocol P((void));
-void run_protocol P((void));
-
-void parse_pkt_header P((pkt_t *pkt));
-
-#ifdef KRB4_SECURITY
-int make_krb_request P((char *hostname, int port, char *req,
-                       void *datap, time_t repwait,
-                       void (*continuation) P((proto_t *p, pkt_t *pkt))
-                       ));
-#endif
-
-extern char *parse_errmsg;
+#include "security.h"
+
+void protocol_init P((void));
+typedef        void (*protocol_sendreq_callback) P((void *, pkt_t *,
+    security_handle_t *));
+void protocol_sendreq P((const char *, const security_driver_t *, 
+       char *(*) P((char *, void *)), 
+       const char *,
+    time_t, protocol_sendreq_callback, void *));
+void protocol_check P((void));
+void protocol_run P((void));
 
 #endif /* PROTOCOL_H */
diff --git a/common-src/queue.h b/common-src/queue.h
new file mode 100644 (file)
index 0000000..bf1aecc
--- /dev/null
@@ -0,0 +1,406 @@
+/* Amanda $Id: queue.h,v 1.2 1999/05/24 16:10:35 kashmir Exp $ */
+/* from: $NetBSD: queue.h,v 1.16 1998/07/10 23:28:31 nathanw Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)queue.h     8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef        QUEUE_H
+#define        QUEUE_H
+
+/*
+ * This file defines four types of data structures: lists, simple queues,
+ * tail queues, and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so only elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may only be traversed in the forward direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the QUEUE-API document
+ * in the docs directory.
+ *
+ * Note that the #undef's in this file exist so we override any
+ * macros declared in <sys/queue.h>.
+ */
+
+/*
+ * List definitions.
+ */
+#undef LIST_HEAD
+#define LIST_HEAD(name, type)                                          \
+struct name {                                                          \
+       struct type *lh_first;  /* first element */                     \
+}
+
+#undef LIST_HEAD_INITIALIZER
+#define LIST_HEAD_INITIALIZER(head)                                    \
+       { NULL }
+
+#undef LIST_ENTRY
+#define LIST_ENTRY(type)                                               \
+struct {                                                               \
+       struct type *le_next;   /* next element */                      \
+       struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * List functions.
+ */
+#undef LIST_INIT
+#define        LIST_INIT(head) do {                                            \
+       (head)->lh_first = NULL;                                        \
+} while (0)
+
+#undef LIST_INSERT_AFTER
+#define LIST_INSERT_AFTER(listelm, elm, field) do {                    \
+       if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
+               (listelm)->field.le_next->field.le_prev =               \
+                   &(elm)->field.le_next;                              \
+       (listelm)->field.le_next = (elm);                               \
+       (elm)->field.le_prev = &(listelm)->field.le_next;               \
+} while (0)
+
+#undef LIST_INSERT_BEFORE
+#define        LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
+       (elm)->field.le_prev = (listelm)->field.le_prev;                \
+       (elm)->field.le_next = (listelm);                               \
+       *(listelm)->field.le_prev = (elm);                              \
+       (listelm)->field.le_prev = &(elm)->field.le_next;               \
+} while (0)
+
+#undef LIST_INSERT_HEAD
+#define LIST_INSERT_HEAD(head, elm, field) do {                                \
+       if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
+               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+       (head)->lh_first = (elm);                                       \
+       (elm)->field.le_prev = &(head)->lh_first;                       \
+} while (0)
+
+#undef LIST_REMOVE
+#define LIST_REMOVE(elm, field) do {                                   \
+       if ((elm)->field.le_next != NULL)                               \
+               (elm)->field.le_next->field.le_prev =                   \
+                   (elm)->field.le_prev;                               \
+       *(elm)->field.le_prev = (elm)->field.le_next;                   \
+} while (0)
+
+/*
+ * List access methods.
+ */
+#undef LIST_FIRST
+#define        LIST_FIRST(head)                ((head)->lh_first)
+
+#undef LIST_NEXT
+#define        LIST_NEXT(elm, field)           ((elm)->field.le_next)
+
+/*
+ * Simple queue definitions.
+ */
+#undef SIMPLEQ_HEAD
+#define SIMPLEQ_HEAD(name, type)                                       \
+struct name {                                                          \
+       struct type *sqh_first; /* first element */                     \
+       struct type **sqh_last; /* addr of last next element */         \
+}
+
+#undef SIMPLEQ_HEAD_INITIALIZER
+#define SIMPLEQ_HEAD_INITIALIZER(head)                                 \
+       { NULL, &(head).sqh_first }
+
+#undef SIMPLEQ_ENTRY
+#define SIMPLEQ_ENTRY(type)                                            \
+struct {                                                               \
+       struct type *sqe_next;  /* next element */                      \
+}
+
+/*
+ * Simple queue functions.
+ */
+#undef SIMPLEQ_INIT
+#define        SIMPLEQ_INIT(head) do {                                         \
+       (head)->sqh_first = NULL;                                       \
+       (head)->sqh_last = &(head)->sqh_first;                          \
+} while (0)
+
+#undef SIMPLEQ_INSERT_HEAD
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {                     \
+       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
+               (head)->sqh_last = &(elm)->field.sqe_next;              \
+       (head)->sqh_first = (elm);                                      \
+} while (0)
+
+#undef SIMPLEQ_INSERT_TAIL
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {                     \
+       (elm)->field.sqe_next = NULL;                                   \
+       *(head)->sqh_last = (elm);                                      \
+       (head)->sqh_last = &(elm)->field.sqe_next;                      \
+} while (0)
+
+#undef SIMPLEQ_INSERT_AFTER
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {           \
+       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+               (head)->sqh_last = &(elm)->field.sqe_next;              \
+       (listelm)->field.sqe_next = (elm);                              \
+} while (0)
+
+#undef SIMPLEQ_REMOVE_HEAD
+#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do {                     \
+       if (((head)->sqh_first = (elm)->field.sqe_next) == NULL)        \
+               (head)->sqh_last = &(head)->sqh_first;                  \
+} while (0)
+
+/*
+ * Simple queue access methods.
+ */
+#undef SIMPLEQ_FIRST
+#define        SIMPLEQ_FIRST(head)             ((head)->sqh_first)
+
+#undef SIMPLEQ_NEXT
+#define        SIMPLEQ_NEXT(elm, field)        ((elm)->field.sqe_next)
+
+/*
+ * Tail queue definitions.
+ */
+#undef TAILQ_HEAD
+#define TAILQ_HEAD(name, type)                                         \
+struct name {                                                          \
+       struct type *tqh_first; /* first element */                     \
+       struct type **tqh_last; /* addr of last next element */         \
+}
+
+#undef TAILQ_HEAD_INITIALIZER
+#define TAILQ_HEAD_INITIALIZER(head)                                   \
+       { NULL, &(head).tqh_first }
+
+#undef TAILQ_ENTRY
+#define TAILQ_ENTRY(type)                                              \
+struct {                                                               \
+       struct type *tqe_next;  /* next element */                      \
+       struct type **tqe_prev; /* address of previous next element */  \
+}
+
+/*
+ * Tail queue functions.
+ */
+#undef TAILQ_INIT
+#define        TAILQ_INIT(head) do {                                           \
+       (head)->tqh_first = NULL;                                       \
+       (head)->tqh_last = &(head)->tqh_first;                          \
+} while (0)
+
+#undef TAILQ_INSERT_HEAD
+#define TAILQ_INSERT_HEAD(head, elm, field) do {                       \
+       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
+               (head)->tqh_first->field.tqe_prev =                     \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (head)->tqh_first = (elm);                                      \
+       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
+} while (0)
+
+#undef TAILQ_INSERT_TAIL
+#define TAILQ_INSERT_TAIL(head, elm, field) do {                       \
+       (elm)->field.tqe_next = NULL;                                   \
+       (elm)->field.tqe_prev = (head)->tqh_last;                       \
+       *(head)->tqh_last = (elm);                                      \
+       (head)->tqh_last = &(elm)->field.tqe_next;                      \
+} while (0)
+
+#undef TAILQ_INSERT_AFTER
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {             \
+       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (listelm)->field.tqe_next = (elm);                              \
+       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
+} while (0)
+
+#undef TAILQ_INSERT_BEFORE
+#define        TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+       (elm)->field.tqe_next = (listelm);                              \
+       *(listelm)->field.tqe_prev = (elm);                             \
+       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
+} while (0)
+
+#undef TAILQ_REMOVE
+#define TAILQ_REMOVE(head, elm, field) do {                            \
+       if (((elm)->field.tqe_next) != NULL)                            \
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   (elm)->field.tqe_prev;                              \
+       else                                                            \
+               (head)->tqh_last = (elm)->field.tqe_prev;               \
+       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
+} while (0)
+
+/*
+ * Tail queue access methods.
+ */
+#undef TAILQ_FIRST
+#define        TAILQ_FIRST(head)               ((head)->tqh_first)
+
+#undef TAILQ_NEXT
+#define        TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
+
+/*
+ * Circular queue definitions.
+ */
+#undef CIRCLEQ_HEAD
+#define CIRCLEQ_HEAD(name, type)                                       \
+struct name {                                                          \
+       struct type *cqh_first;         /* first element */             \
+       struct type *cqh_last;          /* last element */              \
+}
+
+#undef CIRCLEQ_HEAD_INITIALIZER
+#define CIRCLEQ_HEAD_INITIALIZER(head)                                 \
+       { (void *)&head, (void *)&head }
+
+#undef CIRCLEQ_ENTRY
+#define CIRCLEQ_ENTRY(type)                                            \
+struct {                                                               \
+       struct type *cqe_next;          /* next element */              \
+       struct type *cqe_prev;          /* previous element */          \
+}
+
+/*
+ * Circular queue functions.
+ */
+#undef CIRCLEQ_INIT
+#define        CIRCLEQ_INIT(head) do {                                         \
+       (head)->cqh_first = (void *)(head);                             \
+       (head)->cqh_last = (void *)(head);                              \
+} while (0)
+
+#undef CIRCLEQ_INSERT_AFTER
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {           \
+       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
+       (elm)->field.cqe_prev = (listelm);                              \
+       if ((listelm)->field.cqe_next == (void *)(head))                \
+               (head)->cqh_last = (elm);                               \
+       else                                                            \
+               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
+       (listelm)->field.cqe_next = (elm);                              \
+} while (0)
+
+#undef CIRCLEQ_INSERT_BEFORE
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {          \
+       (elm)->field.cqe_next = (listelm);                              \
+       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
+       if ((listelm)->field.cqe_prev == (void *)(head))                \
+               (head)->cqh_first = (elm);                              \
+       else                                                            \
+               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
+       (listelm)->field.cqe_prev = (elm);                              \
+} while (0)
+
+#undef CIRCLEQ_INSERT_HEAD
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {                     \
+       (elm)->field.cqe_next = (head)->cqh_first;                      \
+       (elm)->field.cqe_prev = (void *)(head);                         \
+       if ((head)->cqh_last == (void *)(head))                         \
+               (head)->cqh_last = (elm);                               \
+       else                                                            \
+               (head)->cqh_first->field.cqe_prev = (elm);              \
+       (head)->cqh_first = (elm);                                      \
+} while (0)
+
+#undef CIRCLEQ_INSERT_TAIL
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {                     \
+       (elm)->field.cqe_next = (void *)(head);                         \
+       (elm)->field.cqe_prev = (head)->cqh_last;                       \
+       if ((head)->cqh_first == (void *)(head))                        \
+               (head)->cqh_first = (elm);                              \
+       else                                                            \
+               (head)->cqh_last->field.cqe_next = (elm);               \
+       (head)->cqh_last = (elm);                                       \
+} while (0)
+
+#undef CIRCLEQ_REMOVE
+#define        CIRCLEQ_REMOVE(head, elm, field) do {                           \
+       if ((elm)->field.cqe_next == (void *)(head))                    \
+               (head)->cqh_last = (elm)->field.cqe_prev;               \
+       else                                                            \
+               (elm)->field.cqe_next->field.cqe_prev =                 \
+                   (elm)->field.cqe_prev;                              \
+       if ((elm)->field.cqe_prev == (void *)(head))                    \
+               (head)->cqh_first = (elm)->field.cqe_next;              \
+       else                                                            \
+               (elm)->field.cqe_prev->field.cqe_next =                 \
+                   (elm)->field.cqe_next;                              \
+} while (0)
+
+/*
+ * Circular queue access methods.
+ */
+#undef CIRCLEQ_FIRST
+#define        CIRCLEQ_FIRST(head)             ((head)->cqh_first)
+
+#undef CIRCLEQ_LAST
+#define        CIRCLEQ_LAST(head)              ((head)->cqh_last)
+
+#undef CIRCLEQ_NEXT
+#define        CIRCLEQ_NEXT(elm, field)        ((elm)->field.cqe_next)
+
+#undef CIRCLEQ_PREV
+#define        CIRCLEQ_PREV(elm, field)        ((elm)->field.cqe_prev)
+#endif /* !QUEUE_H */
diff --git a/common-src/rsh-security.c b/common-src/rsh-security.c
new file mode 100644 (file)
index 0000000..4c74f71
--- /dev/null
@@ -0,0 +1,1218 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+
+/*
+ * $Id: rsh-security.c,v 1.18 2005/12/01 01:14:39 martinea Exp $
+ *
+ * rsh-security.c - security and transport over rsh or a rsh-like command.
+ *
+ * XXX still need to check for initial keyword on connect so we can skip
+ * over shell garbage and other stuff that rsh might want to spew out.
+ */
+
+#include "amanda.h"
+#include "event.h"
+#include "packet.h"
+#include "queue.h"
+#include "security.h"
+#include "stream.h"
+#include "version.h"
+
+#ifdef RSH_SECURITY
+
+/*#define      RSH_DEBUG*/
+
+#ifdef RSH_DEBUG
+#define        rshprintf(x)    dbprintf(x)
+#else
+#define        rshprintf(x)
+#endif
+
+/*
+ * Path to the rsh binary.  This should be configurable.
+ */
+#define        RSH_PATH        "/usr/bin/rsh"
+
+/*
+ * Arguments to rsh.  This should also be configurable
+ */
+#define        RSH_ARGS        "-l", CLIENT_LOGIN
+
+/*
+ * Number of seconds rsh has to start up
+ */
+#define        CONNECT_TIMEOUT 20
+
+/*
+ * Magic values for rsh_conn->handle
+ */
+#define        H_TAKEN -1              /* rsh_conn->tok was already read */
+#define        H_EOF   -2              /* this connection has been shut down */
+
+/*
+ * This is a rsh connection to a host.  We should only have
+ * one connection per host.
+ */
+struct rsh_conn {
+    int read, write;                           /* pipes to rsh */
+    pid_t pid;                                 /* pid of rsh process */
+    char pkt[NETWORK_BLOCK_BYTES];             /* last pkt read */
+    unsigned long pktlen;                      /* len of above */
+    struct {                                   /* buffer read() calls */
+       char buf[STREAM_BUFSIZE];               /* buffer */
+       size_t left;                    /* unread data */
+       ssize_t size;                   /* size of last read */
+    } readbuf;
+    event_handle_t *ev_read;                   /* read (EV_READFD) handle */
+    int ev_read_refcnt;                                /* number of readers */
+    char hostname[MAX_HOSTNAME_LENGTH+1];      /* host we're talking to */
+    char *errmsg;                              /* error passed up */
+    int refcnt;                                        /* number of handles using */
+    int handle;                                        /* last proto handle read */
+    TAILQ_ENTRY(rsh_conn) tq;                  /* queue handle */
+};
+
+
+struct rsh_stream;
+
+/*
+ * This is the private handle data.
+ */
+struct rsh_handle {
+    security_handle_t sech;            /* MUST be first */
+    char *hostname;                    /* ptr to rc->hostname */
+    struct rsh_stream *rs;             /* virtual stream we xmit over */
+
+    union {
+       void (*recvpkt) P((void *, pkt_t *, security_status_t));
+                                       /* func to call when packet recvd */
+       void (*connect) P((void *, security_handle_t *, security_status_t));
+                                       /* func to call when connected */
+    } fn;
+    void *arg;                         /* argument to pass function */
+    event_handle_t *ev_timeout;                /* timeout handle for recv */
+};
+
+/*
+ * This is the internal security_stream data for rsh.
+ */
+struct rsh_stream {
+    security_stream_t secstr;          /* MUST be first */
+    struct rsh_conn *rc;               /* physical connection */
+    int handle;                                /* protocol handle */
+    event_handle_t *ev_read;           /* read (EV_WAIT) event handle */
+    void (*fn) P((void *, void *, ssize_t));   /* read event fn */
+    void *arg;                         /* arg for previous */
+};
+
+/*
+ * Interface functions
+ */
+static int rsh_sendpkt P((void *, pkt_t *));
+static int rsh_stream_accept P((void *));
+static int rsh_stream_auth P((void *));
+static int rsh_stream_id P((void *));
+static int rsh_stream_write P((void *, const void *, size_t));
+static void *rsh_stream_client P((void *, int));
+static void *rsh_stream_server P((void *));
+static void rsh_accept P((int, int,
+    void (*)(security_handle_t *, pkt_t *)));
+static void rsh_close P((void *));
+static void rsh_connect P((const char *,
+    char *(*)(char *, void *), 
+    void (*)(void *, security_handle_t *, security_status_t), void *));
+static void rsh_recvpkt P((void *,
+    void (*)(void *, pkt_t *, security_status_t), void *, int));
+static void rsh_recvpkt_cancel P((void *));
+static void rsh_stream_close P((void *));
+static void rsh_stream_read P((void *, void (*)(void *, void *, ssize_t),
+    void *));
+static void rsh_stream_read_cancel P((void *));
+
+/*
+ * This is our interface to the outside world.
+ */
+const security_driver_t rsh_security_driver = {
+    "RSH",
+    rsh_connect,
+    rsh_accept,
+    rsh_close,
+    rsh_sendpkt,
+    rsh_recvpkt,
+    rsh_recvpkt_cancel,
+    rsh_stream_server,
+    rsh_stream_accept,
+    rsh_stream_client,
+    rsh_stream_close,
+    rsh_stream_auth,
+    rsh_stream_id,
+    rsh_stream_write,
+    rsh_stream_read,
+    rsh_stream_read_cancel,
+};
+
+/*
+ * This is a queue of open connections
+ */
+static struct {
+    TAILQ_HEAD(, rsh_conn) tailq;
+    int qlength;
+} connq = {
+    TAILQ_HEAD_INITIALIZER(connq.tailq), 0
+};
+#define        connq_first()           TAILQ_FIRST(&connq.tailq)
+#define        connq_next(rc)          TAILQ_NEXT(rc, tq)
+#define        connq_append(rc)        do {                                    \
+    TAILQ_INSERT_TAIL(&connq.tailq, rc, tq);                           \
+    connq.qlength++;                                                   \
+} while (0)
+#define        connq_remove(rc)        do {                                    \
+    assert(connq.qlength > 0);                                         \
+    TAILQ_REMOVE(&connq.tailq, rc, tq);                                        \
+    connq.qlength--;                                                   \
+} while (0)
+
+static int newhandle = 1;
+
+/*
+ * This is a function that should be called if a new security_handle_t is
+ * created.  If NULL, no new handles are created.
+ * It is passed the new handle and the received pkt
+ */
+static void (*accept_fn) P((security_handle_t *, pkt_t *));
+
+/*
+ * Local functions
+ */
+static void connect_callback P((void *));
+static void connect_timeout P((void *));
+static int send_token P((struct rsh_conn *, int, const void *, size_t));
+static int recv_token P((struct rsh_conn *, int));
+static void recvpkt_callback P((void *, void *, ssize_t));
+static void recvpkt_timeout P((void *));
+static void stream_read_callback P((void *));
+
+static int runrsh P((struct rsh_conn *));
+static struct rsh_conn *conn_get P((const char *));
+static void conn_put P((struct rsh_conn *));
+static void conn_read P((struct rsh_conn *));
+static void conn_read_cancel P((struct rsh_conn *));
+static void conn_read_callback P((void *));
+static int net_writev P((int, struct iovec *, int));
+static ssize_t net_read P((struct rsh_conn *, void *, size_t, int));
+static int net_read_fillbuf P((struct rsh_conn *, int, int));
+static void parse_pkt P((pkt_t *, const void *, size_t));
+
+
+/*
+ * rsh version of a security handle allocator.  Logically sets
+ * up a network "connection".
+ */
+static void
+rsh_connect(hostname, conf_fn, fn, arg)
+    const char *hostname;
+    char *(*conf_fn) P((char *, void *));
+    void (*fn) P((void *, security_handle_t *, security_status_t));
+    void *arg;
+{
+    struct rsh_handle *rh;
+    struct hostent *he;
+
+    assert(fn != NULL);
+    assert(hostname != NULL);
+
+    rshprintf(("rsh_connect: %s\n", hostname));
+
+    rh = alloc(sizeof(*rh));
+    security_handleinit(&rh->sech, &rsh_security_driver);
+    rh->hostname = NULL;
+    rh->rs = NULL;
+    rh->ev_timeout = NULL;
+
+    if ((he = gethostbyname(hostname)) == NULL) {
+       security_seterror(&rh->sech,
+           "%s: could not resolve hostname", hostname);
+       (*fn)(arg, &rh->sech, S_ERROR);
+       return;
+    }
+    rh->hostname = he->h_name; /* will be replaced */
+    rh->rs = rsh_stream_client(rh, newhandle++);
+
+    if (rh->rs == NULL)
+       goto error;
+
+    rh->hostname = rh->rs->rc->hostname;
+
+    if (rh->rs->rc->pid < 0) {
+       /*
+        * We need to open a new connection.
+        *
+        * XXX need to eventually limit number of outgoing connections here.
+        */
+       if (runrsh(rh->rs->rc) < 0) {
+           security_seterror(&rh->sech,
+               "can't connect to %s: %s", hostname, rh->rs->rc->errmsg);
+           goto error;
+       }
+    }
+    /*
+     * The socket will be opened async so hosts that are down won't
+     * block everything.  We need to register a write event
+     * so we will know when the socket comes alive.
+     *
+     * Overload rh->rs->ev_read to provide a write event handle.
+     * We also register a timeout.
+     */
+    rh->fn.connect = fn;
+    rh->arg = arg;
+    rh->rs->ev_read = event_register(rh->rs->rc->write, EV_WRITEFD,
+       connect_callback, rh);
+    rh->ev_timeout = event_register(CONNECT_TIMEOUT, EV_TIME,
+       connect_timeout, rh);
+
+    return;
+
+error:
+    (*fn)(arg, &rh->sech, S_ERROR);
+}
+
+/*
+ * Called when a rsh connection is finished connecting and is ready
+ * to be authenticated.
+ */
+static void
+connect_callback(cookie)
+    void *cookie;
+{
+    struct rsh_handle *rh = cookie;
+
+    event_release(rh->rs->ev_read);
+    rh->rs->ev_read = NULL;
+    event_release(rh->ev_timeout);
+    rh->ev_timeout = NULL;
+
+    (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
+}
+
+/*
+ * Called if a connection times out before completion.
+ */
+static void
+connect_timeout(cookie)
+    void *cookie;
+{
+    struct rsh_handle *rh = cookie;
+
+    event_release(rh->rs->ev_read);
+    rh->rs->ev_read = NULL;
+    event_release(rh->ev_timeout);
+    rh->ev_timeout = NULL;
+
+    (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
+}
+
+/*
+ * Setup to handle new incoming connections
+ */
+static void
+rsh_accept(in, out, fn)
+    int in, out;
+    void (*fn) P((security_handle_t *, pkt_t *));
+{
+    struct rsh_conn *rc;
+
+    rc = conn_get("unknown");
+    rc->read = in;
+    rc->write = out;
+    accept_fn = fn;
+    conn_read(rc);
+}
+
+/*
+ * Locate an existing connection to the given host, or create a new,
+ * unconnected entry if none exists.  The caller is expected to check
+ * for the lack of a connection (rc->read == -1) and set one up.
+ */
+static struct rsh_conn *
+conn_get(hostname)
+    const char *hostname;
+{
+    struct rsh_conn *rc;
+
+    rshprintf(("rsh: conn_get: %s\n", hostname));
+
+    for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {
+       if (strcasecmp(hostname, rc->hostname) == 0)
+           break;
+    }
+
+    if (rc != NULL) {
+       rc->refcnt++;
+       rshprintf(("rsh: conn_get: exists, refcnt to %s is now %d\n",
+           rc->hostname, rc->refcnt));
+       return (rc);
+    }
+
+    rshprintf(("rsh: conn_get: creating new handle\n"));
+    /*
+     * We can't be creating a new handle if we are the client
+     */
+    assert(accept_fn == NULL);
+    rc = alloc(sizeof(*rc));
+    rc->read = rc->write = -1;
+    rc->pid = -1;
+    rc->readbuf.left = 0;
+    rc->readbuf.size = 0;
+    rc->ev_read = NULL;
+    strncpy(rc->hostname, hostname, sizeof(rc->hostname) - 1);
+    rc->hostname[sizeof(rc->hostname) - 1] = '\0';
+    rc->errmsg = NULL;
+    rc->refcnt = 1;
+    rc->handle = -1;
+    connq_append(rc);
+    return (rc);
+}
+
+/*
+ * Delete a reference to a connection, and close it if it is the last
+ * reference.
+ */
+static void
+conn_put(rc)
+    struct rsh_conn *rc;
+{
+    amwait_t status;
+
+    assert(rc->refcnt > 0);
+    if (--rc->refcnt > 0) {
+       rshprintf(("rsh: conn_put: decrementing refcnt for %s to %d\n",
+           rc->hostname, rc->refcnt));
+       return;
+    }
+    rshprintf(("rsh: conn_put: closing connection to %s\n", rc->hostname));
+    if (rc->read != -1)
+       aclose(rc->read);
+    if (rc->write != -1)
+       aclose(rc->write);
+    if (rc->pid != -1) {
+       waitpid(rc->pid, &status, WNOHANG);
+    }
+    if (rc->ev_read != NULL)
+       event_release(rc->ev_read);
+    if (rc->errmsg != NULL)
+       amfree(rc->errmsg);
+    connq_remove(rc);
+    amfree(rc);
+}
+
+/*
+ * Turn on read events for a conn.  Or, increase a refcnt if we are
+ * already receiving read events.
+ */
+static void
+conn_read(rc)
+    struct rsh_conn *rc;
+{
+
+    if (rc->ev_read != NULL) {
+       rc->ev_read_refcnt++;
+       rshprintf(("rsh: conn_read: incremented refcnt to %d for %s\n",
+           rc->ev_read_refcnt, rc->hostname));
+       return;
+    }
+    rshprintf(("rsh: conn_read registering event handler for %s\n",
+       rc->hostname));
+    rc->ev_read = event_register(rc->read, EV_READFD, conn_read_callback, rc);
+    rc->ev_read_refcnt = 1;
+}
+
+static void
+conn_read_cancel(rc)
+    struct rsh_conn *rc;
+{
+
+    if (--rc->ev_read_refcnt > 0) {
+       rshprintf(("rsh: conn_read_cancel: decremented refcnt to %d for %s\n",
+           rc->ev_read_refcnt, rc->hostname));
+       return;
+    }
+    rshprintf(("rsh: conn_read_cancel: releasing event handler for %s\n",
+       rc->hostname));
+    event_release(rc->ev_read);
+    rc->ev_read = NULL;
+}
+
+/*
+ * frees a handle allocated by the above
+ */
+static void
+rsh_close(inst)
+    void *inst;
+{
+    struct rsh_handle *rh = inst;
+
+    assert(rh != NULL);
+
+    rshprintf(("rsh: closing handle to %s\n", rh->hostname));
+
+    if (rh->rs != NULL) {
+       /* This may be null if we get here on an error */
+       rsh_recvpkt_cancel(rh);
+       security_stream_close(&rh->rs->secstr);
+    }
+    /* keep us from getting here again */
+    rh->sech.driver = NULL;
+    amfree(rh);
+}
+
+/*
+ * Forks a rsh to the host listed in rc->hostname
+ * Returns negative on error, with an errmsg in rc->errmsg.
+ */
+static int
+runrsh(rc)
+    struct rsh_conn *rc;
+{
+    int rpipe[2], wpipe[2];
+    char *amandad_path;
+
+    if (pipe(rpipe) < 0 || pipe(wpipe) < 0) {
+       rc->errmsg = newvstralloc("pipe: ", strerror(errno), NULL);
+       return (-1);
+    }
+    switch (rc->pid = fork()) {
+    case -1:
+       rc->errmsg = newvstralloc("fork: ", strerror(errno), NULL);
+       aclose(rpipe[0]);
+       aclose(rpipe[1]);
+       aclose(wpipe[0]);
+       aclose(wpipe[1]);
+       return (-1);
+    case 0:
+       dup2(wpipe[0], 0);
+       dup2(rpipe[1], 1);
+       dup2(rpipe[1], 2);
+       break;
+    default:
+       rc->read = rpipe[0];
+       aclose(rpipe[1]);
+       rc->write = wpipe[1];
+       aclose(wpipe[0]);
+       return (0);
+    }
+
+    safe_fd(-1, 0);
+
+    amandad_path = vstralloc(libexecdir, "/", "amandad", versionsuffix(),
+       NULL);
+    execlp(RSH_PATH, RSH_PATH, RSH_ARGS, rc->hostname, amandad_path,
+       "-auth=rsh", NULL);
+    error("error: couldn't exec %s: %s", RSH_PATH, strerror(errno));
+
+    /* should nerver go here, shut up compiler warning */
+    return(-1);
+}
+
+/*
+ * Transmit a packet.
+ */
+static int
+rsh_sendpkt(cookie, pkt)
+    void *cookie;
+    pkt_t *pkt;
+{
+    char buf[sizeof(pkt_t)];
+    struct rsh_handle *rh = cookie;
+    size_t len;
+
+    assert(rh != NULL);
+    assert(pkt != NULL);
+
+    rshprintf(("rsh: sendpkt: enter\n"));
+
+    len = strlen(pkt->body) + 2;
+    buf[0] = (char)pkt->type;
+    strcpy(&buf[1], pkt->body);
+
+    rshprintf(("rsh: sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n",
+       pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body));
+
+    if (rsh_stream_write(rh->rs, buf, len) < 0) {
+       security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
+       return (-1);
+    }
+    return (0);
+}
+
+/*
+ * Set up to receive a packet asyncronously, and call back when
+ * it has been read.
+ */
+static void
+rsh_recvpkt(cookie, fn, arg, timeout)
+    void *cookie, *arg;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    int timeout;
+{
+    struct rsh_handle *rh = cookie;
+
+    assert(rh != NULL);
+
+    rshprintf(("rsh: recvpkt registered for %s\n", rh->hostname));
+
+    /*
+     * Reset any pending timeout on this handle
+     */
+    if (rh->ev_timeout != NULL)
+       event_release(rh->ev_timeout);
+
+    /*
+     * Negative timeouts mean no timeout
+     */
+    if (timeout < 0)
+       rh->ev_timeout = NULL;
+    else
+       rh->ev_timeout = event_register(timeout, EV_TIME, recvpkt_timeout, rh);
+
+    rh->fn.recvpkt = fn;
+    rh->arg = arg;
+    rsh_stream_read(rh->rs, recvpkt_callback, rh);
+}
+
+/*
+ * Remove a async receive request from the queue
+ */
+static void
+rsh_recvpkt_cancel(cookie)
+    void *cookie;
+{
+    struct rsh_handle *rh = cookie;
+
+    rshprintf(("rsh: cancelling recvpkt for %s\n", rh->hostname));
+
+    assert(rh != NULL);
+
+    rsh_stream_read_cancel(rh->rs);
+    if (rh->ev_timeout != NULL) {
+       event_release(rh->ev_timeout);
+       rh->ev_timeout = NULL;
+    }
+}
+
+/*
+ * This is called when a handle is woken up because data read off of the
+ * net is for it.
+ */
+static void
+recvpkt_callback(cookie, buf, bufsize)
+    void *cookie, *buf;
+    ssize_t bufsize;
+{
+    pkt_t pkt;
+    struct rsh_handle *rh = cookie;
+
+    assert(rh != NULL);
+
+    /*
+     * We need to cancel the recvpkt request before calling
+     * the callback because the callback may reschedule us.
+     */
+    rsh_recvpkt_cancel(rh);
+
+    switch (bufsize) {
+    case 0:
+       security_seterror(&rh->sech,
+           "EOF on read from %s", rh->hostname);
+       (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
+       return;
+    case -1:
+       security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
+       (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
+       return;
+    default:
+       break;
+    }
+
+    parse_pkt(&pkt, buf, bufsize);
+    rshprintf(("rsh: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n",
+       pkt_type2str(pkt.type), pkt.type, rh->hostname, pkt.body));
+    (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
+}
+
+/*
+ * This is called when a handle times out before receiving a packet.
+ */
+static void
+recvpkt_timeout(cookie)
+    void *cookie;
+{
+    struct rsh_handle *rh = cookie;
+
+    assert(rh != NULL);
+
+    rshprintf(("rsh: recvpkt timeout for %s\n", rh->hostname));
+
+    rsh_recvpkt_cancel(rh);
+    (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);
+}
+
+/*
+ * Create the server end of a stream.  For rsh, this means setup a stream
+ * object and allocate a new handle for it.
+ */
+static void *
+rsh_stream_server(h)
+    void *h;
+{
+    struct rsh_handle *rh = h;
+    struct rsh_stream *rs;
+
+    assert(rh != NULL);
+
+    rs = alloc(sizeof(*rs));
+    security_streaminit(&rs->secstr, &rsh_security_driver);
+    rs->rc = conn_get(rh->hostname);
+    /*
+     * Stream should already be setup!
+     */
+    if (rs->rc->read < 0) {
+       conn_put(rs->rc);
+       amfree(rs);
+       security_seterror(&rh->sech, "lost connection to %s", rh->hostname);
+       return (NULL);
+    }
+    rh->hostname = rs->rc->hostname;
+    /*
+     * so as not to conflict with the amanda server's handle numbers,
+     * we start at 5000 and work down
+     */
+    rs->handle = 5000 - newhandle++;
+    rs->ev_read = NULL;
+    rshprintf(("rsh: stream_server: created stream %d\n", rs->handle));
+    return (rs);
+}
+
+/*
+ * Accept an incoming connection on a stream_server socket
+ * Nothing needed for rsh.
+ */
+static int
+rsh_stream_accept(s)
+    void *s;
+{
+
+    return (0);
+}
+
+/*
+ * Return a connected stream.  For rsh, this means setup a stream
+ * with the supplied handle.
+ */
+static void *
+rsh_stream_client(h, id)
+    void *h;
+    int id;
+{
+    struct rsh_handle *rh = h;
+    struct rsh_stream *rs;
+
+    assert(rh != NULL);
+
+    if (id <= 0) {
+       security_seterror(&rh->sech,
+           "%d: invalid security stream id", id);
+       return (NULL);
+    }
+
+    rs = alloc(sizeof(*rs));
+    security_streaminit(&rs->secstr, &rsh_security_driver);
+    rs->handle = id;
+    rs->ev_read = NULL;
+    rs->rc = conn_get(rh->hostname);
+
+    rshprintf(("rsh: stream_client: connected to stream %d\n", id));
+
+    return (rs);
+}
+
+/*
+ * Close and unallocate resources for a stream.
+ */
+static void
+rsh_stream_close(s)
+    void *s;
+{
+    struct rsh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    rshprintf(("rsh: stream_close: closing stream %d\n", rs->handle));
+
+    rsh_stream_read_cancel(rs);
+    conn_put(rs->rc);
+    amfree(rs);
+}
+
+/*
+ * Authenticate a stream
+ * Nothing needed for rsh.  The connection is authenticated by rshd
+ * on startup.
+ */
+static int
+rsh_stream_auth(s)
+    void *s;
+{
+
+    return (0);
+}
+
+/*
+ * Returns the stream id for this stream.  This is just the local
+ * port.
+ */
+static int
+rsh_stream_id(s)
+    void *s;
+{
+    struct rsh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    return (rs->handle);
+}
+
+/*
+ * Write a chunk of data to a stream.  Blocks until completion.
+ */
+static int
+rsh_stream_write(s, buf, size)
+    void *s;
+    const void *buf;
+    size_t size;
+{
+    struct rsh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    rshprintf(("rsh: stream_write: writing %d bytes to %s:%d\n", size,
+       rs->rc->hostname, rs->handle));
+
+    if (send_token(rs->rc, rs->handle, buf, size) < 0) {
+       security_stream_seterror(&rs->secstr, rs->rc->errmsg);
+       return (-1);
+    }
+    return (0);
+}
+
+/*
+ * Submit a request to read some data.  Calls back with the given
+ * function and arg when completed.
+ */
+static void
+rsh_stream_read(s, fn, arg)
+    void *s, *arg;
+    void (*fn) P((void *, void *, ssize_t));
+{
+    struct rsh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    /*
+     * Only one read request can be active per stream.
+     */
+    if (rs->ev_read == NULL) {
+       rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
+           stream_read_callback, rs);
+       conn_read(rs->rc);
+    }
+    rs->fn = fn;
+    rs->arg = arg;
+}
+
+/*
+ * Cancel a previous stream read request.  It's ok if we didn't have a read
+ * scheduled.
+ */
+static void
+rsh_stream_read_cancel(s)
+    void *s;
+{
+    struct rsh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    if (rs->ev_read != NULL) {
+       event_release(rs->ev_read);
+       rs->ev_read = NULL;
+       conn_read_cancel(rs->rc);
+    }
+}
+
+/*
+ * Callback for rsh_stream_read
+ */
+static void
+stream_read_callback(arg)
+    void *arg;
+{
+    struct rsh_stream *rs = arg;
+    assert(rs != NULL);
+
+    rshprintf(("rsh: stream_read_callback: handle %d\n", rs->handle));
+
+    /*
+     * Make sure this was for us.  If it was, then blow away the handle
+     * so it doesn't get claimed twice.  Otherwise, leave it alone.
+     *
+     * If the handle is EOF, pass that up to our callback.
+     */
+    if (rs->rc->handle == rs->handle) {
+       rshprintf(("rsh: stream_read_callback: it was for us\n"));
+       rs->rc->handle = H_TAKEN;
+    } else if (rs->rc->handle != H_EOF) {
+       rshprintf(("rsh: stream_read_callback: not for us\n"));
+       return;
+    }
+
+    /*
+     * Remove the event first, and then call the callback.
+     * We remove it first because we don't want to get in their
+     * way if they reschedule it.
+     */
+    rsh_stream_read_cancel(rs);
+
+    if (rs->rc->pktlen == 0) {
+       rshprintf(("rsh: stream_read_callback: EOF\n"));
+       (*rs->fn)(rs->arg, NULL, 0);
+       return;
+    }
+    rshprintf(("rsh: stream_read_callback: read %ld bytes from %s:%d\n",
+       rs->rc->pktlen, rs->rc->hostname, rs->handle));
+    (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
+}
+
+/*
+ * The callback for the netfd for the event handler
+ * Determines if this packet is for this security handle,
+ * and does the real callback if so.
+ */
+static void
+conn_read_callback(cookie)
+    void *cookie;
+{
+    struct rsh_conn *rc = cookie;
+    struct rsh_handle *rh;
+    pkt_t pkt;
+    int rval;
+
+    assert(cookie != NULL);
+
+    rshprintf(("rsh: conn_read_callback\n"));
+
+    /* Read the data off the wire.  If we get errors, shut down. */
+    rval = recv_token(rc, 5);
+    rshprintf(("rsh: conn_read_callback: recv_token returned %d\n", rval));
+    if (rval <= 0) {
+       rc->pktlen = 0;
+       rc->handle = H_EOF;
+       rval = event_wakeup((event_id_t)rc);
+       rshprintf(("rsh: conn_read_callback: event_wakeup return %d\n", rval));
+       /* delete our 'accept' reference */
+       if (accept_fn != NULL)
+           conn_put(rc);
+       accept_fn = NULL;
+       return;
+    }
+
+    /* If there are events waiting on this handle, we're done */
+    rval = event_wakeup((event_id_t)rc);
+    rshprintf(("rsh: conn_read_callback: event_wakeup return %d\n", rval));
+    if (rval > 0)
+       return;
+
+    /* If there is no accept fn registered, then drop the packet */
+    if (accept_fn == NULL)
+       return;
+
+    rh = alloc(sizeof(*rh));
+    security_handleinit(&rh->sech, &rsh_security_driver);
+    rh->hostname = rc->hostname;
+    rh->rs = rsh_stream_client(rh, rc->handle);
+    rh->ev_timeout = NULL;
+
+    rshprintf(("rsh: new connection\n"));
+    parse_pkt(&pkt, rc->pkt, rc->pktlen);
+    rshprintf(("rsh: calling accept_fn\n"));
+    (*accept_fn)(&rh->sech, &pkt);
+}
+
+static void
+parse_pkt(pkt, buf, bufsize)
+    pkt_t *pkt;
+    const void *buf;
+    size_t bufsize;
+{
+    const unsigned char *bufp = buf;
+
+    rshprintf(("rsh: parse_pkt: parsing buffer of %d bytes\n", bufsize));
+
+    pkt->type = (pktype_t)*bufp++;
+    bufsize--;
+
+    if (bufsize == 0) {
+       pkt->body[0] = '\0';
+    } else {
+       if (bufsize > sizeof(pkt->body) - 1)
+           bufsize = sizeof(pkt->body) - 1;
+       memcpy(pkt->body, bufp, bufsize);
+       pkt->body[sizeof(pkt->body) - 1] = '\0';
+    }
+
+    rshprintf(("rsh: parse_pkt: %s (%d): \"%s\"\n", pkt_type2str(pkt->type),
+       pkt->type, pkt->body));
+}
+
+
+/*
+ * Transmits a chunk of data over a rsh_handle, adding
+ * the necessary headers to allow the remote end to decode it.
+ */
+static int
+send_token(rc, handle, buf, len)
+    struct rsh_conn *rc;
+    int handle;
+    const void *buf;
+    size_t len;
+{
+    unsigned int netlength, nethandle;
+    struct iovec iov[3];
+
+    rshprintf(("rsh: send_token: writing %d bytes to %s\n", len,
+       rc->hostname));
+
+    assert(sizeof(netlength) == 4);
+
+    /*
+     * Format is:
+     *   32 bit length (network byte order)
+     *   32 bit handle (network byte order)
+     *   data
+     */
+    netlength = htonl(len);
+    iov[0].iov_base = (void *)&netlength;
+    iov[0].iov_len = sizeof(netlength);
+
+    nethandle = htonl(handle);
+    iov[1].iov_base = (void *)&nethandle;
+    iov[1].iov_len = sizeof(nethandle);
+
+    iov[2].iov_base = (void *)buf;
+    iov[2].iov_len = len;
+
+    if (net_writev(rc->write, iov, 3) < 0) {
+       rc->errmsg = newvstralloc(rc->errmsg, "rsh write error to ",
+           rc->hostname, ": ", strerror(errno), NULL);
+       return (-1);
+    }
+    return (0);
+}
+
+static int
+recv_token(rc, timeout)
+    struct rsh_conn *rc;
+    int timeout;
+{
+    unsigned int netint;
+
+    assert(sizeof(netint) == 4);
+
+    assert(rc->read >= 0);
+
+    rshprintf(("rsh: recv_token: reading from %s\n", rc->hostname));
+
+    switch (net_read(rc, &netint, sizeof(netint), timeout)) {
+    case -1:
+       rc->errmsg = newvstralloc(rc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       return (-1);
+    case 0:
+       rc->pktlen = 0;
+       return (0);
+    default:
+       break;
+    }
+    rc->pktlen = ntohl(netint);
+    if (rc->pktlen > sizeof(rc->pkt)) {
+       rc->errmsg = newstralloc(rc->errmsg, "recv error: huge packet");
+       return (-1);
+    }
+
+    switch (net_read(rc, &netint, sizeof(netint), timeout)) {
+    case -1:
+       rc->errmsg = newvstralloc(rc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       return (-1);
+    case 0:
+       rc->pktlen = 0;
+       return (0);
+    default:
+       break;
+    }
+    rc->handle = ntohl(netint);
+
+    switch (net_read(rc, rc->pkt, rc->pktlen, timeout)) {
+    case -1:
+       rc->errmsg = newvstralloc(rc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       return (-1);
+    case 0:
+       rc->pktlen = 0;
+       break;
+    default:
+       break;
+    }
+
+    rshprintf(("rsh: recv_token: read %ld bytes from %s\n", rc->pktlen,
+       rc->hostname));
+    return (rc->pktlen);
+}
+
+/*
+ * Writes out the entire iovec
+ */
+static int
+net_writev(fd, iov, iovcnt)
+    int fd, iovcnt;
+    struct iovec *iov;
+{
+    int delta, n, total;
+
+    assert(iov != NULL);
+
+    total = 0;
+    while (iovcnt > 0) {
+       /*
+        * Write the iovec
+        */
+       total += n = writev(fd, iov, iovcnt);
+       if (n < 0)
+           return (-1);
+       if (n == 0) {
+           errno = EIO;
+           return (-1);
+       }
+       /*
+        * Iterate through each iov.  Figure out what we still need
+        * to write out.
+        */
+       for (; n > 0; iovcnt--, iov++) {
+           /* 'delta' is the bytes written from this iovec */
+           delta = n < iov->iov_len ? n : iov->iov_len;
+           /* subtract from the total num bytes written */
+           n -= delta;
+           assert(n >= 0);
+           /* subtract from this iovec */
+           iov->iov_len -= delta;
+           iov->iov_base = (char *)iov->iov_base + delta;
+           /* if this iovec isn't empty, run the writev again */
+           if (iov->iov_len > 0)
+               break;
+       }
+    }
+    return (total);
+}
+
+/*
+ * Like read(), but waits until the entire buffer has been filled.
+ */
+static ssize_t
+net_read(rc, vbuf, origsize, timeout)
+    struct rsh_conn *rc;
+    void *vbuf;
+    size_t origsize;
+    int timeout;
+{
+    char *buf = vbuf, *off;    /* ptr arith */
+    int nread;
+    size_t size = origsize;
+
+    while (size > 0) {
+       if (rc->readbuf.left == 0) {
+           if (net_read_fillbuf(rc, timeout, size) < 0)
+               return (-1);
+           if (rc->readbuf.size == 0)
+               return (0);
+       }
+       nread = min(rc->readbuf.left, size);
+       off = rc->readbuf.buf + rc->readbuf.size - rc->readbuf.left;
+       memcpy(buf, off, nread);
+
+       buf += nread;
+       size -= nread;
+       rc->readbuf.left -= nread;
+    }
+    return ((ssize_t)origsize);
+}
+
+/*
+ * net_read likes to do a lot of little reads.  Buffer it.
+ */
+static int
+net_read_fillbuf(rc, timeout, size)
+    struct rsh_conn *rc;
+    int timeout;
+    int size;
+{
+    fd_set readfds;
+    struct timeval tv;
+    if(size > sizeof(rc->readbuf.buf)) size = sizeof(rc->readbuf.buf);
+
+    FD_ZERO(&readfds);
+    FD_SET(rc->read, &readfds);
+    tv.tv_sec = timeout;
+    tv.tv_usec = 0;
+    switch (select(rc->read + 1, &readfds, NULL, NULL, &tv)) {
+    case 0:
+       errno = ETIMEDOUT;
+       /* FALLTHROUGH */
+    case -1:
+       return (-1);
+    case 1:
+       assert(FD_ISSET(rc->read, &readfds));
+       break;
+    default:
+       assert(0);
+       break;
+    }
+    rc->readbuf.left = 0;
+    rc->readbuf.size = read(rc->read, rc->readbuf.buf, size);
+    if (rc->readbuf.size < 0)
+       return (-1);
+    rc->readbuf.left = rc->readbuf.size;
+    return (0);
+}
+
+#endif /* RSH_SECURITY */
index a651b4b3c6c7b816f6f1e55a5ab756f72873322c..795d64eda86df73eacd91f34a4f2de0c586a9e33 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: security.c,v 1.17.2.6.4.1.2.5.2.1 2004/04/29 20:47:22 martinea Exp $
+ * $Id: security.c,v 1.26 2004/03/16 19:09:39 martinea Exp $
  *
- * wrapper file for kerberos security
+ * Security driver interface for the Amanda backup system.
  */
 
 #include "amanda.h"
-#include "clock.h"
+#include "arglist.h"
+#include "packet.h"
+#include "security.h"
 
-/*
- * Change the following from #undef to #define to cause detailed logging
- * of the security steps, e.g. into /tmp/amanda/amandad*debug.
- */
-#undef SHOW_SECURITY_DETAIL
-
-/*
- * If we don't have the new-style wait access functions, use our own,
- * compatible with old-style BSD systems at least.  Note that we don't
- * care about the case w_stopval == WSTOPPED since we don't ask to see
- * stopped processes, so should never get them from wait.
- */
-#ifndef WEXITSTATUS
-#   define WEXITSTATUS(r)       (((union wait *) &(r))->w_retcode)
-#   define WTERMSIG(r)          (((union wait *) &(r))->w_termsig)
-
-#   undef  WIFSIGNALED
-#   define WIFSIGNALED(r)       (((union wait *) &(r))->w_termsig != 0)
+#ifdef BSD_SECURITY
+extern const security_driver_t bsd_security_driver;
+#endif
+#ifdef KRB4_SECURITY
+extern const security_driver_t krb4_security_driver;
+#endif
+#ifdef KRB5_SECURITY
+extern const security_driver_t krb5_security_driver;
+#endif
+#ifdef RSH_SECURITY
+extern const security_driver_t rsh_security_driver;
+#endif
+#ifdef SSH_SECURITY
+extern const security_driver_t ssh_security_driver;
 #endif
 
-#if defined(TEST)                                              /* { */
-#define SHOW_SECURITY_DETAIL
-#undef dbprintf
-#define dbprintf(p)    printf p
-#endif                                                         /* } */
+static const security_driver_t *drivers[] = {
+#ifdef BSD_SECURITY
+    &bsd_security_driver,
+#endif
+#ifdef KRB4_SECURITY
+    &krb4_security_driver,
+#endif
+#ifdef KRB5_SECURITY
+    &krb5_security_driver,
+#endif
+#ifdef RSH_SECURITY
+    &rsh_security_driver,
+#endif
+#ifdef SSH_SECURITY
+    &ssh_security_driver,
+#endif
+};
+#define        NDRIVERS        (sizeof(drivers) / sizeof(drivers[0]))
 
-#if defined(SHOW_SECURITY_DETAIL)                              /* { */
-void show_stat_info(a, b)
-    char *a, *b;
+/*
+ * Given a name of a security type, returns the driver structure
+ */
+const security_driver_t *
+security_getdriver(name)
+    const char *name;
 {
-    char *name = vstralloc(a, b, NULL);
-    struct stat sbuf;
-    struct passwd *pwptr;
-    char *owner;
-    struct group *grptr;
-    char *group;
+    int i;
 
-    if (stat(name, &sbuf) != 0) {
-       dbprintf(("%s: cannot stat %s: %s\n",
-                 debug_prefix_time(NULL), name, strerror(errno)));
-       amfree(name);
-       return;
-    }
-    if ((pwptr = getpwuid(sbuf.st_uid)) == NULL) {
-       owner = alloc(NUM_STR_SIZE);
-       ap_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
-    } else {
-       owner = stralloc(pwptr->pw_name);
-    }
-    if ((grptr = getgrgid(sbuf.st_gid)) == NULL) {
-       group = alloc(NUM_STR_SIZE);
-       ap_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
-    } else {
-       group = stralloc(grptr->gr_name);
-    }
-    dbprintf(("%s: processing file: %s\n", debug_prefix_time(NULL), name));
-    dbprintf(("%s: owner=%s group=%s mode=%03o\n",
-             debug_prefix(NULL), owner, group, (int) (sbuf.st_mode & 0777)));
-    amfree(name);
-    amfree(owner);
-    amfree(group);
-}
-#endif                                                         /* } */
-
-#ifdef KRB4_SECURITY                                           /* { */
-#include "krb4-security.c"
-#endif                                                         /* } */
+    assert(name != NULL);
 
-int bsd_security_ok P((struct sockaddr_in *addr,
-                      char *str, uint32_t cksum, char **errstr));
+    for (i = 0; i < NDRIVERS; i++)
+       if (strcasecmp(name, drivers[i]->name) == 0)
+           return (drivers[i]);
+    return (NULL);
+}
 
-char *get_bsd_security()
+/*
+ * For the drivers: initialize the common part of a security_handle_t
+ */
+void
+security_handleinit(handle, driver)
+    security_handle_t *handle;
+    const security_driver_t *driver;
 {
-    struct passwd *pwptr;
 
-    if((pwptr = getpwuid(getuid())) == NULL)
-       error("can't get login name for my uid %ld", (long)getuid());
-    return stralloc2("SECURITY USER ", pwptr->pw_name);
+    handle->driver = driver;
+    handle->error = stralloc("unknown protocol error");
 }
 
-int security_ok(addr, str, cksum, errstr)
-struct sockaddr_in *addr;
-char *str;
-uint32_t cksum;
-char **errstr;
+printf_arglist_function1(void security_seterror, security_handle_t *, handle,
+    const char *, fmt)
 {
-#ifdef KRB4_SECURITY                                           /* { */
-    if(krb4_auth)
-       return krb4_security_ok(addr, str, cksum, errstr);
-    else
-#endif                                                         /* } */
-       return bsd_security_ok(addr, str, cksum, errstr);
+    static char buf[256];
+    va_list argp;
+
+    assert(handle->error != NULL);
+    arglist_start(argp, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, argp);
+    arglist_end(argp);
+    handle->error = newstralloc(handle->error, buf);
 }
 
-#ifdef BSD_SECURITY                                            /* { */
-
-int bsd_security_ok(addr, str, cksum, errstr)
-     struct sockaddr_in *addr;
-     char *str;
-     uint32_t cksum;
-     char **errstr;
+void
+security_close(handle)
+    security_handle_t *handle;
 {
-    char *remotehost = NULL, *remoteuser = NULL, *localuser = NULL;
-    char *bad_bsd = NULL;
-    struct hostent *hp;
-    struct passwd *pwptr;
-    int myuid, i, j;
-    char *s, *fp;
-    int ch;
-    char number[NUM_STR_SIZE];
-#ifdef USE_AMANDAHOSTS                                         /* { */
-    FILE *fPerm;
-    char *pbuf = NULL;
-    char *ptmp;
-    int pbuf_len;
-    int amandahostsauth = 0;
-#else                                                          /* } { */
-    FILE *fError;
-    int saved_stderr;
-    int fd[2];
-    amwait_t wait_exitcode;
-    int exitcode;
-    pid_t pid, ruserok_pid;
-#endif                                                         /* } */
-
-    *errstr = NULL;
-
-    /* what host is making the request? */
-
-    hp = gethostbyaddr((char *)&addr->sin_addr, (int)sizeof(addr->sin_addr),
-                      AF_INET);
-    if(hp == NULL) {
-       /* XXX include remote address in message */
-       *errstr = vstralloc("[",
-                           "addr ", inet_ntoa(addr->sin_addr), ": ",
-                           "hostname lookup failed",
-                           "]", NULL);
-       return 0;
-    }
-    remotehost = stralloc(hp->h_name);
-
-    /* Now let's get the hostent for that hostname */
-    hp = gethostbyname( remotehost );
-    if(hp == NULL) {
-       /* XXX include remote hostname in message */
-       *errstr = vstralloc("[",
-                           "host ", remotehost, ": ",
-                           "hostname lookup failed",
-                           "]", NULL);
-       amfree(remotehost);
-       return 0;
-    }
-
-    /* Verify that the hostnames match -- they should theoretically */
-    if( strncasecmp( remotehost, hp->h_name, strlen(remotehost)+1 ) != 0 ) {
-       *errstr = vstralloc("[",
-                           "hostnames do not match: ",
-                           remotehost, " ", hp->h_name,
-                           "]", NULL);
-       amfree(remotehost);
-       return 0;
-    }
-
-    /* Now let's verify that the ip which gave us this hostname
-     * is really an ip for this hostname; or is someone trying to
-     * break in? (THIS IS THE CRUCIAL STEP)
-     */
-    for (i = 0; hp->h_addr_list[i]; i++) {
-       if (memcmp(hp->h_addr_list[i],
-                  (char *) &addr->sin_addr, sizeof(addr->sin_addr)) == 0)
-           break;                     /* name is good, keep it */
-    }
-
-    /* If we did not find it, your DNS is messed up or someone is trying
-     * to pull a fast one on you. :(
-     */
-
-   /*   Check even the aliases list. Work around for Solaris if dns goes over NIS */
-
-    if( !hp->h_addr_list[i] ) {
-        for (j = 0; hp->h_aliases[j] !=0 ; j++) {
-            if ( strcmp(hp->h_aliases[j],inet_ntoa(addr->sin_addr)) == 0)
-                break;                          /* name is good, keep it */
-        }
-       if( !hp->h_aliases[j] ) {
-           *errstr = vstralloc("[",
-                               "ip address ", inet_ntoa(addr->sin_addr),
-                               " is not in the ip list for ", remotehost,
-                               "]",
-                               NULL);
-           amfree(remotehost);
-           return 0;
-       }
-    }
-
-    /* next, make sure the remote port is a "reserved" one */
-
-    if(ntohs(addr->sin_port) >= IPPORT_RESERVED) {
-       ap_snprintf(number, sizeof(number), "%d", ntohs(addr->sin_port));
-       *errstr = vstralloc("[",
-                           "host ", remotehost, ": ",
-                           "port ", number, " not secure",
-                           "]", NULL);
-       amfree(remotehost);
-       return 0;
-    }
-
-    /* extract the remote user name from the message */
 
-    s = str;
-    ch = *s++;
-
-    bad_bsd = vstralloc("[",
-                       "host ", remotehost, ": ",
-                       "bad bsd security line",
-                       "]", NULL);
-
-#define sc "USER "
-    if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
-       *errstr = bad_bsd;
-       bad_bsd = NULL;
-       amfree(remotehost);
-       return 0;
-    }
-    s += sizeof(sc)-1;
-    ch = s[-1];
-#undef sc
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       *errstr = bad_bsd;
-       bad_bsd = NULL;
-       amfree(remotehost);
-       return 0;
-    }
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    remoteuser = stralloc(fp);
-    s[-1] = ch;
-    amfree(bad_bsd);
-
-    /* lookup our local user name */
-
-    myuid = getuid();
-    if((pwptr = getpwuid(myuid)) == NULL) {
-        error("error [getpwuid(%d) fails]", myuid);
-    }
-
-    localuser = stralloc(pwptr->pw_name);
-
-    dbprintf(("%s: bsd security: remote host %s user %s local user %s\n",
-             debug_prefix_time(NULL), remotehost, remoteuser, localuser));
-
-#ifndef USE_AMANDAHOSTS                                                /* { */
-    /*
-     * Note that some versions of ruserok (eg SunOS 3.2) look in
-     * "./.rhosts" rather than "~localuser/.rhosts", so we have to
-     * change directories ourselves.  Sigh.
-     *
-     * And, believe it or not, some ruserok()'s try an initgroup just
-     * for the hell of it.  Since we probably aren't root at this point
-     * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
-     * into our stderr output even though the initgroup failure is not a
-     * problem and is expected.  Thanks a lot.  Not.
-     */
-    if (pipe(fd) != 0) {
-       error("error [pipe() fails]");
-    }
-    if ((ruserok_pid = fork ()) < 0) {
-       error("error [fork() fails]");
-    } else if (ruserok_pid == 0) {
-       close(fd[0]);
-       fError = fdopen(fd[1], "w");
-       /* pamper braindead ruserok's */
-       if(chdir(pwptr->pw_dir) != 0) {
-           fprintf(fError, "[chdir(%s) failed: %s]",
-                   pwptr->pw_dir, strerror(errno));
-           fclose(fError);
-           exit(1);
-       }
-
-#if defined(SHOW_SECURITY_DETAIL)                              /* { */
-       {
-       char *dir = stralloc(pwptr->pw_dir);
-
-       dbprintf(("%s: calling ruserok(%s, %d, %s, %s)\n",
-                 debug_prefix_time(NULL),
-                 remotehost, myuid == 0, remoteuser, localuser));
-       if (myuid == 0) {
-           dbprintf(("%s: because you are running as root, ",
-                     debug_prefix(NULL)));
-           dbprintf(("/etc/hosts.equiv will not be used\n"));
-       } else {
-           show_stat_info("/etc/hosts.equiv", NULL);
-       }
-       show_stat_info(dir, "/.rhosts");
-       amfree(dir);
-       }
-#endif                                                         /* } */
-
-       saved_stderr = dup(2);
-       close(2);
-       (void)open("/dev/null", 2);
-
-       if(ruserok(remotehost, myuid == 0, remoteuser, localuser) == -1) {
-           dup2(saved_stderr,2);
-           close(saved_stderr);
-           *errstr = vstralloc("[",
-                               "access as ", localuser, " not allowed",
-                               " from ", remoteuser, "@", remotehost,
-                               "] ruserok failed",
-                               NULL);
-           fputs(*errstr, fError);
-           fputc('\n', fError);
-           fclose(fError);
-           dbprintf(("%s: check failed: %s\n",
-                     debug_prefix_time(NULL), *errstr));
-           amfree(*errstr);
-           exit(1);
-       }
-
-       dup2(saved_stderr,2);
-       close(saved_stderr);
-       dbprintf(("%s: bsd security check to %s from %s@%s passed\n",
-                 debug_prefix_time(NULL),
-                 localuser, remoteuser, remotehost));
-       amfree(remotehost);
-       amfree(remoteuser);
-       amfree(remoteuser);
-       exit(0);
-    }
-    close(fd[1]);
-    fError = fdopen(fd[0], "r");
-
-    while((pid = wait(&wait_exitcode)) == (pid_t)-1 && errno == EINTR) {}
-    if (pid == (pid_t)-1) {
-       *errstr = vstralloc("[",
-                           "access as ", localuser, " not allowed",
-                           " from ", remoteuser, "@", remotehost,
-                           "] wait failed: ",
-                           strerror(errno),
-                           NULL);
-       exitcode = 0;
-    } else if (pid != ruserok_pid) {
-       ap_snprintf(number, sizeof(number), "%ld", (long)pid);
-       *errstr = vstralloc("[",
-                           "access as ", localuser, " not allowed",
-                           " from ", remoteuser, "@", remotehost,
-                           "] wait got pid ",
-                           number,
-                           NULL);
-       exitcode = 0;
-    } else if (WIFSIGNALED(wait_exitcode)) {
-       ap_snprintf(number, sizeof(number), "%d", WTERMSIG(wait_exitcode));
-       *errstr = vstralloc("[",
-                           "access as ", localuser, " not allowed",
-                           " from ", remoteuser, "@", remotehost,
-                           "] got signal ", number,
-                           NULL);
-       exitcode = 0;
-    } else {
-       exitcode = WEXITSTATUS(wait_exitcode);
-    }
-    if(exitcode) {
-       if((*errstr = agets(fError)) == NULL) {
-           *errstr = vstralloc("[",
-                               "access as ", localuser, " not allowed",
-                               " from ", remoteuser, "@", remotehost,
-                               "] could not get result",
-                               NULL);
-       }
-    }
-    fclose(fError);
-    amfree(remotehost);
-    amfree(localuser);
-    amfree(remoteuser);
-    return *errstr == NULL;
-#else                                                          /* } { */
-#if defined(SHOW_SECURITY_DETAIL)                              /* { */
-    show_stat_info(pwptr->pw_dir, "/.amandahosts");
-#endif                                                         /* } */
-
-    ptmp = stralloc2(pwptr->pw_dir, "/.amandahosts");
-    if((fPerm = fopen(ptmp, "r")) == NULL) {
-       /*
-        * Put an explanation in the amandad.debug log that will help a
-        * system administrator fix the problem, but don't send a clue
-        * back to the other end to tell them what to fix in order to
-        * be able to hack our system.
-         */
-       dbprintf(("%s: fopen of %s failed: %s\n",
-                 debug_prefix_time(NULL), ptmp, strerror(errno)));
-       *errstr = vstralloc("[",
-                           "access as ", localuser, " not allowed",
-                           " from ", remoteuser, "@", remotehost,
-                           "] open of ",
-                           ptmp,
-                           " failed", NULL);
-       amfree(ptmp);
-       amfree(remotehost);
-       amfree(localuser);
-       amfree(remoteuser);
-       return 0;
-    }
-    amfree(ptmp);
-
-    for(; (pbuf = agets(fPerm)) != NULL; free(pbuf)) {
-#if defined(SHOW_SECURITY_DETAIL)                              /* { */
-       dbprintf(("%s: processing line: <%s>\n", debug_prefix(NULL), pbuf));
-#endif                                                         /* } */
-       pbuf_len = strlen(pbuf);
-       s = pbuf;
-       ch = *s++;
-
-       /* Find end of remote host */
-       skip_non_whitespace(s, ch);
-       if(s - 1 == pbuf) {
-           memset(pbuf, '\0', pbuf_len);       /* leave no trace */
-           continue;                           /* no remotehost field */
-       }
-       s[-1] = '\0';                           /* terminate remotehost field */
-
-       /* Find start of remote user */
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           ptmp = localuser;                   /* no remoteuser field */
-       } else {
-           ptmp = s-1;                         /* start of remoteuser field */
-
-           /* Find end of remote user */
-           skip_non_whitespace(s, ch);
-           s[-1] = '\0';                       /* terminate remoteuser field */
-       }
-#if defined(SHOW_SECURITY_DETAIL)                              /* { */
-       dbprintf(("%s: comparing %s with\n", debug_prefix(NULL), pbuf));
-       dbprintf(("%s:           %s (%s)\n",
-                 debug_prefix(NULL), remotehost,
-                 (strcasecmp(pbuf, remotehost) == 0) ? "match" : "no match"));
-       dbprintf(("%s:       and %s with\n", debug_prefix(NULL), ptmp));
-       dbprintf(("%s:           %s (%s)\n",
-                 debug_prefix(NULL), remoteuser,
-                 (strcasecmp(ptmp, remoteuser) == 0) ? "match" : "no match"));
-#endif                                                         /* } */
-       if(strcasecmp(pbuf, remotehost) == 0
-          && strcasecmp(ptmp, remoteuser) == 0) {
-           amandahostsauth = 1;
-           break;
-       }
-       memset(pbuf, '\0', pbuf_len);           /* leave no trace */
-    }
-    afclose(fPerm);
-    amfree(pbuf);
-
-    if(amandahostsauth) {
-       dbprintf(("%s: amandahosts security check passed\n",
-                 debug_prefix_time(NULL)));
-       amfree(remotehost);
-       amfree(localuser);
-       amfree(remoteuser);
-       return 1;
-    }
-
-    *errstr = vstralloc("[",
-                       "access as ", localuser, " not allowed",
-                       " from ", remoteuser, "@", remotehost,
-                       "] amandahostsauth failed", NULL);
-    dbprintf(("%s: check failed: %s\n", debug_prefix_time(NULL), *errstr));
+    amfree(handle->error);
+    (*handle->driver->close)(handle);
+}
 
-    amfree(remotehost);
-    amfree(localuser);
-    amfree(remoteuser);
-    return 0;
+/*
+ * For the drivers: initialize the common part of a security_stream_t
+ */
+void
+security_streaminit(stream, driver)
+    security_stream_t *stream;
+    const security_driver_t *driver;
+{
 
-#endif                                                         /* } */
+    stream->driver = driver;
+    stream->error = stralloc("unknown stream error");
 }
 
-#else  /* ! BSD_SECURITY */                                    /* } { */
-
-int bsd_security_ok(addr, str, cksum, errstr)
-struct sockaddr_in *addr;
-char *str;
-uint32_t cksum;
-char **errstr;
+printf_arglist_function1(void security_stream_seterror,
+    security_stream_t *, stream,
+    const char *, fmt)
 {
-#if defined(SHOW_SECURITY_DETAIL)                              /* { */
-    dbprintf(("You configured Amanda using --without-bsd-security, so it\n"));
-    dbprintf(("will let anyone on the Internet connect and do dumps of\n"));
-    dbprintf(("your system unless you have some other kind of protection,\n"));
-    dbprintf(("such as a firewall or TCP wrappers.\n"));
-#endif                                                         /* } */
-    return 1;
+    static char buf[256];
+    va_list argp;
+
+    assert(stream->error != NULL);
+    arglist_start(argp, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, argp);
+    arglist_end(argp);
+    stream->error = newstralloc(stream->error, buf);
 }
 
-#endif /* ! BSD_SECURITY */                                    /* } */
-
-#if defined(TEST)                                              /* { */
-
-int
-main (argc, argv)
+void
+security_stream_close(stream)
+    security_stream_t *stream;
 {
-    char *remoteuser;
-    char *remotehost;
-    struct hostent *hp;
-    struct sockaddr_in fake;
-    char *str;
-    char *errstr;
-    int r;
-    struct passwd      *pwent;
 
-    /*
-     * The following is stolen from amandad to emulate what it would
-     * do on startup.
-     */
-    if(client_uid == (uid_t) -1 && (pwent = getpwnam(CLIENT_LOGIN)) != NULL) {
-       client_uid = pwent->pw_uid;
-       client_gid = pwent->pw_gid;
-       endpwent();
-    }
-#ifdef FORCE_USERID
-
-    /* we'd rather not run as root */
-    if(geteuid() == 0) {
-#ifdef KRB4_SECURITY
-        if(client_uid == (uid_t) -1) {
-           error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN);
-       }
-
-        /*
-        * if we're using kerberos security, we'll need to be root in
-        * order to get at the machine's srvtab entry, so we hang on to
-        * some root privledges for now.  We give them up entirely later.
-        */
-       setegid(client_gid);
-       seteuid(client_uid);
-#else
-       initgroups(CLIENT_LOGIN, client_gid);
-       setgid(client_gid);
-       setuid(client_uid);
-#endif  /* KRB4_SECURITY */
-    }
-#endif /* FORCE_USERID */
-
-    fputs("Remote user: ", stdout);
-    fflush(stdout);
-    if ((remoteuser = agets(stdin)) == NULL) {
-       return 0;
-    }
-    str = stralloc2("USER ", remoteuser);
-
-    fputs("Remote host: ", stdout);
-    fflush(stdout);
-    if ((remotehost = agets(stdin)) == NULL) {
-       return 0;
-    }
-
-    set_pname("security");
-    startclock();
-
-    if ((hp = gethostbyname(remotehost)) == NULL) {
-       dbprintf(("%s: cannot look up remote host %s\n",
-                 debug_prefix_time(NULL), remotehost));
-       return 1;
-    }
-    memcpy((char *)&fake.sin_addr, (char *)hp->h_addr, sizeof(hp->h_addr));
-    fake.sin_port = htons(IPPORT_RESERVED - 1);
-
-    if ((r = bsd_security_ok(&fake, str, 0, &errstr)) == 0) {
-       dbprintf(("%s: security check of %s@%s failed\n",
-                 debug_prefix_time(NULL), remoteuser, remotehost));
-       dbprintf(("%s: %s\n", debug_prefix(NULL), errstr));
-    } else {
-       dbprintf(("%s: security check of %s@%s passed\n",
-                 debug_prefix_time(NULL), remoteuser, remotehost));
-    }
-    return r;
+    amfree(stream->error);
+    (*stream->driver->stream_close)(stream);
 }
-
-#endif                                                         /* } */
diff --git a/common-src/security.h b/common-src/security.h
new file mode 100644 (file)
index 0000000..9d8448e
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: security.h,v 1.11 2003/04/26 02:02:19 kovert Exp $
+ *
+ * security api
+ */
+#ifndef SECURITY_H
+#define        SECURITY_H
+
+struct security_handle;
+
+/*
+ * This is a type that gets passed to the security_recvpkt() and
+ * security_connect() callbacks.
+ * It details what the status of this callback is.
+ */
+typedef enum { S_OK, S_TIMEOUT, S_ERROR } security_status_t;
+
+/*
+ * This structure defines a security driver.  This driver abstracts
+ * common security actions behind a set of function pointers.  Macros
+ * mask this.
+ */
+typedef struct security_driver {
+    /*
+     * The name of this driver, eg, "BSD", "KRB4", etc...
+     */
+    const char *name;
+
+    /*
+     * Connects a security handle, for this driver to a remote
+     * host.
+     */
+    void (*connect) P((const char *,
+       char *(*)(char *, void *),
+       void (*)(void *, struct security_handle *, security_status_t),
+       void *));
+
+    /*
+     * This form sets up a callback that returns new handles as
+     * they are received.  It takes an input and output file descriptor.
+     */
+    void (*accept) P((int, int, void (*)(struct security_handle *, pkt_t *)));
+
+    /*
+     * Frees up handles allocated by the previous
+     */
+    void (*close) P((void *));
+
+    /*
+     * This transmits a packet after adding the security information
+     * Returns 0 on success, negative on error.
+     */
+    int (*sendpkt) P((void *, pkt_t *));
+
+    /*
+     * This creates an event in the event handler for receiving pkt_t's
+     * on a security_handle.  The given callback with the given arg
+     * will be called when the driver determines that it has data
+     * for that handle.  The last argument is a timeout, in seconds.
+     * This may be -1 to indicate no timeout.
+     *
+     * If there was an error or timeout, this will be indicated in
+     * the status argument.
+     * 
+     * Only one recvpkt request can exist per handle.
+     */
+    void (*recvpkt) P((void *, void (*)(void *, pkt_t *,
+       security_status_t), void *, int));
+
+    /*
+     * Cancel an outstanding recvpkt request on a handle.
+     */
+    void (*recvpkt_cancel) P((void *));
+
+    /*
+     * Get a stream given a security handle
+     */
+    void *(*stream_server) P((void *));
+
+    /*
+     * Accept a stream created by stream_server
+     */
+    int (*stream_accept) P((void *));
+
+    /*
+     * Get a stream and connect it to a remote given a security handle
+     * and a stream id.
+     */
+    void *(*stream_client) P((void *, int));
+
+    /*
+     * Close a stream opened with stream_server or stream_client
+     */
+    void (*stream_close) P((void *));
+
+    /*
+     * Authenticate a stream.
+     */
+    int (*stream_auth) P((void *));
+
+    /*
+     * Return a numeric id for a stream.
+     */
+    int (*stream_id) P((void *));
+
+    /*
+     * Write to a stream.
+     */
+    int (*stream_write) P((void *, const void *, size_t));
+
+    /*
+     * Read asyncronously from a stream.  Only one request can exist
+     * per stream.
+     */
+    void (*stream_read) P((void *, void (*)(void *, void *, ssize_t), void *));
+
+    /*
+     * Cancel a stream read request
+     */
+    void (*stream_read_cancel) P((void *));
+
+} security_driver_t;
+
+/*
+ * This structure is a handle to a connection to a host for transmission
+ * of protocol packets (pkt_t's).  The underlying security type defines
+ * the actual protocol and transport.
+ *
+ * This handle is reference counted so that it can be used inside of
+ * security streams after it has been closed by our callers.
+ */
+typedef struct security_handle {
+    const security_driver_t *driver;
+    char *error;
+} security_handle_t;
+
+/*
+ * This structure is a handle to a stream connection to a host for
+ * transmission of random data such as dumps or index data.
+ */
+typedef struct security_stream {
+    const security_driver_t *driver;
+    char *error;
+} security_stream_t;
+
+
+const security_driver_t *security_getdriver P((const char *));
+void security_handleinit P((security_handle_t *, const security_driver_t *));
+void security_streaminit P((security_stream_t *, const security_driver_t *));
+
+/* const char *security_geterror P((security_handle_t *)); */
+#define        security_geterror(handle)       ((handle)->error)
+void security_seterror P((security_handle_t *, const char *, ...))
+    __attribute__ ((format (printf, 2, 3)));
+
+
+/* void security_connect P((const security_driver_t *, const char *,
+    void (*)(void *, security_handle_t *, security_status_t), void *)); */
+#define        security_connect(driver, hostname, conf_fn, fn, arg)    \
+    (*(driver)->connect)(hostname, conf_fn, fn, arg)
+/* void security_accept P((const security_driver_t *, int, int,
+    void (*)(security_handle_t *, pkt_t *))); */
+#define        security_accept(driver, in, out, fn)    \
+    (*(driver)->accept)(in, out, fn)
+void security_close P((security_handle_t *));
+
+/* int security_sendpkt P((security_handle_t *, const pkt_t *)); */
+#define        security_sendpkt(handle, pkt)           \
+    (*(handle)->driver->sendpkt)(handle, pkt)
+
+/* void security_recvpkt P((security_handle_t *,
+    void (*)(void *, pkt_t *, security_status_t), void *, int); */
+#define        security_recvpkt(handle, fn, arg, timeout)      \
+    (*(handle)->driver->recvpkt)(handle, fn, arg, timeout)
+
+/* void security_recvpkt_cancel P((security_handle_t *)); */
+#define        security_recvpkt_cancel(handle)         \
+    (*(handle)->driver->recvpkt_cancel)(handle)
+
+/* const char *security_stream_geterror P((security_stream_t *)); */
+#define        security_stream_geterror(stream)        ((stream)->error)
+void security_stream_seterror P((security_stream_t *, const char *, ...))
+    __attribute__ ((format (printf, 2, 3)));
+
+/* security_stream_t *security_stream_server P((security_handle_t *)); */
+#define        security_stream_server(handle)  \
+    (*(handle)->driver->stream_server)(handle)
+
+/* int security_stream_accept P((security_stream_t *)); */
+#define        security_stream_accept(stream)          \
+    (*(stream)->driver->stream_accept)(stream)
+
+/* security_stream_t *security_stream_client P((security_handle_t *, int)); */
+#define        security_stream_client(handle, id)      \
+    (*(handle)->driver->stream_client)(handle, id)
+
+void security_stream_close P((security_stream_t *));
+
+/* int security_stream_auth P((security_stream_t *)); */
+#define        security_stream_auth(stream)            \
+    (*(stream)->driver->stream_auth)(stream)
+
+/* int security_stream_id P((security_stream_t *)); */
+#define        security_stream_id(stream)              \
+    (*(stream)->driver->stream_id)(stream)
+
+/* int security_stream_write P((security_stream_t *, const void *, size_t)); */
+#define        security_stream_write(stream, buf, size)        \
+    (*(stream)->driver->stream_write)(stream, buf, size)
+
+/* void security_stream_read P((security_stream_t *,
+    void (*)(void *, void *, size_t), void *)); */
+#define        security_stream_read(stream, fn, arg)           \
+    (*(stream)->driver->stream_read)(stream, fn, arg)
+
+/* void security_stream_read_cancel P((security_stream_t *)); */
+#define        security_stream_read_cancel(stream)             \
+    (*(stream)->driver->stream_read_cancel)(stream)
+
+#endif /* SECURITY_H */
index d991ab3ce539424d2ffa07c558f23b98f4b6d59f..44599602c265c6707bc8bb0f6256290215a803a6 100644 (file)
@@ -25,7 +25,7 @@
  *                         University of Maryland at College Park
  */
 /*
- * $Id: sl.c,v 1.1.2.2.2.2 2005/09/30 19:01:53 martinea Exp $
+ * $Id: sl.c,v 1.5 2005/09/30 19:01:43 martinea Exp $
  *
  * A doubly linked list of string (char *)
  */
index 5ab0e6e34911c165e1b755702573ad4f4ed7f2f8..a54a78470992ca4b9293ba6fca41a363d673db8d 100644 (file)
@@ -25,7 +25,7 @@
  *                         University of Maryland at College Park
  */
 /*
- * $Id: sl.h,v 1.1.2.1.2.1 2004/04/23 11:44:51 martinea Exp $
+ * $Id: sl.h,v 1.3 2004/04/23 11:44:46 martinea Exp $
  *
  * A doubly linked list of string (char *)
  */
index 10ec588a8a783ca36cdde9d4a49ab42b228857f5..fa060c9c309be5e7a3ec64ba31ab3f3b00904ad0 100644 (file)
@@ -1002,9 +1002,9 @@ va_list ap;
 
 
 /*
-int ap_snprintf(char *buf, size_t len, const char *format,...)
+int snprintf(char *buf, size_t len, const char *format,...)
 */
-printf_arglist_function2(int ap_snprintf,
+printf_arglist_function2(int snprintf,
                         char *, buf,
                         size_t, len,
                         const char *, format)
@@ -1020,9 +1020,9 @@ printf_arglist_function2(int ap_snprintf,
 
 
 /*
-int ap_vsnprintf(char *buf, size_t len, const char *format, va_list ap)
+int vsnprintf(char *buf, size_t len, const char *format, va_list ap)
 */
-int ap_vsnprintf(buf, len, format, ap)
+int vsnprintf(buf, len, format, ap)
 char *buf;
 size_t len;
 const char *format;
diff --git a/common-src/ssh-security.c b/common-src/ssh-security.c
new file mode 100644 (file)
index 0000000..17272f7
--- /dev/null
@@ -0,0 +1,1239 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1999 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+
+/*
+ * $Id: ssh-security.c,v 1.8 2006/02/17 00:58:51 ktill Exp $
+ *
+ * ssh-security.c - security and transport over ssh or a ssh-like command.
+ *
+ * XXX still need to check for initial keyword on connect so we can skip
+ * over shell garbage and other stuff that ssh might want to spew out.
+ */
+
+#include "amanda.h"
+#include "event.h"
+#include "packet.h"
+#include "queue.h"
+#include "security.h"
+#include "stream.h"
+#include "version.h"
+
+#ifdef SSH_SECURITY
+
+/*#define      SSH_DEBUG*/
+
+#ifdef SSH_DEBUG
+#define        sshprintf(x)    dbprintf(x)
+#else
+#define        sshprintf(x)
+#endif
+
+/*
+ * Path to the ssh binary.  This should be configurable.
+ */
+#define        SSH_PATH        "/usr/bin/ssh"
+
+/*
+ * Arguments to ssh.  This should also be configurable
+ */
+#define        SSH_ARGS        "-x", "-l", CLIENT_LOGIN
+
+/*
+ * Number of seconds ssh has to start up
+ */
+#define        CONNECT_TIMEOUT 20
+
+/*
+ * Magic values for ssh_conn->handle
+ */
+#define        H_TAKEN -1              /* ssh_conn->tok was already read */
+#define        H_EOF   -2              /* this connection has been shut down */
+
+/*
+ * This is a ssh connection to a host.  We should only have
+ * one connection per host.
+ */
+struct ssh_conn {
+    int read, write;                           /* pipes to ssh */
+    pid_t pid;                                 /* pid of ssh process */
+    char pkt[NETWORK_BLOCK_BYTES];             /* last pkt read */
+    unsigned long pktlen;                      /* len of above */
+    struct {                                   /* buffer read() calls */
+       char buf[STREAM_BUFSIZE];               /* buffer */
+       size_t left;                    /* unread data */
+       ssize_t size;                   /* size of last read */
+    } readbuf;
+    event_handle_t *ev_read;                   /* read (EV_READFD) handle */
+    int ev_read_refcnt;                                /* number of readers */
+    char hostname[MAX_HOSTNAME_LENGTH+1];      /* host we're talking to */
+    char *errmsg;                              /* error passed up */
+    int refcnt;                                        /* number of handles using */
+    int handle;                                        /* last proto handle read */
+    TAILQ_ENTRY(ssh_conn) tq;                  /* queue handle */
+};
+
+
+struct ssh_stream;
+
+/*
+ * This is the private handle data.
+ */
+struct ssh_handle {
+    security_handle_t sech;            /* MUST be first */
+    char *hostname;                    /* ptr to rc->hostname */
+    struct ssh_stream *rs;             /* virtual stream we xmit over */
+
+    union {
+       void (*recvpkt) P((void *, pkt_t *, security_status_t));
+                                       /* func to call when packet recvd */
+       void (*connect) P((void *, security_handle_t *, security_status_t));
+                                       /* func to call when connected */
+    } fn;
+    void *arg;                         /* argument to pass function */
+    event_handle_t *ev_timeout;                /* timeout handle for recv */
+};
+
+/*
+ * This is the internal security_stream data for ssh.
+ */
+struct ssh_stream {
+    security_stream_t secstr;          /* MUST be first */
+    struct ssh_conn *rc;               /* physical connection */
+    int handle;                                /* protocol handle */
+    event_handle_t *ev_read;           /* read (EV_WAIT) event handle */
+    void (*fn) P((void *, void *, ssize_t));   /* read event fn */
+    void *arg;                         /* arg for previous */
+};
+
+/*
+ * Interface functions
+ */
+static int ssh_sendpkt P((void *, pkt_t *));
+static int ssh_stream_accept P((void *));
+static int ssh_stream_auth P((void *));
+static int ssh_stream_id P((void *));
+static int ssh_stream_write P((void *, const void *, size_t));
+static void *ssh_stream_client P((void *, int));
+static void *ssh_stream_server P((void *));
+static void ssh_accept P((int, int,
+    void (*)(security_handle_t *, pkt_t *)));
+static void ssh_close P((void *));
+static void ssh_connect P((const char *,
+    char *(*)(char *, void *), 
+    void (*)(void *, security_handle_t *, security_status_t), void *));
+static void ssh_recvpkt P((void *,
+    void (*)(void *, pkt_t *, security_status_t), void *, int));
+static void ssh_recvpkt_cancel P((void *));
+static void ssh_stream_close P((void *));
+static void ssh_stream_read P((void *, void (*)(void *, void *, ssize_t),
+    void *));
+static void ssh_stream_read_cancel P((void *));
+
+/*
+ * This is our interface to the outside world.
+ */
+const security_driver_t ssh_security_driver = {
+    "SSH",
+    ssh_connect,
+    ssh_accept,
+    ssh_close,
+    ssh_sendpkt,
+    ssh_recvpkt,
+    ssh_recvpkt_cancel,
+    ssh_stream_server,
+    ssh_stream_accept,
+    ssh_stream_client,
+    ssh_stream_close,
+    ssh_stream_auth,
+    ssh_stream_id,
+    ssh_stream_write,
+    ssh_stream_read,
+    ssh_stream_read_cancel,
+};
+
+/*
+ * This is a queue of open connections
+ */
+static struct {
+    TAILQ_HEAD(, ssh_conn) tailq;
+    int qlength;
+} connq = {
+    TAILQ_HEAD_INITIALIZER(connq.tailq), 0
+};
+#define        connq_first()           TAILQ_FIRST(&connq.tailq)
+#define        connq_next(rc)          TAILQ_NEXT(rc, tq)
+#define        connq_append(rc)        do {                                    \
+    TAILQ_INSERT_TAIL(&connq.tailq, rc, tq);                           \
+    connq.qlength++;                                                   \
+} while (0)
+#define        connq_remove(rc)        do {                                    \
+    assert(connq.qlength > 0);                                         \
+    TAILQ_REMOVE(&connq.tailq, rc, tq);                                        \
+    connq.qlength--;                                                   \
+} while (0)
+
+static int newhandle = 1;
+
+/*
+ * This is a function that should be called if a new security_handle_t is
+ * created.  If NULL, no new handles are created.
+ * It is passed the new handle and the received pkt
+ */
+static void (*accept_fn) P((security_handle_t *, pkt_t *));
+
+/*
+ * Local functions
+ */
+static void connect_callback P((void *));
+static void connect_timeout P((void *));
+static int send_token P((struct ssh_conn *, int, const void *, size_t));
+static int recv_token P((struct ssh_conn *, int));
+static void recvpkt_callback P((void *, void *, ssize_t));
+static void recvpkt_timeout P((void *));
+static void stream_read_callback P((void *));
+
+static int runssh P((struct ssh_conn *));
+static struct ssh_conn *conn_get P((const char *));
+static void conn_put P((struct ssh_conn *));
+static void conn_read P((struct ssh_conn *));
+static void conn_read_cancel P((struct ssh_conn *));
+static void conn_read_callback P((void *));
+static int net_writev P((int, struct iovec *, int));
+static ssize_t net_read P((struct ssh_conn *, void *, size_t, int));
+static int net_read_fillbuf P((struct ssh_conn *, int, int));
+static void parse_pkt P((pkt_t *, const void *, size_t));
+
+
+/*
+ * ssh version of a security handle allocator.  Logically sets
+ * up a network "connection".
+ */
+static void
+ssh_connect(hostname, conf_fn, fn, arg)
+    const char *hostname;
+    char *(*conf_fn) P((char *, void *));
+    void (*fn) P((void *, security_handle_t *, security_status_t));
+    void *arg;
+{
+    struct ssh_handle *rh;
+    struct hostent *he;
+
+    assert(fn != NULL);
+    assert(hostname != NULL);
+
+    sshprintf(("%s: ssh: ssh_connect: %s\n", debug_prefix_time(NULL), hostname));
+
+    rh = alloc(sizeof(*rh));
+    security_handleinit(&rh->sech, &ssh_security_driver);
+    rh->hostname = NULL;
+    rh->rs = NULL;
+    rh->ev_timeout = NULL;
+
+    if ((he = gethostbyname(hostname)) == NULL) {
+       security_seterror(&rh->sech,
+           "%s: could not resolve hostname", hostname);
+       (*fn)(arg, &rh->sech, S_ERROR);
+       return;
+    }
+    rh->hostname = he->h_name; /* will be replaced */
+    rh->rs = ssh_stream_client(rh, newhandle++);
+
+    if (rh->rs == NULL)
+       goto error;
+
+    rh->hostname = rh->rs->rc->hostname;
+
+    if (rh->rs->rc->pid < 0) {
+       /*
+        * We need to open a new connection.
+        *
+        * XXX need to eventually limit number of outgoing connections here.
+        */
+       if (runssh(rh->rs->rc) < 0) {
+           security_seterror(&rh->sech,
+               "can't connect to %s: %s", hostname, rh->rs->rc->errmsg);
+           goto error;
+       }
+    }
+    /*
+     * The socket will be opened async so hosts that are down won't
+     * block everything.  We need to register a write event
+     * so we will know when the socket comes alive.
+     *
+     * Overload rh->rs->ev_read to provide a write event handle.
+     * We also register a timeout.
+     */
+    rh->fn.connect = fn;
+    rh->arg = arg;
+    rh->rs->ev_read = event_register(rh->rs->rc->write, EV_WRITEFD,
+       connect_callback, rh);
+    rh->ev_timeout = event_register(CONNECT_TIMEOUT, EV_TIME,
+       connect_timeout, rh);
+
+    return;
+
+error:
+    (*fn)(arg, &rh->sech, S_ERROR);
+}
+
+/*
+ * Called when a ssh connection is finished connecting and is ready
+ * to be authenticated.
+ */
+static void
+connect_callback(cookie)
+    void *cookie;
+{
+    struct ssh_handle *rh = cookie;
+
+    event_release(rh->rs->ev_read);
+    rh->rs->ev_read = NULL;
+    event_release(rh->ev_timeout);
+    rh->ev_timeout = NULL;
+
+    (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
+}
+
+/*
+ * Called if a connection times out before completion.
+ */
+static void
+connect_timeout(cookie)
+    void *cookie;
+{
+    struct ssh_handle *rh = cookie;
+
+    event_release(rh->rs->ev_read);
+    rh->rs->ev_read = NULL;
+    event_release(rh->ev_timeout);
+    rh->ev_timeout = NULL;
+
+    (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
+}
+
+/*
+ * Setup to handle new incoming connections
+ */
+static void
+ssh_accept(in, out, fn)
+    int in, out;
+    void (*fn) P((security_handle_t *, pkt_t *));
+{
+    struct ssh_conn *rc;
+
+    rc = conn_get("unknown");
+    rc->read = in;
+    rc->write = out;
+    accept_fn = fn;
+    conn_read(rc);
+}
+
+/*
+ * Locate an existing connection to the given host, or create a new,
+ * unconnected entry if none exists.  The caller is expected to check
+ * for the lack of a connection (rc->read == -1) and set one up.
+ */
+static struct ssh_conn *
+conn_get(hostname)
+    const char *hostname;
+{
+    struct ssh_conn *rc;
+
+    sshprintf(("%s: ssh: conn_get: %s\n", debug_prefix_time(NULL), hostname));
+
+    for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {
+       if (strcasecmp(hostname, rc->hostname) == 0)
+           break;
+    }
+
+    if (rc != NULL) {
+       rc->refcnt++;
+       sshprintf(("%s: ssh: conn_get: exists, refcnt to %s is now %d\n", debug_prefix_time(NULL),
+           rc->hostname, rc->refcnt));
+       return (rc);
+    }
+
+    sshprintf(("%s: ssh: conn_get: creating new handle\n", debug_prefix_time(NULL)));
+    /*
+     * We can't be creating a new handle if we are the client
+     */
+    assert(accept_fn == NULL);
+    rc = alloc(sizeof(*rc));
+    rc->read = rc->write = -1;
+    rc->pid = -1;
+    rc->readbuf.left = 0;
+    rc->readbuf.size = 0;
+    rc->ev_read = NULL;
+    strncpy(rc->hostname, hostname, sizeof(rc->hostname) - 1);
+    rc->hostname[sizeof(rc->hostname) - 1] = '\0';
+    rc->errmsg = NULL;
+    rc->refcnt = 1;
+    rc->handle = -1;
+    connq_append(rc);
+    return (rc);
+}
+
+/*
+ * Delete a reference to a connection, and close it if it is the last
+ * reference.
+ */
+static void
+conn_put(rc)
+    struct ssh_conn *rc;
+{
+    amwait_t status;
+
+    assert(rc->refcnt > 0);
+    --rc->refcnt;
+    sshprintf(("%s: ssh: conn_put: decrementing refcnt for %s to %d\n", debug_prefix_time(NULL),
+       rc->hostname, rc->refcnt));
+    if (rc->refcnt > 0) {
+       return;
+    }
+    sshprintf(("%s: ssh: conn_put: closing connection to %s\n", debug_prefix_time(NULL), rc->hostname));
+    if (rc->read != -1)
+       aclose(rc->read);
+    if (rc->write != -1)
+       aclose(rc->write);
+    if (rc->pid != -1) {
+       waitpid(rc->pid, &status, WNOHANG);
+    }
+    if (rc->ev_read != NULL)
+       event_release(rc->ev_read);
+    if (rc->errmsg != NULL)
+       amfree(rc->errmsg);
+    connq_remove(rc);
+    amfree(rc);
+}
+
+/*
+ * Turn on read events for a conn.  Or, increase a ev_read_refcnt if we are
+ * already receiving read events.
+ */
+static void
+conn_read(rc)
+    struct ssh_conn *rc;
+{
+
+    if (rc->ev_read != NULL) {
+       rc->ev_read_refcnt++;
+       sshprintf(("%s: ssh: conn_read: incremented ev_read_refcnt to %d for %s\n", debug_prefix_time(NULL),
+           rc->ev_read_refcnt, rc->hostname));
+       return;
+    }
+    sshprintf(("%s: ssh: conn_read registering event handler for %s\n", debug_prefix_time(NULL),
+       rc->hostname));
+    rc->ev_read = event_register(rc->read, EV_READFD, conn_read_callback, rc);
+    rc->ev_read_refcnt = 1;
+}
+
+static void
+conn_read_cancel(rc)
+    struct ssh_conn *rc;
+{
+
+    --rc->ev_read_refcnt;
+    sshprintf(("%s: ssh: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n", debug_prefix_time(NULL),
+       rc->ev_read_refcnt, rc->hostname));
+    if(rc->ev_read_refcnt > 0) {
+       return;
+    }
+    sshprintf(("%s: ssh: conn_read_cancel: releasing event handler for %s\n", debug_prefix_time(NULL),
+       rc->hostname));
+    event_release(rc->ev_read);
+    rc->ev_read = NULL;
+}
+
+/*
+ * frees a handle allocated by the above
+ */
+static void
+ssh_close(inst)
+    void *inst;
+{
+    struct ssh_handle *rh = inst;
+
+    assert(rh != NULL);
+
+    sshprintf(("%s: ssh: closing handle to %s\n", debug_prefix_time(NULL), rh->hostname));
+
+    if (rh->rs != NULL) {
+       /* This may be null if we get here on an error */
+       ssh_recvpkt_cancel(rh);
+       security_stream_close(&rh->rs->secstr);
+    }
+    /* keep us from getting here again */
+    rh->sech.driver = NULL;
+    amfree(rh);
+}
+
+/*
+ * Forks a ssh to the host listed in rc->hostname
+ * Returns negative on error, with an errmsg in rc->errmsg.
+ */
+static int
+runssh(rc)
+    struct ssh_conn *rc;
+{
+    int rpipe[2], wpipe[2];
+    char *amandad_path;
+
+    if (pipe(rpipe) < 0 || pipe(wpipe) < 0) {
+       rc->errmsg = newvstralloc("pipe: ", strerror(errno), NULL);
+       return (-1);
+    }
+    switch (rc->pid = fork()) {
+    case -1:
+       rc->errmsg = newvstralloc("fork: ", strerror(errno), NULL);
+       aclose(rpipe[0]);
+       aclose(rpipe[1]);
+       aclose(wpipe[0]);
+       aclose(wpipe[1]);
+       return (-1);
+    case 0:
+       dup2(wpipe[0], 0);
+       dup2(rpipe[1], 1);
+       dup2(rpipe[1], 2);
+       break;
+    default:
+       rc->read = rpipe[0];
+       aclose(rpipe[1]);
+       rc->write = wpipe[1];
+       aclose(wpipe[0]);
+       return (0);
+    }
+
+    safe_fd(-1, 0);
+
+    amandad_path = vstralloc(libexecdir, "/", "amandad", versionsuffix(),
+       NULL);
+    execlp(SSH_PATH, SSH_PATH, SSH_ARGS, rc->hostname, amandad_path,
+       "-auth=ssh", NULL);
+    error("error: couldn't exec %s: %s", SSH_PATH, strerror(errno));
+
+    /* should nerver go here, shut up compiler warning */
+    return(-1);
+}
+
+/*
+ * Transmit a packet.
+ */
+static int
+ssh_sendpkt(cookie, pkt)
+    void *cookie;
+    pkt_t *pkt;
+{
+    char buf[sizeof(pkt_t)];
+    struct ssh_handle *rh = cookie;
+    size_t len;
+
+    assert(rh != NULL);
+    assert(pkt != NULL);
+
+    sshprintf(("%s: ssh: sendpkt: enter\n", debug_prefix_time(NULL)));
+
+    len = strlen(pkt->body) + 2;
+    buf[0] = (char)pkt->type;
+    strcpy(&buf[1], pkt->body);
+
+    sshprintf(("%s: ssh: sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n", debug_prefix_time(NULL),
+       pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body));
+
+    if (ssh_stream_write(rh->rs, buf, len) < 0) {
+       security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
+       return (-1);
+    }
+    return (0);
+}
+
+/*
+ * Set up to receive a packet asyncronously, and call back when
+ * it has been read.
+ */
+static void
+ssh_recvpkt(cookie, fn, arg, timeout)
+    void *cookie, *arg;
+    void (*fn) P((void *, pkt_t *, security_status_t));
+    int timeout;
+{
+    struct ssh_handle *rh = cookie;
+
+    assert(rh != NULL);
+
+    sshprintf(("%s: ssh: recvpkt registered for %s\n", debug_prefix_time(NULL), rh->hostname));
+
+    /*
+     * Reset any pending timeout on this handle
+     */
+    if (rh->ev_timeout != NULL)
+       event_release(rh->ev_timeout);
+
+    /*
+     * Negative timeouts mean no timeout
+     */
+    if (timeout < 0)
+       rh->ev_timeout = NULL;
+    else
+       rh->ev_timeout = event_register(timeout, EV_TIME, recvpkt_timeout, rh);
+
+    rh->fn.recvpkt = fn;
+    rh->arg = arg;
+    ssh_stream_read(rh->rs, recvpkt_callback, rh);
+}
+
+/*
+ * Remove a async receive request from the queue
+ */
+static void
+ssh_recvpkt_cancel(cookie)
+    void *cookie;
+{
+    struct ssh_handle *rh = cookie;
+
+    sshprintf(("%s: ssh: cancelling recvpkt for %s\n", debug_prefix_time(NULL), rh->hostname));
+
+    assert(rh != NULL);
+
+    ssh_stream_read_cancel(rh->rs);
+    if (rh->ev_timeout != NULL) {
+       event_release(rh->ev_timeout);
+       rh->ev_timeout = NULL;
+    }
+}
+
+/*
+ * This is called when a handle is woken up because data read off of the
+ * net is for it.
+ */
+static void
+recvpkt_callback(cookie, buf, bufsize)
+    void *cookie, *buf;
+    ssize_t bufsize;
+{
+    pkt_t pkt;
+    struct ssh_handle *rh = cookie;
+
+    assert(rh != NULL);
+
+    /*
+     * We need to cancel the recvpkt request before calling
+     * the callback because the callback may reschedule us.
+     */
+    ssh_recvpkt_cancel(rh);
+
+    switch (bufsize) {
+    case 0:
+       security_seterror(&rh->sech,
+           "EOF on read from %s", rh->hostname);
+       (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
+       return;
+    case -1:
+       security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
+       (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
+       return;
+    default:
+       break;
+    }
+
+    parse_pkt(&pkt, buf, bufsize);
+    sshprintf(("%s: ssh: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n", debug_prefix_time(NULL),
+       pkt_type2str(pkt.type), pkt.type, rh->hostname, pkt.body));
+    (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
+}
+
+/*
+ * This is called when a handle times out before receiving a packet.
+ */
+static void
+recvpkt_timeout(cookie)
+    void *cookie;
+{
+    struct ssh_handle *rh = cookie;
+
+    assert(rh != NULL);
+
+    sshprintf(("%s: ssh: recvpkt timeout for %s\n", debug_prefix_time(NULL), rh->hostname));
+
+    ssh_recvpkt_cancel(rh);
+    (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);
+}
+
+/*
+ * Create the server end of a stream.  For ssh, this means setup a stream
+ * object and allocate a new handle for it.
+ */
+static void *
+ssh_stream_server(h)
+    void *h;
+{
+    struct ssh_handle *rh = h;
+    struct ssh_stream *rs;
+
+    assert(rh != NULL);
+
+    rs = alloc(sizeof(*rs));
+    security_streaminit(&rs->secstr, &ssh_security_driver);
+    rs->rc = conn_get(rh->hostname);
+    /*
+     * Stream should already be setup!
+     */
+    if (rs->rc->read < 0) {
+       conn_put(rs->rc);
+       amfree(rs);
+       security_seterror(&rh->sech, "lost connection to %s", rh->hostname);
+       return (NULL);
+    }
+    rh->hostname = rs->rc->hostname;
+    /*
+     * so as not to conflict with the amanda server's handle numbers,
+     * we start at 5000 and work down
+     */
+    rs->handle = 5000 - newhandle++;
+    rs->ev_read = NULL;
+    sshprintf(("%s: ssh: stream_server: created stream %d\n", debug_prefix_time(NULL), rs->handle));
+    return (rs);
+}
+
+/*
+ * Accept an incoming connection on a stream_server socket
+ * Nothing needed for ssh.
+ */
+static int
+ssh_stream_accept(s)
+    void *s;
+{
+
+    return (0);
+}
+
+/*
+ * Return a connected stream.  For ssh, this means setup a stream
+ * with the supplied handle.
+ */
+static void *
+ssh_stream_client(h, id)
+    void *h;
+    int id;
+{
+    struct ssh_handle *rh = h;
+    struct ssh_stream *rs;
+
+    assert(rh != NULL);
+
+    if (id <= 0) {
+       security_seterror(&rh->sech,
+           "%d: invalid security stream id", id);
+       return (NULL);
+    }
+
+    rs = alloc(sizeof(*rs));
+    security_streaminit(&rs->secstr, &ssh_security_driver);
+    rs->handle = id;
+    rs->ev_read = NULL;
+    rs->rc = conn_get(rh->hostname);
+
+    sshprintf(("%s: ssh: stream_client: connected to stream %d\n", debug_prefix_time(NULL), id));
+
+    return (rs);
+}
+
+/*
+ * Close and unallocate resources for a stream.
+ */
+static void
+ssh_stream_close(s)
+    void *s;
+{
+    struct ssh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    sshprintf(("%s: ssh: stream_close: closing stream %d\n", debug_prefix_time(NULL), rs->handle));
+
+    ssh_stream_read_cancel(rs);
+    conn_put(rs->rc);
+    amfree(rs);
+}
+
+/*
+ * Authenticate a stream
+ * Nothing needed for ssh.  The connection is authenticated by sshd
+ * on startup.
+ */
+static int
+ssh_stream_auth(s)
+    void *s;
+{
+
+    return (0);
+}
+
+/*
+ * Returns the stream id for this stream.  This is just the local
+ * port.
+ */
+static int
+ssh_stream_id(s)
+    void *s;
+{
+    struct ssh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    return (rs->handle);
+}
+
+/*
+ * Write a chunk of data to a stream.  Blocks until completion.
+ */
+static int
+ssh_stream_write(s, buf, size)
+    void *s;
+    const void *buf;
+    size_t size;
+{
+    struct ssh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    sshprintf(("%s: ssh: stream_write: writing %d bytes to %s:%d\n", debug_prefix_time(NULL), size,
+       rs->rc->hostname, rs->handle));
+
+    if (send_token(rs->rc, rs->handle, buf, size) < 0) {
+       security_stream_seterror(&rs->secstr, rs->rc->errmsg);
+       return (-1);
+    }
+    return (0);
+}
+
+/*
+ * Submit a request to read some data.  Calls back with the given
+ * function and arg when completed.
+ */
+static void
+ssh_stream_read(s, fn, arg)
+    void *s, *arg;
+    void (*fn) P((void *, void *, ssize_t));
+{
+    struct ssh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    /*
+     * Only one read request can be active per stream.
+     */
+    if (rs->ev_read == NULL) {
+       rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
+           stream_read_callback, rs);
+       conn_read(rs->rc);
+    }
+    rs->fn = fn;
+    rs->arg = arg;
+}
+
+/*
+ * Cancel a previous stream read request.  It's ok if we didn't have a read
+ * scheduled.
+ */
+static void
+ssh_stream_read_cancel(s)
+    void *s;
+{
+    struct ssh_stream *rs = s;
+
+    assert(rs != NULL);
+
+    if (rs->ev_read != NULL) {
+       event_release(rs->ev_read);
+       rs->ev_read = NULL;
+       conn_read_cancel(rs->rc);
+    }
+}
+
+/*
+ * Callback for ssh_stream_read
+ */
+static void
+stream_read_callback(arg)
+    void *arg;
+{
+    struct ssh_stream *rs = arg;
+    assert(rs != NULL);
+
+    sshprintf(("%s: ssh: stream_read_callback: handle %d\n", debug_prefix_time(NULL), rs->handle));
+
+    /*
+     * Make sure this was for us.  If it was, then blow away the handle
+     * so it doesn't get claimed twice.  Otherwise, leave it alone.
+     *
+     * If the handle is EOF, pass that up to our callback.
+     */
+    if (rs->rc->handle == rs->handle) {
+       sshprintf(("%s: ssh: stream_read_callback: it was for us\n", debug_prefix_time(NULL)));
+       rs->rc->handle = H_TAKEN;
+    } else if (rs->rc->handle != H_EOF) {
+       sshprintf(("%s: ssh: stream_read_callback: not for us\n", debug_prefix_time(NULL)));
+       return;
+    }
+
+    /*
+     * Remove the event first, and then call the callback.
+     * We remove it first because we don't want to get in their
+     * way if they reschedule it.
+     */
+    ssh_stream_read_cancel(rs);
+
+    if (rs->rc->pktlen == 0) {
+       sshprintf(("%s: ssh: stream_read_callback: EOF\n", debug_prefix_time(NULL)));
+       (*rs->fn)(rs->arg, NULL, 0);
+       return;
+    }
+    sshprintf(("%s: ssh: stream_read_callback: read %ld bytes from %s:%d\n", debug_prefix_time(NULL),
+       rs->rc->pktlen, rs->rc->hostname, rs->handle));
+    (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
+}
+
+/*
+ * The callback for the netfd for the event handler
+ * Determines if this packet is for this security handle,
+ * and does the real callback if so.
+ */
+static void
+conn_read_callback(cookie)
+    void *cookie;
+{
+    struct ssh_conn *rc = cookie;
+    struct ssh_handle *rh;
+    pkt_t pkt;
+    int rval;
+
+    assert(cookie != NULL);
+
+    sshprintf(("%s: ssh: conn_read_callback\n",debug_prefix_time(NULL)));
+
+    /* Read the data off the wire.  If we get errors, shut down. */
+    rval = recv_token(rc, 5);
+    sshprintf(("%s: ssh: conn_read_callback: recv_token returned %d\n", debug_prefix_time(NULL), rval));
+    if (rval <= 0) {
+       rc->pktlen = 0;
+       rc->handle = H_EOF;
+       rval = event_wakeup((event_id_t)rc);
+       sshprintf(("%s: ssh: conn_read_callback: event_wakeup return %d\n", debug_prefix_time(NULL), rval));
+       /* delete our 'accept' reference */
+       if (accept_fn != NULL)
+           conn_put(rc);
+       accept_fn = NULL;
+       return;
+    }
+
+    /* If there are events waiting on this handle, we're done */
+    rval = event_wakeup((event_id_t)rc);
+    sshprintf(("%s: ssh: conn_read_callback: event_wakeup return %d\n", debug_prefix_time(NULL), rval));
+    if (rval > 0)
+       return;
+
+    /* If there is no accept fn registered, then drop the packet */
+    if (accept_fn == NULL)
+       return;
+
+    rh = alloc(sizeof(*rh));
+    security_handleinit(&rh->sech, &ssh_security_driver);
+    rh->hostname = rc->hostname;
+    rh->rs = ssh_stream_client(rh, rc->handle);
+    rh->ev_timeout = NULL;
+
+    sshprintf(("%s: ssh: new connection\n", debug_prefix_time(NULL)));
+    parse_pkt(&pkt, rc->pkt, rc->pktlen);
+    sshprintf(("%s: ssh: calling accept_fn\n", debug_prefix_time(NULL)));
+    (*accept_fn)(&rh->sech, &pkt);
+}
+
+static void
+parse_pkt(pkt, buf, bufsize)
+    pkt_t *pkt;
+    const void *buf;
+    size_t bufsize;
+{
+    const unsigned char *bufp = buf;
+
+    sshprintf(("%s: ssh: parse_pkt: parsing buffer of %d bytes\n", debug_prefix_time(NULL), bufsize));
+
+    pkt->type = (pktype_t)*bufp++;
+    bufsize--;
+
+    if (bufsize == 0) {
+       pkt->body[0] = '\0';
+    } else {
+       if (bufsize > sizeof(pkt->body) - 1)
+           bufsize = sizeof(pkt->body) - 1;
+       memcpy(pkt->body, bufp, bufsize);
+       pkt->body[sizeof(pkt->body) - 1] = '\0';
+    }
+
+    sshprintf(("%s: ssh: parse_pkt: %s (%d): \"%s\"\n", debug_prefix_time(NULL), pkt_type2str(pkt->type),
+       pkt->type, pkt->body));
+}
+
+
+/*
+ * Transmits a chunk of data over a ssh_handle, adding
+ * the necessary headers to allow the remote end to decode it.
+ */
+static int
+send_token(rc, handle, buf, len)
+    struct ssh_conn *rc;
+    int handle;
+    const void *buf;
+    size_t len;
+{
+    unsigned int netlength, nethandle;
+    struct iovec iov[3];
+
+    sshprintf(("%s: ssh: send_token: handle %d writing %d bytes to %s\n", debug_prefix_time(NULL), handle, len,
+       rc->hostname));
+
+    assert(sizeof(netlength) == 4);
+
+    /*
+     * Format is:
+     *   32 bit length (network byte order)
+     *   32 bit handle (network byte order)
+     *   data
+     */
+    netlength = htonl(len);
+    iov[0].iov_base = (void *)&netlength;
+    iov[0].iov_len = sizeof(netlength);
+
+    nethandle = htonl(handle);
+    iov[1].iov_base = (void *)&nethandle;
+    iov[1].iov_len = sizeof(nethandle);
+
+    iov[2].iov_base = (void *)buf;
+    iov[2].iov_len = len;
+
+    if (net_writev(rc->write, iov, 3) < 0) {
+       rc->errmsg = newvstralloc(rc->errmsg, "ssh write error to ",
+           rc->hostname, ": ", strerror(errno), NULL);
+       return (-1);
+    }
+    return (0);
+}
+
+static int
+recv_token(rc, timeout)
+    struct ssh_conn *rc;
+    int timeout;
+{
+    unsigned int netint;
+
+    assert(sizeof(netint) == 4);
+
+    assert(rc->read >= 0);
+
+    sshprintf(("%s: ssh: recv_token: reading from %s\n", debug_prefix_time(NULL), rc->hostname));
+
+    switch (net_read(rc, &netint, sizeof(netint), timeout)) {
+    case -1:
+       rc->errmsg = newvstralloc(rc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       sshprintf(("%s: ssh: recv_token: A return(-1)\n", debug_prefix_time(NULL)));
+       return (-1);
+    case 0:
+       rc->pktlen = 0;
+       sshprintf(("%s: ssh: recv_token: A return(0)\n", debug_prefix_time(NULL)));
+       return (0);
+    default:
+       break;
+    }
+    rc->pktlen = ntohl(netint);
+    if (rc->pktlen > sizeof(rc->pkt)) {
+       rc->errmsg = newstralloc(rc->errmsg, "recv error: huge packet");
+       sshprintf(("%s: ssh: recv_token: B return(-1)\n", debug_prefix_time(NULL)));
+       return (-1);
+    }
+
+    switch (net_read(rc, &netint, sizeof(netint), timeout)) {
+    case -1:
+       rc->errmsg = newvstralloc(rc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       sshprintf(("%s: ssh: recv_token: C return(-1)\n", debug_prefix_time(NULL)));
+       return (-1);
+    case 0:
+       rc->pktlen = 0;
+       sshprintf(("%s: ssh: recv_token: D return(0)\n", debug_prefix_time(NULL)));
+       return (0);
+    default:
+       break;
+    }
+    rc->handle = ntohl(netint);
+
+    switch (net_read(rc, rc->pkt, rc->pktlen, timeout)) {
+    case -1:
+       rc->errmsg = newvstralloc(rc->errmsg, "recv error: ", strerror(errno),
+           NULL);
+       sshprintf(("%s: ssh: recv_token: E return(-1)\n", debug_prefix_time(NULL)));
+       return (-1);
+    case 0:
+       rc->pktlen = 0;
+       break;
+    default:
+       break;
+    }
+
+    sshprintf(("%s: ssh: recv_token: read %ld bytes from %s\n", debug_prefix_time(NULL), rc->pktlen,
+       rc->hostname));
+    sshprintf(("%s: ssh: recv_token: end %d\n", debug_prefix_time(NULL),rc->pktlen));
+    return (rc->pktlen);
+}
+
+/*
+ * Writes out the entire iovec
+ */
+static int
+net_writev(fd, iov, iovcnt)
+    int fd, iovcnt;
+    struct iovec *iov;
+{
+    int delta, n, total;
+
+    assert(iov != NULL);
+
+    total = 0;
+    while (iovcnt > 0) {
+       /*
+        * Write the iovec
+        */
+       total += n = writev(fd, iov, iovcnt);
+       if (n < 0)
+           return (-1);
+       if (n == 0) {
+           errno = EIO;
+           return (-1);
+       }
+       /*
+        * Iterate through each iov.  Figure out what we still need
+        * to write out.
+        */
+       for (; n > 0; iovcnt--, iov++) {
+           /* 'delta' is the bytes written from this iovec */
+           delta = n < iov->iov_len ? n : iov->iov_len;
+           /* subtract from the total num bytes written */
+           n -= delta;
+           assert(n >= 0);
+           /* subtract from this iovec */
+           iov->iov_len -= delta;
+           iov->iov_base = (char *)iov->iov_base + delta;
+           /* if this iovec isn't empty, run the writev again */
+           if (iov->iov_len > 0)
+               break;
+       }
+    }
+    return (total);
+}
+
+/*
+ * Like read(), but waits until the entire buffer has been filled.
+ */
+static ssize_t
+net_read(rc, vbuf, origsize, timeout)
+    struct ssh_conn *rc;
+    void *vbuf;
+    size_t origsize;
+    int timeout;
+{
+    char *buf = vbuf, *off;    /* ptr arith */
+    int nread;
+    size_t size = origsize;
+
+    sshprintf(("%s: ssh: net_read: begin %d\n", debug_prefix_time(NULL), origsize));
+    while (size > 0) {
+       sshprintf(("%s: ssh: net_read: while %d\n", debug_prefix_time(NULL), size));
+       if (rc->readbuf.left == 0) {
+           if (net_read_fillbuf(rc, timeout, size) < 0) {
+               sshprintf(("%s: ssh: net_read: end retrun(-1)\n", debug_prefix_time(NULL)));
+               return (-1);
+           }
+           if (rc->readbuf.size == 0) {
+               sshprintf(("%s: ssh: net_read: end retrun(0)\n", debug_prefix_time(NULL)));
+               return (0);
+           }
+       }
+       nread = min(rc->readbuf.left, size);
+       off = rc->readbuf.buf + rc->readbuf.size - rc->readbuf.left;
+       memcpy(buf, off, nread);
+
+       buf += nread;
+       size -= nread;
+       rc->readbuf.left -= nread;
+    }
+    sshprintf(("%s: ssh: net_read: end %d\n", debug_prefix_time(NULL), origsize));
+    return ((ssize_t)origsize);
+}
+
+/*
+ * net_read likes to do a lot of little reads.  Buffer it.
+ */
+static int
+net_read_fillbuf(rc, timeout, size)
+    struct ssh_conn *rc;
+    int timeout;
+    int size;
+{
+    fd_set readfds;
+    struct timeval tv;
+    if(size > sizeof(rc->readbuf.buf)) size = sizeof(rc->readbuf.buf);
+
+    sshprintf(("%s: ssh: net_read_fillbuf: begin\n", debug_prefix_time(NULL)));
+    FD_ZERO(&readfds);
+    FD_SET(rc->read, &readfds);
+    tv.tv_sec = timeout;
+    tv.tv_usec = 0;
+    switch (select(rc->read + 1, &readfds, NULL, NULL, &tv)) {
+    case 0:
+       errno = ETIMEDOUT;
+       /* FALLTHROUGH */
+    case -1:
+       sshprintf(("%s: ssh: net_read_fillbuf: case -1\n", debug_prefix_time(NULL)));
+       return (-1);
+    case 1:
+       sshprintf(("%s: ssh: net_read_fillbuf: case 1\n", debug_prefix_time(NULL)));
+       assert(FD_ISSET(rc->read, &readfds));
+       break;
+    default:
+       sshprintf(("%s: ssh: net_read_fillbuf: case default\n", debug_prefix_time(NULL)));
+       assert(0);
+       break;
+    }
+    rc->readbuf.left = 0;
+    rc->readbuf.size = read(rc->read, rc->readbuf.buf, size);
+    if (rc->readbuf.size < 0)
+       return (-1);
+    rc->readbuf.left = rc->readbuf.size;
+    sshprintf(("%s: ssh: net_read_fillbuf: end %d\n", debug_prefix_time(NULL),rc->readbuf.size));
+    return (0);
+}
+
+#endif /* SSH_SECURITY */
index 5ab78d9661d022f1bdfbbf96a5ebbf17678c4993..5f5270feebd28e7340b045e09c95603c34d9b661 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: statfs.c,v 1.10.4.1.8.2 2005/09/30 19:13:36 martinea Exp $
+ * $Id: statfs.c,v 1.13 2005/09/30 19:13:27 martinea Exp $
  *
  * a generic statfs-like routine
  */
index 100450d0e4b81246968b32378106af9b3c6fd2f9..b5e24456e7cc64355b77367d064f87dcf198de6b 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: stream.c,v 1.10.2.6.4.4.2.4.2.1 2005/10/02 13:48:42 martinea Exp $
+ * $Id: stream.c,v 1.31 2006/01/14 04:37:19 paddy_s Exp $
  *
  * functions for managing stream sockets
  */
 #include "amanda.h"
 #include "dgram.h"
 #include "stream.h"
-#include "clock.h"
 #include "util.h"
 
 /* local functions */
@@ -83,17 +82,19 @@ int sendsize, recvsize;
      * If a port range was specified, we try to get a port in that
      * range first.  Next, we try to get a reserved port.  If that
      * fails, we just go for any port.
+     * 
+     * In all cases, not to use port that's assigned to other services. 
      *
      * It is up to the caller to make sure we have the proper permissions
      * to get the desired port, and to make sure we return a port that
      * is within the range it requires.
      */
 #ifdef TCPPORTRANGE
-    if (bind_portrange(server_socket, &server, TCPPORTRANGE) == 0)
+    if (bind_portrange(server_socket, &server, TCPPORTRANGE, "tcp") == 0)
        goto out;
 #endif
 
-    if (bind_portrange(server_socket, &server, 512, IPPORT_RESERVED - 1) == 0)
+    if (bind_portrange(server_socket, &server, 512, IPPORT_RESERVED - 1, "tcp") == 0)
        goto out;
 
     server.sin_port = INADDR_ANY;
@@ -146,9 +147,15 @@ out:
 }
 
 static int
-stream_client_internal(hostname, port, sendsize, recvsize, localport, priv)
-    char *hostname;
-    int port, sendsize, recvsize, *localport, priv;
+stream_client_internal(hostname,
+                      port,
+                      sendsize,
+                      recvsize,
+                      localport,
+                      nonblock,
+                      priv)
+    const char *hostname;
+    int port, sendsize, recvsize, *localport, nonblock, priv;
 {
     int client_socket;
     socklen_t len;
@@ -195,7 +202,7 @@ stream_client_internal(hostname, port, sendsize, recvsize, localport, priv)
 
 #ifdef SO_KEEPALIVE
     r = setsockopt(client_socket, SOL_SOCKET, SO_KEEPALIVE,
-                  (void *)&on, sizeof(on));
+       (void *)&on, sizeof(on));
     if(r == -1) {
        save_errno = errno;
        dbprintf(("%s: %s: setsockopt() failed: %s\n",
@@ -225,7 +232,7 @@ stream_client_internal(hostname, port, sendsize, recvsize, localport, priv)
     if (priv) {
        int b;
 
-       b = bind_portrange(client_socket, &claddr, 512, IPPORT_RESERVED - 1);
+       b = bind_portrange(client_socket, &claddr, 512, IPPORT_RESERVED - 1, "tcp");
        if (b == 0) {
            goto out;                           /* got what we wanted */
        }
@@ -240,7 +247,7 @@ stream_client_internal(hostname, port, sendsize, recvsize, localport, priv)
     }
 
 #ifdef TCPPORTRANGE
-    if (bind_portrange(client_socket, &claddr, TCPPORTRANGE) == 0)
+    if (bind_portrange(client_socket, &claddr, TCPPORTRANGE, "tcp") == 0)
        goto out;
 #endif
 
@@ -272,8 +279,12 @@ out:
        return -1;
     }
 
+    if (nonblock)
+       fcntl(client_socket, F_SETFL,
+           fcntl(client_socket, F_GETFL, 0)|O_NONBLOCK);
+
     if(connect(client_socket, (struct sockaddr *)&svaddr, sizeof(svaddr))
-       == -1) {
+       == -1 && !nonblock) {
        save_errno = errno;
        dbprintf(("%s: %s: connect to %s.%d failed: %s\n",
                  debug_prefix_time(NULL),
@@ -309,28 +320,35 @@ out:
 }
 
 int
-stream_client_privileged(hostname, port, sendsize, recvsize, localport)
-    char *hostname;
-    int port, sendsize, recvsize, *localport;
+stream_client_privileged(hostname,
+                        port,
+                        sendsize,
+                        recvsize,
+                        localport,
+                        nonblock)
+    const char *hostname;
+    int port, sendsize, recvsize, *localport, nonblock;
 {
     return stream_client_internal(hostname,
                                  port,
                                  sendsize,
                                  recvsize,
                                  localport,
+                                 nonblock,
                                  1);
 }
 
 int
-stream_client(hostname, port, sendsize, recvsize, localport)
-    char *hostname;
-    int port, sendsize, recvsize, *localport;
+stream_client(hostname, port, sendsize, recvsize, localport, nonblock)
+    const char *hostname;
+    int port, sendsize, recvsize, *localport, nonblock;
 {
     return stream_client_internal(hostname,
                                  port,
                                  sendsize,
                                  recvsize,
                                  localport,
+                                 nonblock,
                                  0);
 }
 
@@ -352,11 +370,7 @@ int server_socket, timeout, sendsize, recvsize;
     tv.tv_usec = 0;
     FD_ZERO(&readset);
     FD_SET(server_socket, &readset);
-    nfound = select(server_socket+1,
-                   (SELECT_ARG_TYPE *)&readset,
-                   NULL,
-                   NULL,
-                   &tv);
+    nfound = select(server_socket+1, (SELECT_ARG_TYPE *)&readset, NULL, NULL, &tv);
     if(nfound <= 0 || !FD_ISSET(server_socket, &readset)) {
        save_errno = errno;
        if(nfound < 0) {
index 22538287741829f657c59008a7da1f60c33cc51f..6835cf4ce3649dcfac16f12553a1c1f96d29b9fb 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: stream.h,v 1.4.2.1.4.3 2001/08/14 22:20:57 jrjackson Exp $
+ * $Id: stream.h,v 1.10 2001/08/14 22:38:26 jrjackson Exp $
  *
  * interface to stream module
  */
 
 #include "amanda.h"
 
-/* Note: This must be kept in sync with the DATABUF_SIZE defined in
- * client-src/sendbackup-krb4.c, or kerberos encryption won't work...
- *     - Chris Ross (cross@uu.net)  4-Jun-1998
- */
 #define NETWORK_BLOCK_BYTES    DISK_BLOCK_BYTES
 #define STREAM_BUFSIZE         (NETWORK_BLOCK_BYTES * 2)
 
 int stream_server P((int *port, int sendsize, int recvsize));
 int stream_accept P((int sock, int timeout, int sendsize, int recvsize));
-int stream_client_privileged P((char *hostname,
+int stream_client_privileged P((const char *hostname,
                                int port,
                                int sendsize,
                                int recvsize,
-                               int *localport));
-int stream_client P((char *hostname,
+                               int *localport,
+                               int nonblock));
+int stream_client P((const char *hostname,
                     int port,
                     int sendsize,
                     int recvsize,
-                    int *localport));
+                    int *localport,
+                    int nonblock));
 
 #endif
index 96bb4d7d13e814338ec707da70973799ae5b2b31..b33db7adc90badc113f0dbd3a2ebfd7f457931b5 100644 (file)
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-/* $Id: strerror.c,v 1.4 1997/12/30 05:24:24 jrj Exp $ */
+/* $Id: strerror.c,v 1.6 1999/05/18 20:38:53 kashmir Exp $ */
 
 #include "amanda.h"
 
+#define        UPREFIX "Unknown error: %u"
+
 /*
  * Return the error message corresponding to some error number.
  */
 char *
 strerror(e)
-       int e;
+    int e;
 {
-       extern int sys_nerr;
-       extern char *sys_errlist[];
-       char number[NUM_STR_SIZE];
-       static char *unknown = NULL;
+    extern int sys_nerr;
+    extern char *sys_errlist[];
+    unsigned int errnum;
+    static char buf[NUM_STR_SIZE + sizeof(UPREFIX) + 1];
+
+    errnum = e;                /* convert to unsigned */
 
-       if ((unsigned)e < sys_nerr)
-               return sys_errlist[e];
-       ap_snprintf(number, sizeof(number), "%d", e);
-       unknown = newstralloc2(unknown, "Unknown error: ", number);
-       return unknown;
+    if (errnum < sys_nerr)
+       return (sys_errlist[errnum]);
+    snprintf(buf, sizeof(buf), UPREFIX, errnum);
+    return (buf);
 }
index 4882c39ef98ff1cb21efe8436a6ee5257783f3aa..b3de11d4f94706933a94b87ff664dbfb90c1041a 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: strstr.c,v 1.4.10.1 2002/02/11 01:30:42 jrjackson Exp $
+ * $Id: strstr.c,v 1.5 2002/02/11 01:32:10 jrjackson Exp $
  *
  * replacement for missing ANSI-C strstr function
  */
diff --git a/common-src/tapelist.c b/common-src/tapelist.c
new file mode 100644 (file)
index 0000000..8d39cab
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1998 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: tapelist.c,v 1.3 2006/01/15 21:00:59 martinea Exp $
+ *
+ * Support code for amidxtaped and amindexd.
+ */
+
+#include "amanda.h"
+#include "tapelist.h"
+
+/*
+ * Count the number of entries in this tapelist
+ */
+int num_entries (tapelist)
+tapelist_t *tapelist;
+{
+    tapelist_t *cur_tape;
+    int count = 0;
+
+    for(cur_tape = tapelist ; cur_tape ; cur_tape = cur_tape->next) count++;
+
+    return(count);
+}
+
+/*
+ * Add a tape entry with the given label to the given tapelist, creating a new
+ * tapelist if handed a NULL one.  Squashes duplicates.
+ */
+tapelist_t *append_to_tapelist (tapelist, label, file, isafile)
+tapelist_t *tapelist;
+char *label;
+int file, isafile;
+{
+    tapelist_t *new_tape, *cur_tape;
+    int c;
+
+    /* see if we have this tape already, and if so just add to its file list */
+    for(cur_tape = tapelist; cur_tape; cur_tape = cur_tape->next){
+       if(!strcmp(label, cur_tape->label)){
+           int d_idx = 0;
+           int *newfiles;
+           if(file >= 0){
+               newfiles = alloc(sizeof(int) * (cur_tape->numfiles + 1));
+               for(c = 0; c < cur_tape->numfiles ; c++){
+                   if(cur_tape->files[c] > file && c == d_idx){
+                       newfiles[d_idx] = file;
+                       d_idx++;
+                   }
+                   newfiles[d_idx] = cur_tape->files[c];
+                   d_idx++;
+               }
+               if(c == d_idx) newfiles[d_idx] = file;
+               cur_tape->numfiles++;
+               amfree(cur_tape->files);
+               cur_tape->files = newfiles;
+           }
+           return(tapelist);
+       }
+    }
+
+    new_tape = alloc(sizeof(tapelist_t));
+    memset(new_tape, 0, sizeof(tapelist_t));
+    new_tape->label = stralloc(label);
+    if(file >= 0){
+       new_tape->files = alloc(sizeof(int));
+       new_tape->files[0] = file;
+       new_tape->numfiles = 1;
+       new_tape->isafile = isafile;
+    }
+
+    /* first instance of anything, start our tapelist with it */
+    if(!tapelist){
+       tapelist = new_tape;
+       return(tapelist);
+    }
+
+    /* new tape, tack it onto the end of the list */
+    for(cur_tape = tapelist; cur_tape->next; cur_tape = cur_tape->next);
+    cur_tape->next = new_tape;
+
+    return(tapelist);
+}
+
+/*
+ * Backslash-escape all of the commas (and backslashes) in a label string.
+ */
+char *escape_label (label)
+char *label;
+{
+    char *cooked_str, *temp_str;
+    int s_idx = 0, d_idx = 0;
+
+    if(!label) return(NULL);
+
+    temp_str = alloc(strlen(label) * 2);
+
+    do{
+       if(label[s_idx] == ',' || label[s_idx] == '\\' ||
+               label[s_idx] == ';' || label[s_idx] == ':'){
+           temp_str[d_idx] = '\\';
+           d_idx++;
+       }
+       temp_str[d_idx] = label[s_idx];
+       s_idx++;
+       d_idx++;
+    } while(label[s_idx] != '\0');
+    temp_str[d_idx] = '\0';
+
+    cooked_str = stralloc(temp_str);
+    amfree(temp_str);
+    
+    return(cooked_str);
+}
+
+/*
+ * Strip out any escape characters (backslashes)
+ */
+char *unescape_label(label)
+char *label;
+{
+    char *cooked_str, *temp_str;
+    int s_idx = 0, d_idx = 0, prev_esc = 0;
+    
+    if(!label) return(NULL);
+
+    temp_str = alloc(strlen(label));
+
+    do{
+       if(label[s_idx] == '\\' && !prev_esc){
+           s_idx++;
+           prev_esc = 1;
+           continue;
+       }
+       prev_esc = 0;
+       temp_str[d_idx] = label[s_idx];
+       s_idx++;
+       d_idx++;
+    } while(label[s_idx] != '\0');
+    temp_str[d_idx] = '\0';
+
+    cooked_str = stralloc(temp_str);
+    amfree(temp_str);
+    
+    return(cooked_str);
+}
+
+/*
+ * Convert a tapelist into a parseable string of tape labels and file numbers.
+ */
+char *marshal_tapelist (tapelist, do_escape)
+tapelist_t *tapelist;
+int do_escape;
+{
+    tapelist_t *cur_tape;
+    char *str = NULL;
+
+    for(cur_tape = tapelist; cur_tape; cur_tape = cur_tape->next){
+       char *esc_label;
+       char *files_str = NULL;
+       int c;
+
+       if(do_escape) esc_label = escape_label(cur_tape->label);
+       else esc_label = stralloc(cur_tape->label);
+
+       for(c = 0; c < cur_tape->numfiles ; c++){
+           char num_str[NUM_STR_SIZE];
+           snprintf(num_str, sizeof(num_str), "%d", cur_tape->files[c]);
+           if(!files_str) files_str = stralloc(num_str);
+           else files_str = vstralloc(files_str, ",", num_str, NULL);
+       }
+
+       if(!str) str = vstralloc(esc_label, ":", files_str, NULL);
+       else str = vstralloc(str, ";", esc_label, ":", files_str, NULL);
+
+       amfree(esc_label);
+       amfree(files_str);
+    }
+
+    return(str);
+}
+
+/*
+ * Convert a previously str-ified and escaped list of tapes back into a
+ * tapelist structure.
+ */
+tapelist_t *unmarshal_tapelist_str (tapelist_str)
+char *tapelist_str;
+{
+    char *temp_label, *temp_filenum;
+    int l_idx, n_idx, input_length;
+    tapelist_t *tapelist = NULL;
+
+    if(!tapelist_str) return(NULL);
+
+    input_length = strlen(tapelist_str);
+
+    temp_label = alloc(input_length+1);
+    temp_filenum = alloc(input_length+1);
+
+    do{
+       /* first, read the label part */
+       memset(temp_label, '\0', input_length+1);
+        l_idx = 0;
+       while(*tapelist_str != ':' && *tapelist_str != '\0'){
+           if(*tapelist_str == '\\') *tapelist_str++; /* skip escapes */
+           temp_label[l_idx] = *tapelist_str;
+           if(*tapelist_str == '\0') break; /* bad format, should kvetch */
+           *tapelist_str++;
+           l_idx++;
+       }
+       if(*tapelist_str != '\0') *tapelist_str++;
+       tapelist = append_to_tapelist(tapelist, temp_label, -1, 0);
+
+       /* now read the list of file numbers */
+       while(*tapelist_str != ';' && *tapelist_str != '\0'){
+           int filenum = -1;
+           memset(temp_filenum, '\0', input_length+1);
+           n_idx = 0;
+           while(*tapelist_str != ';' && *tapelist_str != ',' &&
+                   *tapelist_str != '\0'){
+               temp_filenum[n_idx] = *tapelist_str; 
+               *tapelist_str++;
+               n_idx++;
+           }
+           filenum = atoi(temp_filenum);
+
+           tapelist = append_to_tapelist(tapelist, temp_label, filenum, 0);
+           if(*tapelist_str != '\0' && *tapelist_str != ';') *tapelist_str++;
+       }
+       if(*tapelist_str != '\0') *tapelist_str++;
+
+    } while(*tapelist_str != '\0');
+
+    amfree(temp_label);
+    amfree(temp_filenum);
+
+    return(tapelist);
+}
+
+/*
+ * Free up a list of tapes
+ */
+void free_tapelist (tapelist)
+tapelist_t *tapelist;
+{
+    tapelist_t *cur_tape;
+    tapelist_t *prev = NULL;
+
+    for(cur_tape = tapelist ; cur_tape ; cur_tape = cur_tape->next){
+       if(cur_tape->label) amfree(cur_tape->label);
+       if(cur_tape->files) amfree(cur_tape->files);
+       if(prev) amfree(prev);
+       prev = cur_tape;
+    }
+    if(prev) amfree(prev);
+
+}
diff --git a/common-src/tapelist.h b/common-src/tapelist.h
new file mode 100644 (file)
index 0000000..7d3e99b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1998 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: tapelist.h,v 1.1 2005/10/11 01:17:00 vectro Exp $
+ *
+ */
+
+#ifndef TAPELIST_H
+#define TAPELIST_H
+
+#include "amanda.h"
+
+/* XXX This looks like a lot of other things, apart from the string
+ * marshalling and unmarshalling.  Things like the EXTRACT_LIST in amrecover's
+ * innards are functionally similar, so there's probably a lot of opportunity
+ * to pare down extraneous code here by mushing things like that in.  Rainy
+ * day project, perhaps.
+ */
+
+typedef struct tapelist_s {
+    struct tapelist_s *next;
+    char *label;
+    int isafile; /* set to 1 and make *label the path to the file */
+    int *files;
+    int numfiles;
+} tapelist_t;
+
+extern int num_entries P((tapelist_t *tapelist));
+extern tapelist_t *append_to_tapelist P((tapelist_t *tapelist, char *label,
+                                       int file, int isafile));
+extern char *marshal_tapelist P((tapelist_t *tapelist, int escape));
+extern tapelist_t *unmarshal_tapelist_str P((char *tapelist_str));
+extern char *escape_label P((char *label));
+extern char *unescape_label P((char *label));
+extern void free_tapelist P((tapelist_t *tapelist));
+
+#endif /* !TAPELIST_H */
index dfe0212b89b090e84f9d24e393aad8ca1308d4c2..d894f40575b614c9f586cbb9bae58882a403f4c8 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: token.c,v 1.22.8.3.2.2 2005/09/30 19:13:36 martinea Exp $
+ * $Id: token.c,v 1.29 2006/01/14 04:37:19 paddy_s Exp $
  *
  * token bashing routines
  */
@@ -141,7 +141,7 @@ printf_arglist_function(char *squotef, char *, format)
        /* Format the token */
 
        arglist_start(argp, format);
-       ap_vsnprintf(linebuf, sizeof(linebuf), format, argp);
+       vsnprintf(linebuf, sizeof(linebuf), format, argp);
        arglist_end(argp);
 
        return quote(" ", linebuf);
@@ -155,7 +155,7 @@ printf_arglist_function1(char *quotef, char *, sep, char *, format)
        /* Format the token */
 
        arglist_start(argp, format);
-       ap_vsnprintf(linebuf, sizeof(linebuf), format, argp);
+       vsnprintf(linebuf, sizeof(linebuf), format, argp);
        arglist_end(argp);
 
        return quote(sep, linebuf);
@@ -368,7 +368,7 @@ char *str;  /* the string to quote */
 
     return buf;
 }
-#endif /* HAVE_SHQUOTE */
+#endif
 
 /* Table lookup.
 */
@@ -413,6 +413,9 @@ int main()
 
        set_pname("token test");
 
+       /* Don't die when child closes pipe */
+       signal(SIGPIPE, SIG_IGN);
+
        erroutput_type = ERR_INTERACTIVE;
 
        printf("Testing split() with \" \" token separator\n");
index 5a3f9254240c75fa1d652ea4a76448e309e3e084..6e33b7b3107ca96f8a51990058a065269a6c3d21 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: token.h,v 1.10.8.3 2003/12/16 22:36:45 martinea Exp $
+ * $Id: token.h,v 1.12 2003/03/26 20:17:13 kovert Exp $
  *
  * interface to token module
  */
@@ -43,7 +43,7 @@ extern char *quotef P((char *sep, char *format, ...))
     __attribute__ ((format (printf, 2, 3)));
 extern char *quote P((char *sep, char *str));
 extern char *rxquote P((char *str));
-#ifndef HAVE_SHQUOTE_DECL
+#ifndef HAVE_SHQUOTE
 extern char *shquote P((char *str));
 #endif
 extern int table_lookup P((table_t *table, char *str));
index cd3a4655fb4e73a1bd9cc574456502951dedf7d4..0eafec0b74d6822f7305e453b69c498eac97f789 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: util.c,v 1.2.2.2.4.3.2.1 2002/03/31 21:01:33 jrjackson Exp $
+ * $Id: util.c,v 1.17 2006/01/14 04:37:19 paddy_s Exp $
  */
 
 #include "amanda.h"
@@ -47,10 +47,15 @@ fullread(fd, vbuf, buflen)
 
     while (buflen > 0) {
        nread = read(fd, buf, buflen);
-       if (nread < 0)
-           return (nread);
+       if (nread < 0) {
+           if ((errno == EINTR) || (errno == EAGAIN))
+               continue;
+           return ((tot > 0) ? tot : -1);
+       }
+
        if (nread == 0)
            break;
+
        tot += nread;
        buf += nread;
        buflen -= nread;
@@ -75,8 +80,11 @@ fullwrite(fd, vbuf, buflen)
 
     while (buflen > 0) {
        nwritten = write(fd, buf, buflen);
-       if (nwritten < 0)
-           return (nwritten);
+       if (nwritten < 0) {
+           if ((errno == EINTR) || (errno == EAGAIN))
+               continue;
+           return ((tot > 0) ? tot : -1);
+       }
        tot += nwritten;
        buf += nwritten;
        buflen -= nwritten;
@@ -91,14 +99,16 @@ fullwrite(fd, vbuf, buflen)
  * on success.
  */
 int
-bind_portrange(s, addrp, first_port, last_port)
+bind_portrange(s, addrp, first_port, last_port, proto)
     int s;
     struct sockaddr_in *addrp;
     int first_port, last_port;
+    char *proto;
 {
     int port, cnt;
     const int num_ports = last_port - first_port + 1;
     int save_errno;
+    struct servent *servPort;
 
     assert(first_port > 0 && first_port <= last_port && last_port < 65536);
 
@@ -107,20 +117,25 @@ bind_portrange(s, addrp, first_port, last_port)
      * time to avoid always picking the same reserved port twice.
      */
     port = ((getpid() + time(0)) % num_ports) + first_port;
-
     /*
-     * Scan through the range, trying all available ports.  Wrap around
+     * Scan through the range, trying all available ports that are either 
+     * not taken in /etc/services or registered for *amanda*.  Wrap around
      * if we don't happen to start at the beginning.
      */
     for (cnt = 0; cnt < num_ports; cnt++) {
-       addrp->sin_port = htons(port);
-       if (bind(s, (struct sockaddr *)addrp, sizeof(*addrp)) >= 0)
-           return 0;
-       /*
-        * If the error was something other then port in use, stop.
-        */
-       if (errno != EADDRINUSE)
-           break;
+       servPort = getservbyport(htons(port), proto);
+       if((servPort == NULL) || strstr(servPort->s_name, "amanda")){
+           dbprintf(("%s: bind_portrange2: trying port=%d\n",
+                     debug_prefix_time(NULL), port));
+           addrp->sin_port = htons(port);
+           if (bind(s, (struct sockaddr *)addrp, sizeof(*addrp)) >= 0)
+               return 0;
+           /*
+            * If the error was something other then port in use, stop.
+            */
+           if (errno != EADDRINUSE)
+               break;
+       }
        if (++port > last_port)
            port = first_port;
     }
@@ -165,8 +180,8 @@ construct_datestamp(t)
        when = *t;
     }
     tm = localtime(&when);
-    ap_snprintf(datestamp, sizeof(datestamp),
-                "%04d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
+    snprintf(datestamp, sizeof(datestamp),
+             "%04d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
     return stralloc(datestamp);
 }
 
@@ -187,9 +202,9 @@ construct_timestamp(t)
        when = *t;
     }
     tm = localtime(&when);
-    ap_snprintf(timestamp, sizeof(timestamp),
-                "%04d%02d%02d%02d%02d%02d",
-               tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
-               tm->tm_hour, tm->tm_min, tm->tm_sec);
+    snprintf(timestamp, sizeof(timestamp),
+            "%04d%02d%02d%02d%02d%02d",
+            tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+            tm->tm_hour, tm->tm_min, tm->tm_sec);
     return stralloc(timestamp);
 }
index b6928737b10dd83911365784d1f92a56a99cdd38..074066d645addf542b290ebc17d2c73b7e7852fd 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: util.h,v 1.2.2.1.4.2 2001/03/20 00:25:22 jrjackson Exp $
+ * $Id: util.h,v 1.5 2005/12/09 03:22:52 paddy_s Exp $
  */
 #ifndef UTIL_H
 #define        UTIL_H
 
+
+#define BSTRNCMP(a,b)  strncmp(a, b, strlen(b)) 
+                                                  
+                                                 
 ssize_t fullread P((int, void *, size_t));
 ssize_t fullwrite P((int, const void *, size_t));
 
-int bind_portrange P((int, struct sockaddr_in *, int, int));
+int bind_portrange P((int, struct sockaddr_in *, int, int, char *));
 
 char *construct_datestamp P((time_t *t));
 char *construct_timestamp P((time_t *t));
index ea8d231029da0eb3d08baa005fb859c90c0fbfc8..33639e6ab8c622558206328856345eb1491fd02c 100644 (file)
@@ -1,10 +1,10 @@
 /* version.c - generated by genversion.c - DO NOT EDIT! */
-char *version_info[] = {
-  "build: VERSION=\"Amanda-2.4.5p1\"\n",
-  "       BUILT_DATE=\"Mon Oct 24 17:25:18 EDT 2005\"\n",
-  "       BUILT_MACH=\"Linux minifee.iro.umontreal.ca 2.6.13-1.1526_FC4 #1 Wed Sep 28 19:15:10 EDT 2005 i686 i686 i386 GNU/Linux\"\n",
+const char * const version_info[] = {
+  "build: VERSION=\"Amanda-2.5.0\"\n",
+  "       BUILT_DATE=\"Thu Mar 23 20:20:38 EST 2006\"\n",
+  "       BUILT_MACH=\"Linux minifee.iro.umontreal.ca 2.6.15-1.1833_FC4 #1 Wed Mar 1 23:41:37 EST 2006 i686 i686 i386 GNU/Linux\"\n",
   "       CC=\"gcc\"\n",
-  "       CONFIGURE_COMMAND=\"'./configure' '--prefix=/u/martinea/linux' '--with-configdir=/u/martinea/etc/amanda' '--with-gnutar-listdir=/var/gnutar-lists' '--with-bsd-security' '--with-user=amanda' '--with-group=amandag' '--disable-shared' '--mandir=/u/martinea/man'\"\n",
+  "       CONFIGURE_COMMAND=\"'./configure' '--prefix=/u/martinea/linux' '--with-configdir=/u/martinea/etc/amanda' '--with-gnutar-listdir=/var/gnutar-lists' '--with-bsd-security' '--with-user=amanda' '--with-group=amandag' '--mandir=/u/martinea/man'\"\n",
   "paths: bindir=\"/u/martinea/linux/bin\"\n",
   "       sbindir=\"/u/martinea/linux/sbin\"\n",
   "       libexecdir=\"/u/martinea/linux/libexec\"\n",
@@ -15,15 +15,15 @@ char *version_info[] = {
   "       RESTORE=\"/sbin/restore\" VDUMP=UNDEF VRESTORE=UNDEF\n",
   "       XFSDUMP=UNDEF XFSRESTORE=UNDEF VXDUMP=UNDEF VXRESTORE=UNDEF\n",
   "       SAMBA_CLIENT=\"/usr/bin/smbclient\" GNUTAR=\"/bin/gtar\"\n",
-  "       COMPRESS_PATH=\"/usr/bin/gzip\"\n",
-  "       UNCOMPRESS_PATH=\"/usr/bin/gzip\" LPRCMD=\"/usr/bin/lpr\"\n",
-  "       MAILER=\"/usr/bin/Mail\" listed_incr_dir=\"/var/gnutar-lists\"\n",
+  "       COMPRESS_PATH=\"/bin/gzip\" UNCOMPRESS_PATH=\"/bin/gzip\"\n",
+  "       LPRCMD=\"/usr/bin/lpr\" MAILER=\"/usr/bin/Mail\"\n",
+  "       listed_incr_dir=\"/var/gnutar-lists\"\n",
   "defs:  DEFAULT_SERVER=\"minifee.iro.umontreal.ca\"\n",
   "       DEFAULT_CONFIG=\"DailySet1\"\n",
   "       DEFAULT_TAPE_SERVER=\"minifee.iro.umontreal.ca\"\n",
-  "       DEFAULT_TAPE_DEVICE=\"/dev/null\" HAVE_MMAP HAVE_SYSVSHM\n",
+  "       DEFAULT_TAPE_DEVICE=\"null:\" HAVE_MMAP HAVE_SYSVSHM\n",
   "       LOCKING=POSIX_FCNTL SETPGRP_VOID DEBUG_CODE\n",
-  "       AMANDA_DEBUG_DAYS=4 BSD_SECURITY USE_AMANDAHOSTS\n",
+  "       AMANDA_DEBUG_DAYS=4 BSD_SECURITY RSH_SECURITY USE_AMANDAHOSTS\n",
   "       CLIENT_LOGIN=\"amanda\" FORCE_USERID HAVE_GZIP\n",
   "       COMPRESS_SUFFIX=\".gz\" COMPRESS_FAST_OPT=\"--fast\"\n",
   "       COMPRESS_BEST_OPT=\"--best\" UNCOMPRESS_OPT=\"-dc\"\n",
index cae54cec71623049cdc98d3ced6daa859aed4799..f287767ac17681a165e21c168e6d047ea40edf2e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: version.h,v 1.4.4.1 1999/05/25 06:59:58 oliva Exp $
+ * $Id: version.h,v 1.5 1999/04/16 04:58:58 kashmir Exp $
  *
  * interface to obtain the current amanda version
  */
@@ -48,11 +48,12 @@ extern const int   VERSION_MAJOR;
 extern const int   VERSION_MINOR;
 extern const int   VERSION_PATCH;
 extern const char * const VERSION_COMMENT;
+extern const char * const version_info[];
 
 /* versionsuffix returns an empty string or a string like -2.3.0.4b1.  */
-extern char *versionsuffix();
+extern const char *versionsuffix P((void));
 
 /* version returns a string representing the version of Amanda.  */
-extern char *version();
+extern const char *version P((void));
 
 #endif
index 4bdadc6379c2e20cb44dc86f1f7ef186db869407..d55153e82bd510a26d641b3fe29f4143f0711570 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: versuff.c.in,v 1.6.4.1.4.1 2001/07/20 19:37:20 jrjackson Exp $
+ * $Id: versuff.c.in,v 1.11 2003/05/20 17:33:53 martinea Exp $
  *
  * provide amanda version number and suffix appended to program names
  */
 #include "version.h"
 
 const int   VERSION_MAJOR   = 2;
-const int   VERSION_MINOR   = 4;
-const int   VERSION_PATCH   = 5;
-const char *const VERSION_COMMENT = "p1";
+const int   VERSION_MINOR   = 5;
+const int   VERSION_PATCH   = 0;
+const char *const VERSION_COMMENT = "";
 
-char *
+const char *
 versionsuffix()
 {
 #ifdef USE_VERSION_SUFFIXES
-       static char *vsuff = NULL;
-
-       if(vsuff) return vsuff;                 /* been here once already */
-
-       vsuff = stralloc2("-", version());
-       malloc_mark(vsuff);
-       return vsuff;
+    return "-2.5.0";
 #else
-       return "";
+    return "";
 #endif
 }
 
-char *
+const char *
 version()
 {
-       static char *vsuff = NULL;
-       char major_str[NUM_STR_SIZE];
-       char minor_str[NUM_STR_SIZE];
-       char patch_str[NUM_STR_SIZE];
-
-       if(vsuff) return vsuff;                 /* been here once already */
-
-       ap_snprintf(major_str, sizeof(major_str), "%d", VERSION_MAJOR);
-       ap_snprintf(minor_str, sizeof(minor_str), "%d", VERSION_MINOR);
-       ap_snprintf(patch_str, sizeof(patch_str), "%d", VERSION_PATCH);
-
-       vsuff = vstralloc(major_str, ".", minor_str, ".", patch_str,
-                         VERSION_COMMENT,
-                         NULL);
-       malloc_mark(vsuff);
-       return vsuff;
+    return "2.5.0";
 }
index 9b32c833109934dbaa580dfb9a29bef34cfe2db5..572333dbfaaf068d2cfdbad17fd2c35e18ecebaf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: versuff.c.in,v 1.6.4.1.4.1 2001/07/20 19:37:20 jrjackson Exp $
+ * $Id: versuff.c.in,v 1.11 2003/05/20 17:33:53 martinea Exp $
  *
  * provide amanda version number and suffix appended to program names
  */
@@ -36,39 +36,18 @@ const int   VERSION_MINOR   = @VERSION_MINOR@;
 const int   VERSION_PATCH   = @VERSION_PATCH@;
 const char *const VERSION_COMMENT = @VERSION_COMMENT@;
 
-char *
+const char *
 versionsuffix()
 {
 #ifdef USE_VERSION_SUFFIXES
-       static char *vsuff = NULL;
-
-       if(vsuff) return vsuff;                 /* been here once already */
-
-       vsuff = stralloc2("-", version());
-       malloc_mark(vsuff);
-       return vsuff;
+    return "-@VERSION_SUFFIX@";
 #else
-       return "";
+    return "";
 #endif
 }
 
-char *
+const char *
 version()
 {
-       static char *vsuff = NULL;
-       char major_str[NUM_STR_SIZE];
-       char minor_str[NUM_STR_SIZE];
-       char patch_str[NUM_STR_SIZE];
-
-       if(vsuff) return vsuff;                 /* been here once already */
-
-       ap_snprintf(major_str, sizeof(major_str), "%d", VERSION_MAJOR);
-       ap_snprintf(minor_str, sizeof(minor_str), "%d", VERSION_MINOR);
-       ap_snprintf(patch_str, sizeof(patch_str), "%d", VERSION_PATCH);
-
-       vsuff = vstralloc(major_str, ".", minor_str, ".", patch_str,
-                         VERSION_COMMENT,
-                         NULL);
-       malloc_mark(vsuff);
-       return vsuff;
+    return "@VERSION_SUFFIX@";
 }
diff --git a/common-src/writev.c b/common-src/writev.c
new file mode 100644 (file)
index 0000000..2d5317b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1998 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: writev.c,v 1.2 1999/03/04 22:40:08 kashmir Exp $
+ *
+ * emulation of writev that simply copies all iovecs into a contiguous
+ * buffer and writes that out in one write.
+ */
+
+#include "amanda.h"
+#ifndef HAVE_WRITEV
+
+ssize_t
+writev(fd, iov, iovcnt)
+    int fd;
+    const struct iovec *iov;
+    int iovcnt;
+{
+    size_t bufsize;
+    int i;
+    ssize_t ret;
+    char *buf, *writeptr;
+
+    /*
+     * Get the sum of the iovecs, and allocate a suitably sized buffer
+     */
+    for (bufsize = 0, i = 0; i < iovcnt; i++)
+       bufsize += iov[i].iov_len;
+    buf = alloc(bufsize);
+
+    /*
+     * Copy each iovec back to back into the buffer
+     */
+    for (writeptr = buf, i = 0; i < iovcnt; i++) {
+       memcpy(writeptr, iov[i].iov_base, iov[i].iov_len);
+       writeptr += iov[i].iov_len;
+    }
+
+    /*
+     * Write the buffer, free it, and return write's result
+     */
+    ret = write(fd, buf, bufsize);
+    amfree(buf);
+    return (ret);
+}
+#endif /* HAVE_WRITEV */
index b88e5aba3094bc0dd4dcad54bcc5c598bdb08106..b4f5d15d0da2120fbd1db402cc30fc01c8a5d08b 100644 (file)
@@ -98,7 +98,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -110,9 +112,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -125,6 +130,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -187,10 +193,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
index bbb5fcd2d3f332dbbaa0dedc3e6cb0095adc43a8..ae6ea72e34105e8a7e1a56a3817909e09ac7c2b3 100644 (file)
@@ -499,9 +499,94 @@ dnl Remember, if the system already had a valid <stdint.h>, the generated
 dnl file will include it directly. No need for fuzzy HAVE_STDINT_H things...
 dnl
 dnl @, (status: used on new platforms) (see http://ac-archive.sf.net/gstdint/)
-dnl @version $Id: acinclude.m4i,v 1.1.2.5.8.3 2004/04/29 20:47:22 martinea Exp $
+dnl @version Id: ax_create_stdint_h.m4,v 1.5 2005/01/06 18:27:27 guidod Exp
 dnl @author  Guido Draheim <guidod@gmx.de> 
 
+AC_DEFUN([AX_CHECK_DATA_MODEL],[
+   AC_CHECK_SIZEOF(char)
+   AC_CHECK_SIZEOF(short)
+   AC_CHECK_SIZEOF(int)
+   AC_CHECK_SIZEOF(long)
+   AC_CHECK_SIZEOF(void*)
+   ac_cv_char_data_model=""
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model=""
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+   AC_MSG_CHECKING([data model])
+   case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+    122/242)     ac_cv_data_model="IP16"  ; n="standard 16bit machine" ;;
+    122/244)     ac_cv_data_model="LP32"  ; n="standard 32bit machine" ;;
+    122/*)       ac_cv_data_model="i16"   ; n="unusual int16 model" ;;
+    124/444)     ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+    124/488)     ac_cv_data_model="LP64"  ; n="standard 64bit unixish" ;;
+    124/448)     ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+    124/*)       ac_cv_data_model="i32"   ; n="unusual int32 model" ;;
+    128/888)     ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+    128/*)       ac_cv_data_model="i64"   ; n="unusual int64 model" ;;         
+    222/*2)      ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+    333/*3)      ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+    444/*4)      ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+    666/*6)      ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+    888/*8)      ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+    222/*|333/*|444/*|666/*|888/*) :
+                 ac_cv_data_model="iDSP"  ; n="unusual dsptype" ;;
+     *)          ac_cv_data_model="none"  ; n="very unusual model" ;;
+   esac
+   AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
+])
+
+dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
+AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
+AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
+ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_uintptr_t 
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+  done
+  AC_MSG_CHECKING([for stdint uintptr_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
+AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
+ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h stdint.h]) ; do
+   unset ac_cv_type_uint32_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint uint32_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
+AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
+ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_u_int32_t
+   unset ac_cv_type_u_int64_t
+   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint u_int32_t])
+ ])
+])
+
 AC_DEFUN([AX_CREATE_STDINT_H],
 [# ------ AX CREATE STDINT H -------------------------------------
 AC_MSG_CHECKING([for stdint types])
@@ -535,94 +620,35 @@ fi
 if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
 
 dnl .....intro message done, now do a few system checks.....
-dnl btw, all CHECK_TYPE macros do automatically "DEFINE" a type, therefore
-dnl we use the autoconf implementation detail _AC CHECK_TYPE_NEW instead
+dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, 
+dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW 
+dnl instead that is triggered with 3 or more arguments (see types.m4)
 
 inttype_headers=`echo $2 | sed -e 's/,/ /g'`
 
 ac_cv_stdint_result="(no helpful system typedefs seen)"
-AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
- ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
-  AC_MSG_RESULT([(..)])
-  for i in stdint.h inttypes.h sys/inttypes.h $inttype_headers ; do
-   unset ac_cv_type_uintptr_t 
-   unset ac_cv_type_uint64_t
-   _AC_CHECK_TYPE_NEW(uintptr_t,[ac_cv_header_stdint_x=$i],dnl
-     continue,[#include <$i>])
-   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
-   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)"
-   break;
-  done
-  AC_MSG_CHECKING([for stdint uintptr_t])
- ])
+AX_CHECK_HEADER_STDINT_X(dnl
+   stdint.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
 
 if test "_$ac_cv_header_stdint_x" = "_" ; then
-AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
- ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
-  AC_MSG_RESULT([(..)])
-  for i in inttypes.h sys/inttypes.h stdint.h $inttype_headers ; do
-   unset ac_cv_type_uint32_t
-   unset ac_cv_type_uint64_t
-   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],dnl
-     continue,[#include <$i>])
-   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
-   ac_cv_stdint_result="(seen uint32_t$and64 in $i)"
-   break;
-  done
-  AC_MSG_CHECKING([for stdint uint32_t])
- ])
+AX_CHECK_HEADER_STDINT_O(dnl,
+   inttypes.h sys/inttypes.h stdint.h $inttype_headers,
+   ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
 fi
 
 if test "_$ac_cv_header_stdint_x" = "_" ; then
 if test "_$ac_cv_header_stdint_o" = "_" ; then
-AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
- ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
-  AC_MSG_RESULT([(..)])
-  for i in sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do
-   unset ac_cv_type_u_int32_t
-   unset ac_cv_type_u_int64_t
-   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],dnl
-     continue,[#include <$i>])
-   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
-   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)"
-   break;
-  done
-  AC_MSG_CHECKING([for stdint u_int32_t])
- ])
+AX_CHECK_HEADER_STDINT_U(dnl,
+   sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
 fi fi
 
 dnl if there was no good C99 header file, do some typedef checks...
 if test "_$ac_cv_header_stdint_x" = "_" ; then
    AC_MSG_CHECKING([for stdint datatype model])
    AC_MSG_RESULT([(..)])
-   AC_CHECK_SIZEOF(char)
-   AC_CHECK_SIZEOF(short)
-   AC_CHECK_SIZEOF(int)
-   AC_CHECK_SIZEOF(long)
-   AC_CHECK_SIZEOF(void*)
-   ac_cv_stdint_char_model=""
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_char"
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_short"
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_int"
-   ac_cv_stdint_long_model=""
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_int"
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_long"
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_voidp"
-   name="$ac_cv_stdint_long_model"
-   case "$ac_cv_stdint_char_model/$ac_cv_stdint_long_model" in
-    122/242)     name="$name,  IP16 (standard 16bit machine)" ;;
-    122/244)     name="$name,  LP32 (standard 32bit mac/win)" ;;
-    122/*)       name="$name        (unusual int16 model)" ;; 
-    124/444)     name="$name, ILP32 (standard 32bit unixish)" ;;
-    124/488)     name="$name,  LP64 (standard 64bit unixish)" ;;
-    124/448)     name="$name, LLP64 (unusual  64bit unixish)" ;;
-    124/*)       name="$name        (unusual int32 model)" ;; 
-    128/888)     name="$name, ILP64 (unusual  64bit numeric)" ;;
-    128/*)       name="$name        (unusual int64 model)" ;; 
-    222/*|444/*) name="$name        (unusual dsptype)" ;;
-     *)          name="$name        (very unusal model)" ;;
-   esac
-   AC_MSG_RESULT([combined for stdint datatype model...  $name])
+   AX_CHECK_DATA_MODEL
 fi
 
 if test "_$ac_cv_header_stdint_x" != "_" ; then
@@ -655,6 +681,7 @@ fi
 AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
 $ac_cv_stdint_result])
 
+dnl -----------------------------------------------------------------
 # ----------------- DONE inttypes.h checks START header -------------
 AC_CONFIG_COMMANDS([$ac_stdint_h],[
 AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
@@ -667,7 +694,10 @@ echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
 echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
 if test "_$ac_cv_header_stdint_t" != "_" ; then 
 echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
-fi
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
 
 cat >>$ac_stdint <<STDINT_EOF
 
@@ -727,9 +757,9 @@ fi
 echo "" >>$ac_stdint
 
 echo "/* which type model has been detected */" >>$ac_stdint
-if test "_$ac_cv_stdint_char_model" != "_" ; then
-echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_stdint_char_model" >>$ac_stdint
-echo "#define   _STDINT_LONG_MODEL" "$ac_cv_stdint_long_model" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define   _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
 else
 echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
 echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
@@ -814,6 +844,7 @@ typedef u_int64_t uint64_t;
 /* .. here are some common heuristics using compiler runtime specifics */
 #if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 
@@ -827,12 +858,14 @@ typedef unsigned __int64 uint64_t;
 /* note: all ELF-systems seem to have loff-support which needs 64-bit */
 #if !defined _NO_LONGLONG
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 #endif
 
 #elif defined __alpha || (defined __mips && defined _ABIN32)
 #if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
 typedef long int64_t;
 typedef unsigned long uint64_t;
 #endif
@@ -918,6 +951,7 @@ typedef          int     int32_t;
 /* assuming the system has a "long long" */
 #ifndef _HAVE_UINT64_T
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef unsigned long long uint64_t;
 typedef          long long  int64_t;
 #endif
@@ -1003,12 +1037,87 @@ typedef           long   intptr_t;
 #endif
 #endif
 
+/* The ISO C99 standard specifies that in C++ implementations these
+   should only be defined if explicitly requested.  */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed.  */
+# define INT8_C(c)      c
+# define INT16_C(c)     c
+# define INT32_C(c)     c
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INT64_C(c)    c ## L
+# else
+#  define INT64_C(c)    c ## LL
+# endif
+
+/* Unsigned.  */
+# define UINT8_C(c)     c ## U
+# define UINT16_C(c)    c ## U
+# define UINT32_C(c)    c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define UINT64_C(c)   c ## UL
+# else
+#  define UINT64_C(c)   c ## ULL
+# endif
+
+/* Maximal type.  */
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INTMAX_C(c)   c ## L
+#  define UINTMAX_C(c)  c ## UL
+# else
+#  define INTMAX_C(c)   c ## LL
+#  define UINTMAX_C(c)  c ## ULL
+# endif
+
+  /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types.  */
+# define INT8_MIN               (-128)
+# define INT16_MIN              (-32767-1)
+# define INT32_MIN              (-2147483647-1)
+# define INT64_MIN              (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types.  */
+# define INT8_MAX               (127)
+# define INT16_MAX              (32767)
+# define INT32_MAX              (2147483647)
+# define INT64_MAX              (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types.  */
+# define UINT8_MAX              (255)
+# define UINT16_MAX             (65535)
+# define UINT32_MAX             (4294967295U)
+# define UINT64_MAX             (__UINT64_C(18446744073709551615))
+
+/* Minimum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MIN         INT8_MIN
+# define INT_LEAST16_MIN        INT16_MIN
+# define INT_LEAST32_MIN        INT32_MIN
+# define INT_LEAST64_MIN        INT64_MIN
+/* Maximum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MAX         INT8_MAX
+# define INT_LEAST16_MAX        INT16_MAX
+# define INT_LEAST32_MAX        INT32_MAX
+# define INT_LEAST64_MAX        INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size.  */
+# define UINT_LEAST8_MAX        UINT8_MAX
+# define UINT_LEAST16_MAX       UINT16_MAX
+# define UINT_LEAST32_MAX       UINT32_MAX
+# define UINT_LEAST64_MAX       UINT64_MAX
+
   /* shortcircuit*/
 #endif
   /* once */
 #endif
 #endif
 STDINT_EOF
+fi
     if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
       AC_MSG_NOTICE([$ac_stdint_h is unchanged])
     else
@@ -1029,8 +1138,8 @@ ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
 ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
 ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
 ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
-ac_cv_stdint_char_model="$ac_cv_stdint_char_model"
-ac_cv_stdint_long_model="$ac_cv_stdint_long_model"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
 ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
 ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
 ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
index ad5281e66e9def96e03533881ed570a8a495ccd5..c38553dc74bb4f06a43f734903d1e1c0f1ed6fdb 100755 (executable)
@@ -3,7 +3,7 @@
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 #   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
-timestamp='2005-08-03'
+timestamp='2006-02-23'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -106,7 +106,7 @@ set_cc_for_build='
 trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
 trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
 : ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
  { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
  { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
  { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
@@ -206,6 +206,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:ekkoBSD:*:*)
        echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
        exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
     macppc:MirBSD:*:*)
        echo powerppc-unknown-mirbsd${UNAME_RELEASE}
        exit ;;
@@ -764,7 +767,12 @@ EOF
        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
        exit ;;
     *:FreeBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
        exit ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
@@ -772,6 +780,9 @@ EOF
     i*:MINGW*:*)
        echo ${UNAME_MACHINE}-pc-mingw32
        exit ;;
+    i*:MSYS_NT-*:*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
     i*:windows32*:*)
        # uname -m includes "-pc" on this system.
        echo ${UNAME_MACHINE}-mingw32
@@ -779,8 +790,11 @@ EOF
     i*:PW*:*)
        echo ${UNAME_MACHINE}-pc-pw32
        exit ;;
-    x86:Interix*:[34]*)
-       echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+    x86:Interix*:[345]*)
+       echo i586-pc-interix${UNAME_RELEASE}
+       exit ;;
+    EM64T:Interix*:[345]*)
+       echo x86_64-unknown-interix${UNAME_RELEASE}
        exit ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
        echo i${UNAME_MACHINE}-pc-mks
@@ -851,7 +865,11 @@ EOF
        #endif
        #endif
 EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
        test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
        ;;
     mips64:Linux:*:*)
@@ -870,7 +888,11 @@ EOF
        #endif
        #endif
 EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
        test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
        ;;
     or32:Linux:*:*)
@@ -919,6 +941,9 @@ EOF
     sparc:Linux:*:* | sparc64:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
        exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
     x86_64:Linux:*:*)
        echo x86_64-unknown-linux-gnu
        exit ;;
@@ -964,7 +989,7 @@ EOF
        LIBC=gnulibc1
        # endif
        #else
-       #ifdef __INTEL_COMPILER
+       #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun)
        LIBC=gnu
        #else
        LIBC=gnuaout
@@ -974,7 +999,11 @@ EOF
        LIBC=dietlibc
        #endif
 EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^LIBC/{
+               s: ::g
+               p
+           }'`"
        test x"${LIBC}" != x && {
                echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
                exit
@@ -1185,7 +1214,6 @@ EOF
     *:Darwin:*:*)
        UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
        case $UNAME_PROCESSOR in
-           *86) UNAME_PROCESSOR=i686 ;;
            unknown) UNAME_PROCESSOR=powerpc ;;
        esac
        echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
@@ -1264,6 +1292,9 @@ EOF
     i*86:skyos:*:*)
        echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
        exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
index 3959454620fa1bb92444cf2ac81f4e5bfa8c7c35..490c6c9db73df885b483bbb6085574f391ba2c8f 100644 (file)
@@ -99,6 +99,9 @@
 /* Define the location of the ufsdump, backup, or dump program. */
 #undef DUMP
 
+/* Directory in which dumper interfaces should be installed and searched. */
+#undef DUMPER_DIR
+
 /* Define if dumper should buffer the sockets for faster throughput. */
 #undef DUMPER_SOCKET_BUFFERING
 
 /* Define to 1 if you have the `nsl' library (-lnsl). */
 #undef HAVE_LIBNSL
 
-/* Define to 1 if you have the `readline' library (-lreadline). */
-#undef HAVE_LIBREADLINE
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
 
 /* Define to 1 if you have the `socket' library (-lsocket). */
 #undef HAVE_LIBSOCKET
 /* Define to 1 if you have the `mkdir' function. */
 #undef HAVE_MKDIR
 
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
+/* Define if mkstemp is declared. */
+#undef HAVE_MKSTEMP_DECL
+
 /* Define to 1 if you have the `mktemp' function. */
 #undef HAVE_MKTEMP
 
 /* Define to 1 if you have the `shquote' function. */
 #undef HAVE_SHQUOTE
 
-/* Define if shquote is declared. */
-#undef HAVE_SHQUOTE_DECL
-
 /* Define to 1 if you have the `sigaction' function. */
 #undef HAVE_SIGACTION
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
 /* Define to 1 if you have the <sys/vfstab.h> header file. */
 #undef HAVE_SYS_VFSTAB_H
 
 /* Define if the compiler support unsigned long constants. */
 #undef HAVE_UNSIGNED_LONG_CONSTANTS
 
-/* Define to 1 if the system has the type `unsigned long long'. */
-#undef HAVE_UNSIGNED_LONG_LONG
-
 /* Define to 1 if you have the `vfprintf' function. */
 #undef HAVE_VFPRINTF
 
 /* Define to 1 if you have the <wait.h> header file. */
 #undef HAVE_WAIT_H
 
+/* Define to 1 if you have the `writev' function. */
+#undef HAVE_WRITEV
+
+/* Define if writev is declared. */
+#undef HAVE_WRITEV_DECL
+
 /* Define if limits.h defines _POSIX2_RE_DUP_MAX. */
 #undef HAVE__POSIX2_RE_DUP_MAX
 
 /* Enable Kerberos security. */
 #undef KRB4_SECURITY
 
+/* Define if Kerberos 5 security is to be enabled. */
+#undef KRB5_SECURITY
+
+/* Format for a long long printf. */
+#undef LL_FMT
+
 /* Command for starting printing jobs. */
 #undef LPRCMD
 
 /* Define as the return type of signal handlers (`int' or `void'). */
 #undef RETSIGTYPE
 
+/* Define if RSH transport should be enabled. */
+#undef RSH_SECURITY
+
 /* Define the location of smbclient for backing up Samba PC clients. */
 #undef SAMBA_CLIENT
 
 /* The size of a `int', as computed by sizeof. */
 #undef SIZEOF_INT
 
+/* The size of a `intmax_t', as computed by sizeof. */
+#undef SIZEOF_INTMAX_T
+
 /* The size of a `long', as computed by sizeof. */
 #undef SIZEOF_LONG
 
+/* The size of a `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of a `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
+
 /* The size of a `short', as computed by sizeof. */
 #undef SIZEOF_SHORT
 
 /* The size of a `void*', as computed by sizeof. */
 #undef SIZEOF_VOIDP
 
+/* Define if SSH transport should be enabled. */
+#undef SSH_SECURITY
+
 /* If using the C implementation of alloca, define if you know the
    direction of stack growth for your system; otherwise it will be
    automatically deduced at run-time.
 /* Define to use Posix fcntl for file locking. */
 #undef USE_POSIX_FCNTL
 
-/* Define if you want to use amqde instead of gnutar for estimates */
-#undef USE_QUICK_AND_DIRTY_ESTIMATES
-
 /* Define to invoke rundump (setuid-root) instead of DUMP program directly. */
 #undef USE_RUNDUMP
 
    `char[]'. */
 #undef YYTEXT_POINTER
 
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
 /* Directory in which user binaries should be installed. */
 #undef bindir
 
 /* Define if socklen_t is not a standard system type */
 #undef socklen_t
 
-/* Define to `int' if <sys/types.h> does not define. */
-#undef ssize_t
-
 /* Define to `int' if <sys/types.h> doesn't define. */
 #undef uid_t
 
index 1c366dfde9ab35fe6474af49933455433951457f..ad9f39571183b5c22b2d269bb52eb9ad50227430 100755 (executable)
@@ -3,7 +3,7 @@
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 #   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
-timestamp='2005-07-08'
+timestamp='2006-02-23'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -119,8 +119,9 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
-  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -171,6 +172,10 @@ case $os in
        -hiux*)
                os=-hiuxwe2
                ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
        -sco5)
                os=-sco3.2v5
                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -187,6 +192,10 @@ case $os in
                # Don't forget version if it is 3.2v4 or newer.
                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
                ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
        -sco*)
                os=-sco3.2v2
                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -239,7 +248,7 @@ case $basic_machine in
        | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
        | i370 | i860 | i960 | ia64 \
        | ip2k | iq2000 \
-       | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+       | m32r | m32rle | m68000 | m68k | m88k | maxq | mb | microblaze | mcore \
        | mips | mipsbe | mipseb | mipsel | mipsle \
        | mips16 \
        | mips64 | mips64el \
@@ -257,8 +266,9 @@ case $basic_machine in
        | mipsisa64sr71k | mipsisa64sr71kel \
        | mipstx39 | mipstx39el \
        | mn10200 | mn10300 \
-       | ms1 \
+       | mt \
        | msp430 \
+       | nios | nios2 \
        | ns16k | ns32k \
        | or32 \
        | pdp10 | pdp11 | pj | pjl \
@@ -286,6 +296,9 @@ case $basic_machine in
                ;;
        m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
                ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
 
        # We use `pc' rather than `unknown'
        # because (1) that's what they normally are, and
@@ -336,8 +349,9 @@ case $basic_machine in
        | mipsisa64sr71k-* | mipsisa64sr71kel-* \
        | mipstx39-* | mipstx39el-* \
        | mmix-* \
-       | ms1-* \
+       | mt-* \
        | msp430-* \
+       | nios-* | nios2-* \
        | none-* | np1-* | ns16k-* | ns32k-* \
        | orion-* \
        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
@@ -696,6 +710,9 @@ case $basic_machine in
                basic_machine=i386-pc
                os=-msdos
                ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
        mvs)
                basic_machine=i370-ibm
                os=-mvs
@@ -803,6 +820,12 @@ case $basic_machine in
        pc532 | pc532-*)
                basic_machine=ns32k-pc532
                ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
        pentium | p5 | k5 | k6 | nexgen | viac3)
                basic_machine=i586-pc
                ;;
@@ -859,6 +882,10 @@ case $basic_machine in
                basic_machine=i586-unknown
                os=-pw32
                ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
        rom68k)
                basic_machine=m68k-rom68k
                os=-coff
@@ -1174,21 +1201,23 @@ case $os in
              | -aos* \
              | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
              | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
              | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
              | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
              | -chorusos* | -chorusrdb* \
              | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-             | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
              | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
              | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
              | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
              | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
              | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
              | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-             | -skyos* | -haiku*)
+             | -skyos* | -haiku* | -rdos*)
        # Remember, each alternative MUST END IN *, to match a version number.
                ;;
        -qnx*)
index 0b0e87cb72f3a3db13b3ac2db8164e96d090b74c..771b86f32dd9eb56fe291b7b50aa3678f50d256f 100644 (file)
@@ -137,7 +137,7 @@ rm="rm -f"
 default_ofile=libtool
 can_build_shared=yes
 
-# All known linkers require a `.a' archive for static linking (except M$VC,
+# All known linkers require a `.a' archive for static linking (except MSVC,
 # which needs '.lib').
 libext=a
 ltmain="$ac_aux_dir/ltmain.sh"
@@ -353,8 +353,8 @@ if test "X${echo_test_string+set}" != Xset; then
 # find a string as large as possible, as long as the shell can cope with it
   for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
     # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
        (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
     then
       break
@@ -523,7 +523,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case "`/usr/bin/file conftest.o`" in
+    case `/usr/bin/file conftest.o` in
     *32-bit*)
       case $host in
         x86_64-*linux*)
@@ -605,7 +605,7 @@ AC_CACHE_CHECK([$1], [$2],
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
    (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
@@ -644,7 +644,7 @@ AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
    LDFLAGS="$LDFLAGS $3"
    printf "$lt_simple_link_test_code" > conftest.$ac_ext
    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
-     # The compiler can only warn and ignore the option if not recognized
+     # The linker can only warn and ignore the option if not recognized
      # So say no if there are warnings
      if test -s conftest.err; then
        # Append any errors to the config.log.
@@ -719,7 +719,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
     elif test -x /usr/sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
     else
-      lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
     fi
     # And add a safety zone
     lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
@@ -731,7 +731,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
     # nice to cause kernel panics so lets avoid the loop below.
     # First set a reasonable default.
     lt_cv_sys_max_cmd_len=16384
-    # 
+    #
     if test -x /sbin/sysconfig; then
       case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
         *1*) lt_cv_sys_max_cmd_len=-1 ;;
@@ -848,7 +848,7 @@ int main ()
 }]
 EOF
   if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) $1 ;;
@@ -997,7 +997,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
    (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
@@ -1015,7 +1015,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
        _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
      fi
    fi
-   chmod u+w .
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
    $rm conftest*
    # SGI C++ compiler will create directory out/ii_files/ for
    # template instantiation
@@ -1275,7 +1275,8 @@ cygwin* | mingw* | pw32*)
       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
       dldir=$destdir/`dirname \$dlpath`~
       test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
       dlpath=$dir/\$dldll~
        $rm \$dlpath'
@@ -1328,7 +1329,7 @@ darwin* | rhapsody*)
   soname_spec='${libname}${release}${major}$shared_ext'
   shlibpath_overrides_runpath=yes
   shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
   # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
   if test "$GCC" = yes; then
     sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
@@ -1366,7 +1367,14 @@ kfreebsd*-gnu)
 freebsd* | dragonfly*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
   version_type=freebsd-$objformat
   case $version_type in
     freebsd-elf*)
@@ -1411,7 +1419,7 @@ hpux9* | hpux10* | hpux11*)
   version_type=sunos
   need_lib_prefix=no
   need_version=no
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     shrext_cmds='.so'
     hardcode_into_libs=yes
@@ -1508,27 +1516,10 @@ linux*)
   # before this can be enabled.
   hardcode_into_libs=yes
 
-  # find out which ABI we are using
-  libsuff=
-  case "$host_cpu" in
-  x86_64*|s390x*|powerpc64*)
-    echo '[#]line __oline__ "configure"' > conftest.$ac_ext
-    if AC_TRY_EVAL(ac_compile); then
-      case `/usr/bin/file conftest.$ac_objext` in
-      *64-bit*)
-        libsuff=64
-        sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
-        ;;
-      esac
-    fi
-    rm -rf conftest*
-    ;;
-  esac
-
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,   ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -1590,7 +1581,11 @@ nto-qnx*)
 openbsd*)
   version_type=sunos
   need_lib_prefix=no
-  need_version=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
   shlibpath_var=LD_LIBRARY_PATH
@@ -1820,7 +1815,7 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN],
 
 # AC_LIBTOOL_WIN32_DLL
 # --------------------
-# declare package support for building win32 dll's
+# declare package support for building win32 DLLs
 AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
 [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
 ])# AC_LIBTOOL_WIN32_DLL
@@ -1994,7 +1989,7 @@ dnl not every word.  This closes a longstanding sh security hole.
       if test -n "$file_magic_test_file"; then
        case $deplibs_check_method in
        "file_magic "*)
-         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
          MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
          if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
            $EGREP "$file_magic_regex" > /dev/null; then
@@ -2104,7 +2099,7 @@ AC_CACHE_VAL(lt_cv_path_LD,
     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
       lt_cv_path_LD="$ac_dir/$ac_prog"
       # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some GNU ld's only accept -v.
+      # but apparently some variants of GNU ld only accept -v.
       # Break only if it was the GNU/non-GNU ld that we prefer.
       case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
       *GNU* | *'with BFD'*)
@@ -2136,7 +2131,7 @@ AC_PROG_LD_GNU
 AC_DEFUN([AC_PROG_LD_GNU],
 [AC_REQUIRE([AC_PROG_EGREP])dnl
 AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
 case `$LD -v 2>&1 </dev/null` in
 *GNU* | *'with BFD'*)
   lt_cv_prog_gnu_ld=yes
@@ -2250,7 +2245,7 @@ gnu*)
 
 hpux10.20* | hpux11*)
   lt_cv_file_magic_cmd=/usr/bin/file
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
     lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
@@ -2424,13 +2419,13 @@ esac
 # -----------------------------------
 # sets LIBLTDL to the link flags for the libltdl convenience library and
 # LTDLINCL to the include flags for the libltdl header and adds
-# --enable-ltdl-convenience to the configure arguments.  Note that LIBLTDL
-# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
-# DIRECTORY is not provided, it is assumed to be `libltdl'.  LIBLTDL will
-# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with
-# '${top_srcdir}/' (note the single quotes!).  If your package is not
-# flat and you're not using automake, define top_builddir and
-# top_srcdir appropriately in the Makefiles.
+# --enable-ltdl-convenience to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# it is assumed to be `libltdl'.  LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!).  If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
 AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
 [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
   case $enable_ltdl_convenience in
@@ -2449,13 +2444,13 @@ AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
 # -----------------------------------
 # sets LIBLTDL to the link flags for the libltdl installable library and
 # LTDLINCL to the include flags for the libltdl header and adds
-# --enable-ltdl-install to the configure arguments.  Note that LIBLTDL
-# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
-# DIRECTORY is not provided and an installed libltdl is not found, it is
-# assumed to be `libltdl'.  LIBLTDL will be prefixed with '${top_builddir}/'
-# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
-# quotes!).  If your package is not flat and you're not using automake,
-# define top_builddir and top_srcdir appropriately in the Makefiles.
+# --enable-ltdl-install to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
 # In the future, this macro may have to be called after AC_PROG_LIBTOOL.
 AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
 [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
@@ -2638,7 +2633,7 @@ test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
 # are all built from PIC.
-case "$host_os" in
+case $host_os in
 aix3*)
   test "$enable_shared" = yes && enable_static=no
   if test -n "$RANLIB"; then
@@ -2705,7 +2700,7 @@ _LT_AC_TAGVAR(postdeps, $1)=
 _LT_AC_TAGVAR(compiler_lib_search_path, $1)=
 
 # Source file extension for C++ test sources.
-ac_ext=cc
+ac_ext=cpp
 
 # Object file extension for compiled C++ test sources.
 objext=o
@@ -2921,7 +2916,7 @@ case $host_os in
        # Exported symbols can be pulled into shared objects from archives
        _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
        _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
-       # This is similar to how AIX traditionally builds it's shared libraries.
+       # This is similar to how AIX traditionally builds its shared libraries.
        _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
       fi
     fi
@@ -2960,7 +2955,7 @@ case $host_os in
     fi
   ;;
       darwin* | rhapsody*)
-        case "$host_os" in
+        case $host_os in
         rhapsody* | darwin1.[[012]])
          _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
          ;;
@@ -2998,7 +2993,7 @@ case $host_os in
           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
         fi
         _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
           if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
             _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           else
@@ -3011,7 +3006,7 @@ case $host_os in
          output_verbose_link_cmd='echo'
           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
           _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -3091,7 +3086,7 @@ case $host_os in
     ;;
   hpux10*|hpux11*)
     if test $with_gnu_ld = no; then
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*)
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
@@ -3107,7 +3102,7 @@ case $host_os in
         ;;
       esac
     fi
-    case "$host_cpu" in
+    case $host_cpu in
     hppa*64*)
       _LT_AC_TAGVAR(hardcode_direct, $1)=no
       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
@@ -3133,7 +3128,7 @@ case $host_os in
        _LT_AC_TAGVAR(ld_shlibs, $1)=no
        ;;
       aCC*)
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
          ;;
@@ -3154,7 +3149,7 @@ case $host_os in
       *)
        if test "$GXX" = yes; then
          if test $with_gnu_ld = no; then
-           case "$host_cpu" in
+           case $host_cpu in
            ia64*|hppa*64*)
              _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
              ;;
@@ -3250,12 +3245,12 @@ case $host_os in
        ;;
       pgCC*)
         # Portland Group C++ compiler
-       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
-       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
        _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
         ;;
       cxx*)
        # Compaq C++
@@ -3487,10 +3482,11 @@ case $host_os in
     case $cc_basename in
       CC*)
        # Sun C++ 4.2, 5.x and Centerline C++
+        _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
        _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
-       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
        _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-       $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
 
        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
        _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
@@ -3510,15 +3506,7 @@ case $host_os in
        esac
        _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
 
-       # Commands to make compiler produce verbose output that lists
-       # what "hidden" libraries, object files and flags are used when
-       # linking a shared library.
-       #
-       # There doesn't appear to be a way to prevent this compiler from
-       # explicitly linking system object files so we need to strip them
-       # from the output so that they don't get included in the library
-       # dependencies.
-       output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       output_verbose_link_cmd='echo'
 
        # Archives containing C++ object files must be created using
        # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -3679,7 +3667,7 @@ if AC_TRY_EVAL(ac_compile); then
   # The `*' in the case matches for architectures that use `case' in
   # $output_verbose_cmd can trigger glob expansion during the loop
   # eval without this substitution.
-  output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
 
   for p in `eval $output_verbose_link_cmd`; do
     case $p in
@@ -3755,6 +3743,21 @@ fi
 
 $rm -f confest.$objext
 
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+solaris*)
+  case $cc_basename in
+  CC*)
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
+    ;;
+  esac
+esac
+])
+
 case " $_LT_AC_TAGVAR(postdeps, $1) " in
 *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
 esac
@@ -3824,7 +3827,7 @@ test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
 # are all built from PIC.
-case "$host_os" in
+case $host_os in
 aix3*)
   test "$enable_shared" = yes && enable_static=no
   if test -n "$RANLIB"; then
@@ -4727,7 +4730,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        ;;
       *)
@@ -4796,7 +4799,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
          aCC*)
            _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
            _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
-           case "$host_cpu" in
+           case $host_cpu in
            hppa*64*|ia64*)
              # +Z the default
              ;;
@@ -4837,7 +4840,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
            # Portland Group C++ compiler.
            _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
            _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
-           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
            ;;
          cxx*)
            # Compaq C++
@@ -5001,7 +5004,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -5048,7 +5051,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -5078,12 +5081,12 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
        _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
        _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
         ;;
-      pgcc* | pgf77* | pgf90*)
+      pgcc* | pgf77* | pgf90* | pgf95*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
        # which looks to be a dead project)
        _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
        _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
-       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
         ;;
       ccc*)
         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
@@ -5166,7 +5169,7 @@ if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
     [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
 fi
-case "$host_os" in
+case $host_os in
   # For platforms which do not support PIC, -DPIC is meaningless:
   *djgpp*)
     _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
@@ -5262,7 +5265,7 @@ ifelse([$1],[CXX],[
   if test "$with_gnu_ld" = yes; then
     # If archive_cmds runs LD, not CC, wlarc should be empty
     wlarc='${wl}'
-    
+
     # Set some defaults for GNU ld with shared library support. These
     # are reset later if shared libraries are not supported. Putting them
     # here allows them to be overridden if necessary.
@@ -5283,7 +5286,7 @@ ifelse([$1],[CXX],[
       *\ 2.11.*) ;; # other 2.11 versions
       *) supports_anon_versioning=yes ;;
     esac
-    
+
     # See if GNU ld supports shared libraries.
     case $host_os in
     aix3* | aix4* | aix5*)
@@ -5357,11 +5360,12 @@ EOF
        tmp_addflag=
        case $cc_basename,$host_cpu in
        pgcc*)                          # Portland Group C compiler
-         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
          ;;
-       pgf77* | pgf90* )                       # Portland Group f77 and f90 compilers
-         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
-         tmp_addflag=' -fpic -Mnomain' ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
        ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
          tmp_addflag=' -i_dynamic' ;;
        efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
@@ -5566,7 +5570,7 @@ EOF
          # Exported symbols can be pulled into shared objects from archives
          _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
          _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
-         # This is similar to how AIX traditionally builds it's shared libraries.
+         # This is similar to how AIX traditionally builds its shared libraries.
          _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
        fi
       fi
@@ -5606,7 +5610,7 @@ EOF
       ;;
 
     darwin* | rhapsody*)
-      case "$host_os" in
+      case $host_os in
         rhapsody* | darwin1.[[012]])
          _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
          ;;
@@ -5635,7 +5639,7 @@ EOF
        output_verbose_link_cmd='echo'
         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
       _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
       _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
     else
@@ -5644,7 +5648,7 @@ EOF
          output_verbose_link_cmd='echo'
          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
          _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -5710,7 +5714,7 @@ EOF
 
     hpux10* | hpux11*)
       if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
          ;;
@@ -5719,7 +5723,7 @@ EOF
          ;;
        esac
       else
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
          ;;
@@ -5729,7 +5733,7 @@ EOF
        esac
       fi
       if test "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*)
          _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
          _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
index 9be0eb1c38c2db306bd70075c0b78a49d842ebf4..9e71d27d86d48ea79d31f3be040ec3933bd76623 100644 (file)
@@ -43,8 +43,8 @@ EXIT_FAILURE=1
 
 PROGRAM=ltmain.sh
 PACKAGE=libtool
-VERSION=1.5.16
-TIMESTAMP=" (1.1220.2.235 2005/04/25 18:13:26)"
+VERSION=1.5.20
+TIMESTAMP=" (1.1220.2.287 2005/08/31 18:54:15)"
 
 # See if we are running on zsh, and set the options which allow our
 # commands through without removal of \ escapes.
@@ -88,14 +88,15 @@ rm="rm -f"
 Xsed="${SED}"' -e 1s/^X//'
 sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
 # test EBCDIC or ASCII
-case `echo A|tr A '\301'` in
- A) # EBCDIC based system
-  SP2NL="tr '\100' '\n'"
-  NL2SP="tr '\r\n' '\100\100'"
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  SP2NL='tr \040 \012'
+  NL2SP='tr \015\012 \040\040'
   ;;
- *) # Assume ASCII based system
-  SP2NL="tr '\040' '\012'"
-  NL2SP="tr '\015\012' '\040\040'"
+ *) # EBCDIC based system
+  SP2NL='tr \100 \n'
+  NL2SP='tr \r\n \100\100'
   ;;
 esac
 
@@ -133,7 +134,6 @@ show_help=
 execute_dlfiles=
 lo2o="s/\\.lo\$/.${objext}/"
 o2lo="s/\\.${objext}\$/.lo/"
-quote_scanset='[[~#^*{};<>?'"'"'       ]'
 
 #####################################
 # Shell function definitions:
@@ -192,7 +192,7 @@ func_infer_tag ()
       CC_quoted=
       for arg in $CC; do
        case $arg in
-         *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+         *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
          arg="\"$arg\""
          ;;
        esac
@@ -213,7 +213,7 @@ func_infer_tag ()
            for arg in $CC; do
            # Double-quote args containing other shell metacharacters.
            case $arg in
-             *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+             *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \     ]*|*]*|"")
              arg="\"$arg\""
              ;;
            esac
@@ -337,7 +337,7 @@ func_extract_archives ()
            func_extract_an_archive "$my_xdir" "$my_xabs"
          fi # $darwin_arches
        fi # $run
-      ;;
+       ;;
       *)
         func_extract_an_archive "$my_xdir" "$my_xabs"
         ;;
@@ -576,7 +576,7 @@ if test -z "$show_help"; then
 
     for arg
     do
-      case "$arg_mode" in
+      case $arg_mode in
       arg  )
        # do not "continue".  Instead, add this to base_compile
        lastarg="$arg"
@@ -627,7 +627,7 @@ if test -z "$show_help"; then
            # Many Bourne shells cannot handle close brackets correctly
            # in scan sets, so we specify it separately.
            case $arg in
-             *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+             *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \     ]*|*]*|"")
              arg="\"$arg\""
              ;;
            esac
@@ -662,7 +662,7 @@ if test -z "$show_help"; then
       # in scan sets (worked around with variable expansion),
       # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
       # at all, so we specify them separately.
-      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        lastarg="\"$lastarg\""
        ;;
       esac
@@ -737,13 +737,12 @@ if test -z "$show_help"; then
 
     qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
     case $qlibobj in
-      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        qlibobj="\"$qlibobj\"" ;;
     esac
-    if test "X$libobj" != "X$qlibobj"; then
-       $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
-       exit $EXIT_FAILURE
-    fi
+    test "X$libobj" != "X$qlibobj" \
+       && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"'  &()|`$[]' \
+       && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
     objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
     xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
     if test "X$xdir" = "X$obj"; then
@@ -824,7 +823,7 @@ compiler."
     fi
     qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
     case $qsrcfile in
-      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
       qsrcfile="\"$qsrcfile\"" ;;
     esac
 
@@ -1111,7 +1110,7 @@ EOF
       arg="$1"
       shift
       case $arg in
-      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
        ;;
       *) qarg=$arg ;;
@@ -1357,6 +1356,8 @@ EOF
          ;;
         darwin_framework)
          compiler_flags="$compiler_flags $arg"
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
          prev=
          continue
          ;;
@@ -1418,9 +1419,11 @@ EOF
        continue
        ;;
 
-      -framework)
+      -framework|-arch)
         prev=darwin_framework
         compiler_flags="$compiler_flags $arg"
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
         continue
         ;;
 
@@ -1539,7 +1542,7 @@ EOF
        # to be aesthetically quoted because they are evaled later.
        arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
        case $arg in
-       *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
          arg="\"$arg\""
          ;;
        esac
@@ -1655,7 +1658,7 @@ EOF
        for flag in $args; do
          IFS="$save_ifs"
          case $flag in
-           *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
            flag="\"$flag\""
            ;;
          esac
@@ -1673,7 +1676,7 @@ EOF
        for flag in $args; do
          IFS="$save_ifs"
          case $flag in
-           *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
            flag="\"$flag\""
            ;;
          esac
@@ -1706,7 +1709,7 @@ EOF
        # to be aesthetically quoted because they are evaled later.
        arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
        case $arg in
-       *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
          arg="\"$arg\""
          ;;
        esac
@@ -1840,7 +1843,7 @@ EOF
        # to be aesthetically quoted because they are evaled later.
        arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
        case $arg in
-       *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
          arg="\"$arg\""
          ;;
        esac
@@ -2405,7 +2408,7 @@ EOF
              case "$temp_rpath " in
              *" $dir "*) ;;
              *" $absdir "*) ;;
-             *) temp_rpath="$temp_rpath $dir" ;;
+             *) temp_rpath="$temp_rpath $absdir" ;;
              esac
            fi
 
@@ -2591,7 +2594,7 @@ EOF
                add_dir="-L$dir"
                # Try looking first in the location we're being installed to.
                if test -n "$inst_prefix_dir"; then
-                 case "$libdir" in
+                 case $libdir in
                    [\\/]*)
                      add_dir="$add_dir -L$inst_prefix_dir$libdir"
                      ;;
@@ -2664,7 +2667,7 @@ EOF
              add_dir="-L$libdir"
              # Try looking first in the location we're being installed to.
              if test -n "$inst_prefix_dir"; then
-               case "$libdir" in
+               case $libdir in
                  [\\/]*)
                    add_dir="$add_dir -L$inst_prefix_dir$libdir"
                    ;;
@@ -2725,8 +2728,6 @@ EOF
              fi
            fi
          else
-           convenience="$convenience $dir/$old_library"
-           old_convenience="$old_convenience $dir/$old_library"
            deplibs="$dir/$old_library $deplibs"
            link_static=yes
          fi
@@ -3416,7 +3417,7 @@ EOF
          if test "$?" -eq 0 ; then
            ldd_output=`ldd conftest`
            for i in $deplibs; do
-             name="`expr $i : '-l\(.*\)'`"
+             name=`expr $i : '-l\(.*\)'`
              # If $name is empty we are operating on a -L argument.
               if test "$name" != "" && test "$name" -ne "0"; then
                if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
@@ -3453,7 +3454,7 @@ EOF
            # Error occurred in the first compile.  Let's try to salvage
            # the situation: Compile a separate program for each library.
            for i in $deplibs; do
-             name="`expr $i : '-l\(.*\)'`"
+             name=`expr $i : '-l\(.*\)'`
              # If $name is empty we are operating on a -L argument.
               if test "$name" != "" && test "$name" != "0"; then
                $rm conftest
@@ -3505,7 +3506,7 @@ EOF
          set dummy $deplibs_check_method
          file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
          for a_deplib in $deplibs; do
-           name="`expr $a_deplib : '-l\(.*\)'`"
+           name=`expr $a_deplib : '-l\(.*\)'`
            # If $name is empty we are operating on a -L argument.
             if test "$name" != "" && test  "$name" != "0"; then
              if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
@@ -3574,7 +3575,7 @@ EOF
          set dummy $deplibs_check_method
          match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
          for a_deplib in $deplibs; do
-           name="`expr $a_deplib : '-l\(.*\)'`"
+           name=`expr $a_deplib : '-l\(.*\)'`
            # If $name is empty we are operating on a -L argument.
            if test -n "$name" && test "$name" != "0"; then
              if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
@@ -3815,6 +3816,9 @@ EOF
                # The command line is too long to execute in one step.
                $show "using reloadable object file for export list..."
                skipped_export=:
+               # Break out early, otherwise skipped_export may be
+               # set to false by a later but shorter cmd.
+               break
              fi
            done
            IFS="$save_ifs"
@@ -3884,7 +3888,8 @@ EOF
          fi
        fi
 
-       if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` &&
+       if test "X$skipped_export" != "X:" &&
+          len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
           test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
          :
        else
@@ -3919,7 +3924,7 @@ EOF
          do
            eval test_cmds=\"$reload_cmds $objlist $last_robj\"
            if test "X$objlist" = X ||
-              { len=`expr "X$test_cmds" : ".*"` &&
+              { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
                 test "$len" -le "$max_cmd_len"; }; then
              objlist="$objlist $obj"
            else
@@ -4009,13 +4014,30 @@ EOF
          IFS="$save_ifs"
          eval cmd=\"$cmd\"
          $show "$cmd"
-         $run eval "$cmd" || exit $?
+         $run eval "$cmd" || {
+           lt_exit=$?
+
+           # Restore the uninstalled library and exit
+           if test "$mode" = relink; then
+             $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+           fi
+
+           exit $lt_exit
+         }
        done
        IFS="$save_ifs"
 
        # Restore the uninstalled library and exit
        if test "$mode" = relink; then
          $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+         if test -n "$convenience"; then
+           if test -z "$whole_archive_flag_spec"; then
+             $show "${rm}r $gentop"
+             $run ${rm}r "$gentop"
+           fi
+         fi
+
          exit $EXIT_SUCCESS
        fi
 
@@ -4360,7 +4382,7 @@ extern \"C\" {
            if test -z "$export_symbols"; then
              export_symbols="$output_objdir/$outputname.exp"
              $run $rm $export_symbols
-             $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+             $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
            else
              $run eval "${SED} -e 's/\([ ][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
              $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
@@ -4762,6 +4784,7 @@ EOF
 EOF
 
            cat >> $cwrappersource <<"EOF"
+  return 127;
 }
 
 void *
@@ -5025,13 +5048,13 @@ else
        # Backslashes separate directories on plain windows
        *-*-mingw | *-*-os2*)
          $echo >> $output "\
-      exec \$progdir\\\\\$program \${1+\"\$@\"}
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
 "
          ;;
 
        *)
          $echo >> $output "\
-      exec \$progdir/\$program \${1+\"\$@\"}
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
 "
          ;;
        esac
@@ -5041,7 +5064,7 @@ else
     fi
   else
     # The program doesn't exist.
-    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+    \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
     \$echo \"This script is just a wrapper for \$program.\" 1>&2
     $echo \"See the $PACKAGE documentation for more information.\" 1>&2
     exit $EXIT_FAILURE
@@ -5164,7 +5187,7 @@ fi\
            oldobjs="$objlist $obj"
            objlist="$objlist $obj"
            eval test_cmds=\"$old_archive_cmds\"
-           if len=`expr "X$test_cmds" : ".*"` &&
+           if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
               test "$len" -le "$max_cmd_len"; then
              :
            else
@@ -5361,11 +5384,11 @@ relink_command=\"$relink_command\""
     # install_prog (especially on Windows NT).
     if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
        # Allow the use of GNU shtool's install command.
-       $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+       $echo "X$nonopt" | grep shtool > /dev/null; then
       # Aesthetically quote it.
       arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
       case $arg in
-      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        arg="\"$arg\""
        ;;
       esac
@@ -5374,14 +5397,14 @@ relink_command=\"$relink_command\""
       shift
     else
       install_prog=
-      arg="$nonopt"
+      arg=$nonopt
     fi
 
     # The real first argument should be the name of the installation program.
     # Aesthetically quote it.
     arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
     case $arg in
-    *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*|"")
       arg="\"$arg\""
       ;;
     esac
@@ -5399,28 +5422,31 @@ relink_command=\"$relink_command\""
     do
       if test -n "$dest"; then
        files="$files $dest"
-       dest="$arg"
+       dest=$arg
        continue
       fi
 
       case $arg in
       -d) isdir=yes ;;
-      -f) prev="-f" ;;
-      -g) prev="-g" ;;
-      -m) prev="-m" ;;
-      -o) prev="-o" ;;
+      -f) 
+       case " $install_prog " in
+       *[\\\ /]cp\ *) ;;
+       *) prev=$arg ;;
+       esac
+       ;;
+      -g | -m | -o) prev=$arg ;;
       -s)
        stripme=" -s"
        continue
        ;;
-      -*) ;;
-
+      -*)
+       ;;
       *)
        # If the previous option needed an argument, then skip it.
        if test -n "$prev"; then
          prev=
        else
-         dest="$arg"
+         dest=$arg
          continue
        fi
        ;;
@@ -5429,7 +5455,7 @@ relink_command=\"$relink_command\""
       # Aesthetically quote the argument.
       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
       case $arg in
-      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        arg="\"$arg\""
        ;;
       esac
@@ -5598,11 +5624,14 @@ relink_command=\"$relink_command\""
 
          if test "$#" -gt 0; then
            # Delete the old symlinks, and create new ones.
+           # Try `ln -sf' first, because the `ln' binary might depend on
+           # the symlink we replace!  Solaris /bin/ln does not understand -f,
+           # so we also need to try rm && ln -s.
            for linkname
            do
              if test "$linkname" != "$realname"; then
-               $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-               $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+                $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+                $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
              fi
            done
          fi
@@ -5615,7 +5644,16 @@ relink_command=\"$relink_command\""
            IFS="$save_ifs"
            eval cmd=\"$cmd\"
            $show "$cmd"
-           $run eval "$cmd" || exit $?
+           $run eval "$cmd" || {
+             lt_exit=$?
+
+             # Restore the uninstalled library and exit
+             if test "$mode" = relink; then
+               $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+             fi
+
+             exit $lt_exit
+           }
          done
          IFS="$save_ifs"
        fi
@@ -5709,17 +5747,15 @@ relink_command=\"$relink_command\""
          notinst_deplibs=
          relink_command=
 
-         # To insure that "foo" is sourced, and not "foo.exe",
-         # finese the cygwin/MSYS system by explicitly sourcing "foo."
-         # which disallows the automatic-append-.exe behavior.
-         case $build in
-         *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
-         *) wrapperdot=${wrapper} ;;
-         esac
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
          # If there is no directory component, then add one.
-         case $file in
-         */* | *\\*) . ${wrapperdot} ;;
-         *) . ./${wrapperdot} ;;
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
          esac
 
          # Check the variables that should have been set.
@@ -5747,17 +5783,15 @@ relink_command=\"$relink_command\""
          done
 
          relink_command=
-         # To insure that "foo" is sourced, and not "foo.exe",
-         # finese the cygwin/MSYS system by explicitly sourcing "foo."
-         # which disallows the automatic-append-.exe behavior.
-         case $build in
-         *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
-         *) wrapperdot=${wrapper} ;;
-         esac
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
          # If there is no directory component, then add one.
-         case $file in
-         */* | *\\*) . ${wrapperdot} ;;
-         *) . ./${wrapperdot} ;;
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
          esac
 
          outputname=
@@ -5798,7 +5832,7 @@ relink_command=\"$relink_command\""
        fi
 
        # remove .exe since cygwin /usr/bin/install will append another
-       # one anyways
+       # one anyway 
        case $install_prog,$host in
        */usr/bin/install*,*cygwin*)
          case $file:$destfile in
index 4b6d6cea15d7a79940bc225e3562cc81cac81a45..e791b2f1697fd1d9cf5123f1f8eed6b770ad42f2 100755 (executable)
--- a/configure
+++ b/configure
@@ -285,8 +285,8 @@ if test "X${echo_test_string+set}" != Xset; then
 # find a string as large as possible, as long as the shell can cope with it
   for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
     # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
        (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
     then
       break
@@ -463,7 +463,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CONFIGURE_COMMAND INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar SNAPSHOT_STAMP VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_COMMENT VERSION_SUFFIX CONFIG_DIR USE_VERSION_SUFFIXES CLIENT_SCRIPTS_OPT DEFAULT_SERVER CLIENT_LOGIN SETUID_GROUP BINARY_OWNER DEFAULT_CONFIG DEFAULT_TAPE_SERVER DEFAULT_TAPE_DEVICE DEFAULT_RAW_TAPE_DEVICE DEFAULT_CHANGER_DEVICE GNUTAR_LISTED_INCREMENTAL_DIRX MAXTAPEBLOCKSIZE AMANDA_TMPDIR AMANDA_DBGDIR AMANDA_DEBUG_DAYS SERVICE_SUFFIX CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE MT_FILE_FLAG CPP EGREP AR AWK_VAR_ASSIGNMENT_OPT YACC CAT COMPRESS DD GETCONF GNUPLOT GREP GNUTAR SAMBA_CLIENT GZIP MAILER MT CHIO CHS MTX MCUTIL PRINT PCAT PERL DUMP RESTORE XFSDUMP XFSRESTORE VXDUMP VXRESTORE VDUMP VRESTORE AMPLOT_COMPRESS AMPLOT_CAT_GZIP AMPLOT_CAT_COMPRESS AMPLOT_CAT_PACK LN_S ECHO ac_ct_AR RANLIB ac_ct_RANLIB CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS LEX LEXLIB LEX_OUTPUT_ROOT READLINE_LIBS DB_EXT ALLOCA LIBOBJS ac_n ac_c WANT_CLIENT_TRUE WANT_CLIENT_FALSE WANT_SAMBA_TRUE WANT_SAMBA_FALSE WANT_RESTORE_TRUE WANT_RESTORE_FALSE WANT_SERVER_TRUE WANT_SERVER_FALSE WANT_RECOVER_TRUE WANT_RECOVER_FALSE WANT_TAPE_TRUE WANT_TAPE_FALSE WANT_AMPLOT_TRUE WANT_AMPLOT_FALSE WANT_CHG_SCSI_TRUE WANT_CHG_SCSI_FALSE WANT_CHIO_SCSI_TRUE WANT_CHIO_SCSI_FALSE WANT_RUNTIME_PSEUDO_RELOC_TRUE WANT_RUNTIME_PSEUDO_RELOC_FALSE WANT_SETUID_CLIENT_TRUE WANT_SETUID_CLIENT_FALSE LTLIBOBJS LTALLOCA'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CONFIGURE_COMMAND INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar SNAPSHOT_STAMP VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_COMMENT VERSION_SUFFIX DUMPER_DIR CONFIG_DIR USE_VERSION_SUFFIXES CLIENT_SCRIPTS_OPT DEFAULT_SERVER CLIENT_LOGIN SETUID_GROUP BINARY_OWNER DEFAULT_CONFIG DEFAULT_TAPE_SERVER DEFAULT_TAPE_DEVICE DEFAULT_RAW_TAPE_DEVICE DEFAULT_CHANGER_DEVICE GNUTAR_LISTED_INCREMENTAL_DIRX GNUTAR_LISTED_INCREMENTAL_DIR MAXTAPEBLOCKSIZE AMANDA_TMPDIR AMANDA_DBGDIR AMANDA_DEBUG_DAYS SERVICE_SUFFIX CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE MT_FILE_FLAG CPP EGREP AR AWK_VAR_ASSIGNMENT_OPT YACC CAT COMPRESS DD GETCONF GNUPLOT GREP GNUTAR SAMBA_CLIENT GZIP MAILER MT CHIO CHS MTX MCUTIL PRINT PCAT PERL DUMP RESTORE XFSDUMP XFSRESTORE VXDUMP VXRESTORE VDUMP VRESTORE AMPLOT_COMPRESS AMPLOT_CAT_GZIP AMPLOT_CAT_COMPRESS AMPLOT_CAT_PACK LL_FMT LN_S ECHO ac_ct_AR RANLIB ac_ct_RANLIB CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS LEX LEXLIB LEX_OUTPUT_ROOT READLINE_LIBS DB_EXT ALLOCA LIBOBJS ac_n ac_c WANT_CLIENT_TRUE WANT_CLIENT_FALSE WANT_SAMBA_TRUE WANT_SAMBA_FALSE WANT_RESTORE_TRUE WANT_RESTORE_FALSE WANT_SERVER_TRUE WANT_SERVER_FALSE WANT_RECOVER_TRUE WANT_RECOVER_FALSE WANT_TAPE_TRUE WANT_TAPE_FALSE WANT_AMPLOT_TRUE WANT_AMPLOT_FALSE WANT_CHG_SCSI_TRUE WANT_CHG_SCSI_FALSE WANT_CHIO_SCSI_TRUE WANT_CHIO_SCSI_FALSE WANT_RUNTIME_PSEUDO_RELOC_TRUE WANT_RUNTIME_PSEUDO_RELOC_FALSE WANT_SETUID_CLIENT_TRUE WANT_SETUID_CLIENT_FALSE WANT_SSH_SECURITY_TRUE WANT_SSH_SECURITY_FALSE LTLIBOBJS LTALLOCA DOC_BUILD_DATE XSLTPROC HAVE_XSLTPROC_TRUE HAVE_XSLTPROC_FALSE'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -1033,13 +1033,16 @@ Optional Features:
   --enable-fast-install[=PKGS]
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
+  --disable-largefile     omit support for large files
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-cflags=CFLAGS   arguments to the c compiler (-Wall, -g, etc)
   --with-includes=DIR    site header files for readline, etc in DIR
   --with-libraries=DIR   site library directories for readline, etc in DIR
-  --with-configdir=DIR   runtime config files in DIR sysconfdir/amanda
+  --with-dumperdir=DIR   where we install the dumpers [EPREFIX/dumper]
+  --with-configdir=DIR   runtime config files in DIR [sysconfdir/amanda]
   --with-indexdir        deprecated, use indexdir in amanda.conf
   --with-dbdir           deprecated, use infofile in amanda.conf
   --with-logdir          deprecated, use logfile in amanda.conf
@@ -1050,55 +1053,59 @@ Optional Packages:
   --without-server       do not build server stuff (set --without-restore)
   --without-restore      do not build amrestore nor amidxtaped
   --without-amrecover    do not build amrecover
-  --with-index-server=HOST default amanda index server `uname -n`
+  --with-index-server=HOST default amanda index server [`uname -n`]
   --without-force-uid    do not force the uid to --with-user
-  --with-user=USER       force execution to USER on client systems required
-  --with-group=GROUP     group allowed to execute setuid-root programs required
-  --with-owner=USER       force ownership of files to USER default == --with-user value
+  --with-user=USER       force execution to USER on client systems [required]
+  --with-group=GROUP     group allowed to execute setuid-root programs [required]
+  --with-owner=USER       force ownership of files to USER [default == --with-user value]
   --with-rundump         use rundump (setuid-root) to invoke dump
-  --with-config=CONFIG   default configuration DailySet1
-  --with-tape-server=HOST default restoring tape server is HOST same as --with-index-server
+  --with-config=CONFIG   default configuration [DailySet1]
+  --with-tape-server=HOST default restoring tape server is HOST [same as --with-index-server]
   --with-tape-device=ARG restoring tape server HOST's no rewinding tape drive
   --with-ftape-rawdevice=ARG raw device on tape server HOST's if using Linux ftape >=3.04d
   --with-rew-tape        deprecated, use --with-tape-device
   --with-norew-tape=ARG  deprecated, use --with-tape-device
-  --with-changer-device=ARG default tape changer device /dev/ch0 if it exists
+  --with-changer-device=ARG default tape changer device [/dev/ch0 if it exists]
   --with-fqdn            use FQDN's to backup multiple networks
   --with-broken-fsf      only enable if tape fsf calls fail mid-file
-  --with-gnutar=PROG     use PROG as GNU tar executable default: looks for one
-   --with-qde                use quick-and-dirty estimates for gnutar
-  --with-smbclient=PROG   use PROG as Samba's smbclient executable default: looks for one
+  --with-gnutar[=PROG]      use PROG as GNU tar executable [default: looks for one]
+  --with-smbclient[=PROG]   use PROG as Samba's smbclient executable [default: looks for one]
   --with-samba-user was deprecated
-  --with-gnutar-listdir=DIR  gnutar directory lists go in DIR localstatedir/amanda/gnutar-lists
+  --with-gnutar-listdir=DIR  gnutar directory lists go in DIR [localstatedir/amanda/gnutar-lists]
   --with-gnutar-listed-incremental was deprecated, use --with-gnutar-listdir
   --without-bsd-security do not use BSD rsh/rlogin style security
   --without-amandahosts  use .rhosts instead of .amandahosts
-  --with-krb4-security=DIR   Location of Kerberos software /usr/kerberos /usr/cygnus /usr /opt/kerberos
-    --with-server-principal=ARG    server host principal  "amanda"
-    --with-server-instance=ARG     server host instance   "amanda"
-    --with-server-keyfile=ARG      server host key file   "/.amanda"
-    --with-client-principal=ARG    client host principal  "rcmd"
-    --with-client-instance=ARG     client host instance   HOSTNAME_INSTANCE
-    --with-client-keyfile=ARG      client host key file   KEYFILE
-    --with-ticket-lifetime=ARG     ticket lifetime        128
-  --with-portrange=low,high     bind unreserved TCP server sockets to ports within this range unlimited
-  --with-tcpportrange=low,high  bind unreserved TCP server sockets to ports within this range unlimited
-  --with-udpportrange=low,high  bind reserved UDP server sockets to ports within this range unlimited
+  --with-dbmalloc=DIR  Location of dbmalloc libs and headers
+  --with-krb4-security=DIR   Location of Kerberos software [/usr/kerberos /usr/cygnus /usr /opt/kerberos]
+  --with-rsh-security use rsh as a transport
+  --with-ssh-security use ssh as a transport
+    --with-server-principal=ARG    server host principal  ["amanda"]
+    --with-server-instance=ARG     server host instance   ["amanda"]
+    --with-server-keyfile=ARG      server host key file   ["/.amanda"]
+    --with-client-principal=ARG    client host principal  ["rcmd"]
+    --with-client-instance=ARG     client host instance   [HOSTNAME_INSTANCE]
+    --with-client-keyfile=ARG      client host key file   [KEYFILE]
+    --with-ticket-lifetime=ARG     ticket lifetime        [128]
+  --with-krb5-security=DIR   Location of Kerberos V software [/usr/kerberos /usr/cygnus /usr /opt/kerberos]
+  --with-portrange=low,high     bind unreserved TCP server sockets to ports within this range [unlimited]
+  --with-tcpportrange=low,high  bind unreserved TCP server sockets to ports within this range [unlimited]
+  --with-udpportrange=low,high  bind reserved UDP server sockets to ports within this range [unlimited]
   --with-maxtapeblocksize=kb            Maximum size of a tape block
-  --with-db={text,db,dbm,gdbm,ndbm} use the selected database format text
+  --with-db={text,db,dbm,gdbm,ndbm} use the selected database format [text]
   --with-mmap            force use of mmap instead of shared memory support
   --with-buffered-dump   buffer the dumping sockets on the server for speed
   --with-assertions      compile assertions into code
-  --with-tmpdir=/temp/dir area Amanda can use for temp files /tmp/amanda
-  --without-debugging=/debug/dir do not record runtime debugging information in specified directory --with-tmpdir
-  --with-debug-days=NN    number of days to keep debugging files default=4
-  --with-testing=suffix use alternate service names
+  --with-tmpdir=/temp/dir area Amanda can use for temp files [/tmp/amanda]
+  --with[out]-debugging[=/debug/dir] [do not] record runtime debugging information in specified directory [--with-tmpdir]
+  --with-debug-days=NN    number of days to keep debugging files [default=4]
+  --with-testing[=suffix] use alternate service names
   --with-dump-honor-nodump  if dump supports -h, use it for level0s too
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-tags[=TAGS]
                           include additional configurations [automatic]
+  --without-built-manpages Do not build manpages from XML source.
 
 Some influential environment variables:
   CC          C compiler command
@@ -1955,7 +1962,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=amanda
- VERSION=2.4.5p1
+ VERSION=2.5.0
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2124,12 +2131,28 @@ SYSPATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb:/usr/bsd:/etc:/usr/etc"
 LOCPATH=`(
     test "x$prefix" = xNONE && prefix=$ac_default_prefix
     test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
-    eval echo "$libexecdir:$PATH:/usr/local/sbin:/usr/local/bin"
+    eval echo "$libexecdir:$PATH:/usr/local/sbin:/usr/local/bin:/usr/ccs/bin"
 )`
 SYSLOCPATH="$SYSPATH:$LOCPATH"
 LOCSYSPATH="$LOCPATH:$SYSPATH"
 
 
+# Check whether --with-cflags or --without-cflags was given.
+if test "${with_cflags+set}" = set; then
+  withval="$with_cflags"
+
+       case "$withval" in
+       "" | y | ye | yes | n | no)
+           { { echo "$as_me:$LINENO: error: *** You must supply an argument to the --with-includes option." >&5
+echo "$as_me: error: *** You must supply an argument to the --with-includes option." >&2;}
+   { (exit 1); exit 1; }; }
+           ;;
+       esac
+       CFLAGS="$withval"
+
+fi;
+
+
 # Check whether --with-includes or --without-includes was given.
 if test "${with_includes+set}" = set; then
   withval="$with_includes"
@@ -2176,7 +2199,7 @@ if test "$LIBRARY_DIRS"; then
        for dir in $LIBRARY_DIRS; do
            if test -d "$dir"; then
                case "$target" in
-                 *-solaris2*)
+                 *-solaris2*,*-netbsd*)
                        AMANDA_LDFLAGS="$AMANDA_LDFLAGS -R$dir"
                        ;;
                esac
@@ -2189,6 +2212,40 @@ echo "$as_me: WARNING: *** Library directory $dir does not exist." >&2;}
 fi
 
 
+# Check whether --with-dumperdir or --without-dumperdir was given.
+if test "${with_dumperdir+set}" = set; then
+  withval="$with_dumperdir"
+
+       case "$withval" in
+       "" | y | ye | yes | n | no)
+           { { echo "$as_me:$LINENO: error: *** You must supply an argument to the --with-dumperdir option." >&5
+echo "$as_me: error: *** You must supply an argument to the --with-dumperdir option." >&2;}
+   { (exit 1); exit 1; }; }
+         ;;
+       esac
+       DUMPER_DIR="$withval"
+
+else
+
+        test "x$prefix" = xNONE && prefix=$ac_default_prefix
+        test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
+        DUMPER_DIR=$exec_prefix/dumper
+
+
+fi;
+DUMPER_DIR=`(
+    test "x$prefix" = xNONE && prefix=$ac_default_prefix
+    test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
+    eval echo "$DUMPER_DIR"
+)`
+
+cat >>confdefs.h <<_ACEOF
+#define DUMPER_DIR "$DUMPER_DIR"
+_ACEOF
+
+
+
+
 # Check whether --with-configdir or --without-configdir was given.
 if test "${with_configdir+set}" = set; then
   withval="$with_configdir"
@@ -2204,7 +2261,7 @@ echo "$as_me: error: *** You must supply an argument to the --with-configdir opt
        esac
 
 else
-  : ${CONFIG_DIR=$sysconfdir/amanda}
+  : ${CONFIG_DIR="$sysconfdir/amanda"}
 
 fi;
 CONFIG_DIR=`(
@@ -2268,7 +2325,7 @@ _ACEOF
 
     program_suffix="-$VERSION"
     # This is from the output of configure.in.
-    if test "$program_transform_name" = s,x,x,; then
+    if test "x$program_transform_name" = xs,x,x,; then
        program_transform_name=
     else
        # Double any \ or $.  echo might interpret backslashes.
@@ -2278,14 +2335,14 @@ EOF_SED
        program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
        rm -f conftestsed
     fi
-    test "$program_prefix" != NONE &&
+    test "x$program_prefix" != xNONE &&
        program_transform_name="s,^,${program_prefix},; $program_transform_name"
     # Use a double $ so make ignores it.
-    test "$program_suffix" != NONE &&
+    test "x$program_suffix" != xNONE &&
        program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
 
     # sed with no file args requires a program.
-    test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+    test "x$program_transform_name" = "" && program_transform_name="xs,x,x,"
     # Remove empty command
     cat <<\EOF_SED > conftestsed
 s,\;\;,\;,g; s,\; \$,,g; s,\;$,,g
@@ -2645,8 +2702,8 @@ else
        if test -z "$DEFAULT_TAPE_DEVICE"; then
            echo "$as_me:$LINENO: checking for non-rewinding tape device" >&5
 echo $ECHO_N "checking for non-rewinding tape device... $ECHO_C" >&6
-                                                                   tape_dev=/dev/null
-           nr_tape_dev=/dev/null
+                                                                   tape_dev=null:
+           nr_tape_dev=null:
            if test -d /dev/rmt; then
 
 
@@ -2853,31 +2910,6 @@ echo "$as_me: error: *** You must supply a full pathname to --with-gnutar" >&2;}
 fi;
 
 
-# Check whether --with-qde or --without-qde was given.
-if test "${with_qde+set}" = set; then
-  withval="$with_qde"
-  USE_QUICK_AND_DIRTY_ESTIMATES=$withval
-else
-  : ${USE_QUICK_AND_DIRTY_ESTIMATES=no}
-
-fi;
-case "$USE_QUICK_AND_DIRTY_ESTIMATES" in
-n | no) : USE_QUICK_AND_DIRTY_ESTIMATES=no;;
-y |  ye | yes) : USE_QUICK_AND_DIRTY_ESTIMATES=yes
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_QUICK_AND_DIRTY_ESTIMATES 1
-_ACEOF
-
-  ;;
-*) { { echo "$as_me:$LINENO: error: *** You must not supply an argument to --with-qde option." >&5
-echo "$as_me: error: *** You must not supply an argument to --with-qde option." >&2;}
-   { (exit 1); exit 1; }; }
-  ;;
-esac
-
-
-
 # Check whether --with-smbclient or --without-smbclient was given.
 if test "${with_smbclient+set}" = set; then
   withval="$with_smbclient"
@@ -2885,7 +2917,7 @@ if test "${with_smbclient+set}" = set; then
        case "$withval" in
            /*) SAMBA_CLIENT="$withval";;
            y|ye|yes) :;;
-           n|no) SAMBA_CLIENT="no";;
+           n|no) SAMBA_CLIENT=;;
            *)  { { echo "$as_me:$LINENO: error: *** You must supply a full pathname to --with-smbclient" >&5
 echo "$as_me: error: *** You must supply a full pathname to --with-smbclient" >&2;}
    { (exit 1); exit 1; }; };;
@@ -2920,7 +2952,7 @@ echo "$as_me: error: *** You must supply a full pathname to --with-gnutar-listdi
        esac
 
 else
-  : ${GNUTAR_LISTDIR=$localstatedir/amanda/gnutar-lists}
+  : ${GNUTAR_LISTDIR="$localstatedir/amanda/gnutar-lists"}
 
 fi;
 if test "$GNUTAR_LISTDIR"; then
@@ -2949,6 +2981,8 @@ echo "$as_me: error: *** The gnutar-listed-incremental option was deprecated, us
 
 
 fi;
+GNUTAR_LISTED_INCREMENTAL_DIR=$GNUTAR_LISTDIR
+
 
 
 # Check whether --with-bsd-security or --without-bsd-security was given.
@@ -3001,6 +3035,28 @@ echo "$as_me: error: *** You must not supply an argument to --with-amandahosts o
 esac
 
 
+
+# Check whether --with-dbmalloc or --without-dbmalloc was given.
+if test "${with_dbmalloc+set}" = set; then
+  withval="$with_dbmalloc"
+  DBMALLOC="$withval"
+else
+  : ${DBMALLOC=no}
+
+fi;
+
+case "$DBMALLOC" in
+n | no)
+    DBMALLOCCFLAGS=""
+    DBMALLOCLIBS=""
+    ;;
+*)
+    DBMALLOCCFLAGS="-I$DBMALLOC -DUSE_DBMALLOC"
+    DBMALLOCLIBS="-L$DBMALLOC -ldbmalloc"
+    ;;
+esac
+
+
 : ${KRB4_SPOTS="/usr/kerberos /usr/cygnus /usr /opt/kerberos"}
 
 
@@ -3023,7 +3079,7 @@ esac
 
 echo "$as_me:$LINENO: checking for Kerberos and Amanda kerberos4 bits" >&5
 echo $ECHO_N "checking for Kerberos and Amanda kerberos4 bits... $ECHO_C" >&6
-if test "${KRB4_SECURITY}" = yes -a -f  ${srcdir-.}/common-src/krb4-security.c ; then
+if test "x${KRB4_SECURITY}" = xyes -a -f  ${srcdir-.}/common-src/krb4-security.c ; then
     for dir in $KRB4_SPOTS; do
        if test -f ${dir}/lib/libkrb.a -a -f ${dir}/lib/libdes.a ; then
            #
@@ -3047,12 +3103,9 @@ _ACEOF
            fi
            KRB4LDFLAGS=-L$dir/lib
            KRB4LIBS="-lkrb -ldes"
-           if test -f ${dir}/lib/libcom_err.a ; then
+           if test -f ${dir}/lib/libcom_err.a; then
                KRB4LIBS="$KRB4LIBS -lcom_err"
            fi
-           if test -f ${dir}/lib/libroken.a ; then
-               KRB4LIBS="$KRB4LIBS -lroken"
-           fi
            break
        elif test -f ${dir}/lib/libkrb4.a &&
             test -f ${dir}/lib/libcrypto.a &&
@@ -3077,36 +3130,12 @@ _ACEOF
                KRB4LIBS="-lkrb4 -lcrypto -ldes425"
            fi
            break
-       elif test -f ${dir}/lib/libkrb4.dylib &&
-            test -f ${dir}/lib/libcrypto.dylib &&
-            test -f ${dir}/lib/libdes425.dylib ; then
-           #
-           # This is Kerberos 5 with Kerberos 4 back-support for Mac OS X.
-           #
-           echo "$as_me:$LINENO: result: found in $dir" >&5
-echo "${ECHO_T}found in $dir" >&6
-           KRB4_SECURITY=yes
-
-cat >>confdefs.h <<\_ACEOF
-#define KRB4_SECURITY 1
-_ACEOF
-
-           KRB4INCLUDES="-I$dir/include -I$dir/include/kerberosIV"
-           KRB4LDFLAGS=-L$dir/lib
-           if test -f ${dir}/lib/libkrb5.dylib &&
-               test -f ${dir}/lib/libcom_err.dylib; then
-               KRB4LIBS="-lkrb4 -lkrb5 -lcrypto -ldes425 -lcom_err"
-           else
-               KRB4LIBS="-lkrb4 -lcrypto -ldes425"
-           fi
-           break
        fi
     done
 
-    if test "$KRB4LDFLAGS" = "" ; then
-       { { echo "$as_me:$LINENO: error: *** Kerberos IV not found." >&5
-echo "$as_me: error: *** Kerberos IV not found." >&2;}
-   { (exit 1); exit 1; }; }
+    if test "x$KRB4LDFLAGS" = "x" ; then
+       echo "$as_me:$LINENO: result: no libraries found" >&5
+echo "${ECHO_T}no libraries found" >&6
     fi
 else
     echo "$as_me:$LINENO: result: no" >&5
@@ -3114,6 +3143,53 @@ echo "${ECHO_T}no" >&6
 fi
 
 
+# Check whether --with-rsh-security or --without-rsh-security was given.
+if test "${with_rsh_security+set}" = set; then
+  withval="$with_rsh_security"
+  RSH_SECURITY=$withval
+else
+  : ${RSH_SECURITY=yes}
+
+fi;
+case "$RSH_SECURITY" in
+n | no) : ;;
+y |  ye | yes)
+cat >>confdefs.h <<\_ACEOF
+#define RSH_SECURITY 1
+_ACEOF
+
+  ;;
+*) { { echo "$as_me:$LINENO: error: *** You must not supply an argument the to --with-rsh-security option." >&5
+echo "$as_me: error: *** You must not supply an argument the to --with-rsh-security option." >&2;}
+   { (exit 1); exit 1; }; }
+  ;;
+esac
+
+
+# Check whether --with-ssh-security or --without-ssh-security was given.
+if test "${with_ssh_security+set}" = set; then
+  withval="$with_ssh_security"
+  SSH_SECURITY=$withval
+else
+  : ${SSH_SECURITY=no}
+
+fi;
+case "$SSH_SECURITY" in
+n | no) : ;;
+y |  ye | yes)
+cat >>confdefs.h <<\_ACEOF
+#define SSH_SECURITY 1
+_ACEOF
+
+              SSH_SECURITY_SET=true
+  ;;
+*) { { echo "$as_me:$LINENO: error: *** You must not supply an argument the to --with-ssh-security option." >&5
+echo "$as_me: error: *** You must not supply an argument the to --with-ssh-security option." >&2;}
+   { (exit 1); exit 1; }; }
+  ;;
+esac
+
+
 # Check whether --with-server-principal or --without-server-principal was given.
 if test "${with_server_principal+set}" = set; then
   withval="$with_server_principal"
@@ -3260,7 +3336,7 @@ else
 fi;
 
 # Assume it's either KEYFILE (defined in krb.h), or a string filename...
-if test "$CLIENT_HOST_KEY_FILE" != "KEYFILE"; then
+if test "x$CLIENT_HOST_KEY_FILE" != "xKEYFILE"; then
   CLIENT_HOST_KEY_FILE="\"$CLIENT_HOST_KEY_FILE\""
 fi
 
@@ -3296,6 +3372,90 @@ _ACEOF
 
 
 
+: ${KRB5_SPOTS="/usr/kerberos /usr/cygnus /usr /opt/kerberos"}
+
+
+# Check whether --with-krb5-security or --without-krb5-security was given.
+if test "${with_krb5_security+set}" = set; then
+  withval="$with_krb5_security"
+  KRB5_SECURITY="$withval"
+else
+  : ${KRB5_SECURITY=no}
+
+fi;
+
+case "$KRB5_SECURITY" in
+n | no) KRB5_SECURITY=no
+        KRB5_SPOTS=""
+       ;;
+y | ye | yes) : ;;
+*) KRB5_SPOTS="$KRB5_SECURITY"
+   KRB5_SECURITY=yes
+   ;;
+esac
+
+# if found, force the static versions of these libs (.a) by linking directly
+# with the .a files.  I don't know how to get -R dependancies checked
+# in autoconf at this time. -kashmir
+echo "$as_me:$LINENO: checking for Kerberos V" >&5
+echo $ECHO_N "checking for Kerberos V... $ECHO_C" >&6
+KRB5_DIR_FOUND=""
+KRB5_CFLAGS=""
+for dir in $KRB5_SPOTS; do
+    k5libdir=${dir}/lib
+    if test -f ${k5libdir}/libkrb5.a -a -f ${k5libdir}/libgssapi_krb5.a -a -f ${k5libdir}/libcom_err.a; then
+       if test -f ${k5libdir}/libcrypto.a; then
+           K5CRYPTO=${k5libdir}/libcrypto.a
+       elif test -f ${k5libdir}/libk5crypto.a; then
+           K5CRYPTO=${k5libdir}/libk5crypto.a
+       else
+           K5CRYPTO=""
+       fi
+       KRB5_DIR_FOUND=$dir
+       KRB5LIBS="${k5libdir}/libgssapi_krb5.a ${k5libdir}/libkrb5.a $K5CRYPTO ${k5libdir}/libcom_err.a"
+       KRB5CFLAGS=""
+       break
+    elif test -f ${k5libdir}/libkrb5.a -a -f ${k5libdir}/libasn1.a -a -f ${k5libdir}/libgssapi.a; then
+       KRB5_DIR_FOUND=$dir
+       KRB5LIBS="${k5libdir}/libgssapi.a ${k5libdir}/libkrb5.a ${k5libdir}/libasn1.a"
+       KRB5_CFLAGS="-DKRB5_HEIMDAL_INCLUDES"
+       break
+    fi
+done
+
+if test "$KRB5_DIR_FOUND"; then
+       echo "$as_me:$LINENO: result: found in $KRB5_DIR_FOUND" >&5
+echo "${ECHO_T}found in $KRB5_DIR_FOUND" >&6
+       KRB5_SECURITY=yes
+
+cat >>confdefs.h <<\_ACEOF
+#define KRB5_SECURITY 1
+_ACEOF
+
+       #
+       # some OS's, such as NetBSD, stick krb5 includes out of the way...
+       # should probably just use autoconf to look for various include
+       # options and set them, but don't quite want to do that until I've
+       # dug into it a bit more.
+       #
+       if test -d "$KRB5_DIR_FOUND/krb5" ; then
+               KRB5INCLUDES="-I$KRB5_DIR_FOUND/include/krb5"
+       else
+               KRB5INCLUDES="-I$KRB5_DIR_FOUND/include"
+       fi
+       if test "$KRB5_CFLAGS" ; then
+               KRB5INCLUDES="$KRB5INCLUDES $KRB5_CFLAGS"
+       fi
+       KRB5LDFLAGS=-L$k5libdir
+       break
+fi
+
+if test "x$KRB5LDFLAGS" = "x" ; then
+    echo "$as_me:$LINENO: result: no krb5 system libraries found" >&5
+echo "${ECHO_T}no krb5 system libraries found" >&6
+fi
+
+
 
 # Check whether --with-portrange or --without-portrange was given.
 if test "${with_portrange+set}" = set; then
@@ -3540,8 +3700,8 @@ debugging=`(
 )`
 case "$debugging" in
 n | no) AMANDA_DBGDIR="";;
-y |  ye | yes) AMANDA_DBGDIR="$AMANDA_TMPDIR" ;;
-/*) AMANDA_DBGDIR="$debugging" ;;
+y |  ye | yes) AMANDA_DBGDIR="$AMANDA_TMPDIR";;
+/*) AMANDA_DBGDIR="$debugging";;
 *) { { echo "$as_me:$LINENO: error: *** You must supply a full pathname to --with-debugging option." >&5
 echo "$as_me: error: *** You must supply a full pathname to --with-debugging option." >&2;}
    { (exit 1); exit 1; }; }
@@ -4818,6 +4978,8 @@ _ACEOF
                        ;;
   *-pc-linux-*)
                        ;;
+  x86_64-*-linux-*)
+                       ;;
   alpha*-*-linux-*)
                        ;;
   sparc*-*-linux-*)
@@ -4932,10 +5094,10 @@ _ACEOF
 
 fi
 
-AMANDA_CFLAGS="$AMANDA_CFLAGS $KRB4INCLUDES"
-AMANDA_CPPFLAGS="$AMANDA_CPPFLAGS $KRB4INCLUDES"
-AMANDA_LDFLAGS="$AMANDA_LDFLAGS $KRB4LDFLAGS"
-AMANDA_LIBS="$KRB4LIBS $AMANDA_LIBS"
+AMANDA_CFLAGS="$AMANDA_CFLAGS $KRB4INCLUDES $KRB5INCLUDES $DBMALLOCCFLAGS"
+AMANDA_CPPFLAGS="$AMANDA_CPPFLAGS $KRB4INCLUDES $KRB5INCLUDES $DBMALLOCINCLUDES"
+AMANDA_LDFLAGS="$AMANDA_LDFLAGS $KRB4LDFLAGS $KRB5LDFLAGS"
+AMANDA_LIBS="$KRB4LIBS $KRB5LIBS $DBMALLOCLIBS $AMANDA_LIBS"
 CFLAGS="$CFLAGS $AMANDA_CFLAGS"
 CPPFLAGS="$CPPFLAGS $AMANDA_CPPFLAGS"
 LDFLAGS="$LDFLAGS $AMANDA_LDFLAGS"
@@ -5526,6 +5688,7 @@ if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
 inttype_headers=`echo  | sed -e 's/,/ /g'`
 
 ac_cv_stdint_result="(no helpful system typedefs seen)"
+
 echo "$as_me:$LINENO: checking for stdint uintptr_t" >&5
 echo $ECHO_N "checking for stdint uintptr_t... $ECHO_C" >&6
 if test "${ac_cv_header_stdint_x+set}" = set; then
@@ -5535,7 +5698,7 @@ else
  ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
   echo "$as_me:$LINENO: result: (..)" >&5
 echo "${ECHO_T}(..)" >&6
-  for i in stdint.h inttypes.h sys/inttypes.h $inttype_headers ; do
+  for i in    stdint.h inttypes.h sys/inttypes.h $inttype_headers ; do
    unset ac_cv_type_uintptr_t
    unset ac_cv_type_uint64_t
    echo "$as_me:$LINENO: checking for uintptr_t" >&5
@@ -5598,7 +5761,7 @@ echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6
 if test $ac_cv_type_uintptr_t = yes; then
   ac_cv_header_stdint_x=$i
 else
-       continue
+  continue
 fi
 
    echo "$as_me:$LINENO: checking for uint64_t" >&5
@@ -5664,8 +5827,8 @@ else
   and64=""
 fi
 
-   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)"
-   break;
+      stdint.h inttypes.h sys/inttypes.h $inttype_headers
+ break
   done
   echo "$as_me:$LINENO: checking for stdint uintptr_t" >&5
 echo $ECHO_N "checking for stdint uintptr_t... $ECHO_C" >&6
@@ -5674,7 +5837,9 @@ fi
 echo "$as_me:$LINENO: result: $ac_cv_header_stdint_x" >&5
 echo "${ECHO_T}$ac_cv_header_stdint_x" >&6
 
+
 if test "_$ac_cv_header_stdint_x" = "_" ; then
+
 echo "$as_me:$LINENO: checking for stdint uint32_t" >&5
 echo $ECHO_N "checking for stdint uint32_t... $ECHO_C" >&6
 if test "${ac_cv_header_stdint_o+set}" = set; then
@@ -5684,7 +5849,7 @@ else
  ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
   echo "$as_me:$LINENO: result: (..)" >&5
 echo "${ECHO_T}(..)" >&6
-  for i in inttypes.h sys/inttypes.h stdint.h $inttype_headers ; do
+  for i in    inttypes.h sys/inttypes.h stdint.h $inttype_headers ; do
    unset ac_cv_type_uint32_t
    unset ac_cv_type_uint64_t
    echo "$as_me:$LINENO: checking for uint32_t" >&5
@@ -5747,7 +5912,7 @@ echo "${ECHO_T}$ac_cv_type_uint32_t" >&6
 if test $ac_cv_type_uint32_t = yes; then
   ac_cv_header_stdint_o=$i
 else
-       continue
+  continue
 fi
 
    echo "$as_me:$LINENO: checking for uint64_t" >&5
@@ -5813,7 +5978,8 @@ else
   and64=""
 fi
 
-   ac_cv_stdint_result="(seen uint32_t$and64 in $i)"
+      inttypes.h sys/inttypes.h stdint.h $inttype_headers
+ break
    break;
   done
   echo "$as_me:$LINENO: checking for stdint uint32_t" >&5
@@ -5822,10 +5988,12 @@ echo $ECHO_N "checking for stdint uint32_t... $ECHO_C" >&6
 fi
 echo "$as_me:$LINENO: result: $ac_cv_header_stdint_o" >&5
 echo "${ECHO_T}$ac_cv_header_stdint_o" >&6
+
 fi
 
 if test "_$ac_cv_header_stdint_x" = "_" ; then
 if test "_$ac_cv_header_stdint_o" = "_" ; then
+
 echo "$as_me:$LINENO: checking for stdint u_int32_t" >&5
 echo $ECHO_N "checking for stdint u_int32_t... $ECHO_C" >&6
 if test "${ac_cv_header_stdint_u+set}" = set; then
@@ -5835,7 +6003,7 @@ else
  ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
   echo "$as_me:$LINENO: result: (..)" >&5
 echo "${ECHO_T}(..)" >&6
-  for i in sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do
+  for i in    sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do
    unset ac_cv_type_u_int32_t
    unset ac_cv_type_u_int64_t
    echo "$as_me:$LINENO: checking for u_int32_t" >&5
@@ -5898,7 +6066,7 @@ echo "${ECHO_T}$ac_cv_type_u_int32_t" >&6
 if test $ac_cv_type_u_int32_t = yes; then
   ac_cv_header_stdint_u=$i
 else
-       continue
+  continue
 fi
 
    echo "$as_me:$LINENO: checking for u_int64_t" >&5
@@ -5964,7 +6132,8 @@ else
   and64=""
 fi
 
-   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)"
+      sys/types.h inttypes.h sys/inttypes.h $inttype_headers
+ break
    break;
   done
   echo "$as_me:$LINENO: checking for stdint u_int32_t" >&5
@@ -5973,6 +6142,7 @@ echo $ECHO_N "checking for stdint u_int32_t... $ECHO_C" >&6
 fi
 echo "$as_me:$LINENO: result: $ac_cv_header_stdint_u" >&5
 echo "${ECHO_T}$ac_cv_header_stdint_u" >&6
+
 fi fi
 
 if test "_$ac_cv_header_stdint_x" = "_" ; then
@@ -5980,6 +6150,7 @@ if test "_$ac_cv_header_stdint_x" = "_" ; then
 echo $ECHO_N "checking for stdint datatype model... $ECHO_C" >&6
    echo "$as_me:$LINENO: result: (..)" >&5
 echo "${ECHO_T}(..)" >&6
+
    echo "$as_me:$LINENO: checking for char" >&5
 echo $ECHO_N "checking for char... $ECHO_C" >&6
 if test "${ac_cv_type_char+set}" = set; then
@@ -8050,30 +8221,38 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-   ac_cv_stdint_char_model=""
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_char"
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_short"
-   ac_cv_stdint_char_model="$ac_cv_stdint_char_model$ac_cv_sizeof_int"
-   ac_cv_stdint_long_model=""
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_int"
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_long"
-   ac_cv_stdint_long_model="$ac_cv_stdint_long_model$ac_cv_sizeof_voidp"
-   name="$ac_cv_stdint_long_model"
-   case "$ac_cv_stdint_char_model/$ac_cv_stdint_long_model" in
-    122/242)     name="$name,  IP16 (standard 16bit machine)" ;;
-    122/244)     name="$name,  LP32 (standard 32bit mac/win)" ;;
-    122/*)       name="$name        (unusual int16 model)" ;;
-    124/444)     name="$name, ILP32 (standard 32bit unixish)" ;;
-    124/488)     name="$name,  LP64 (standard 64bit unixish)" ;;
-    124/448)     name="$name, LLP64 (unusual  64bit unixish)" ;;
-    124/*)       name="$name        (unusual int32 model)" ;;
-    128/888)     name="$name, ILP64 (unusual  64bit numeric)" ;;
-    128/*)       name="$name        (unusual int64 model)" ;;
-    222/*|444/*) name="$name        (unusual dsptype)" ;;
-     *)          name="$name        (very unusal model)" ;;
+   ac_cv_char_data_model=""
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model=""
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+   echo "$as_me:$LINENO: checking data model" >&5
+echo $ECHO_N "checking data model... $ECHO_C" >&6
+   case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+    122/242)     ac_cv_data_model="IP16"  ; n="standard 16bit machine" ;;
+    122/244)     ac_cv_data_model="LP32"  ; n="standard 32bit machine" ;;
+    122/*)       ac_cv_data_model="i16"   ; n="unusual int16 model" ;;
+    124/444)     ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+    124/488)     ac_cv_data_model="LP64"  ; n="standard 64bit unixish" ;;
+    124/448)     ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+    124/*)       ac_cv_data_model="i32"   ; n="unusual int32 model" ;;
+    128/888)     ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+    128/*)       ac_cv_data_model="i64"   ; n="unusual int64 model" ;;
+    222/*2)      ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+    333/*3)      ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+    444/*4)      ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+    666/*6)      ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+    888/*8)      ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+    222/*|333/*|444/*|666/*|888/*) :
+                 ac_cv_data_model="iDSP"  ; n="unusual dsptype" ;;
+     *)          ac_cv_data_model="none"  ; n="very unusual model" ;;
    esac
-   echo "$as_me:$LINENO: result: combined for stdint datatype model...  $name" >&5
-echo "${ECHO_T}combined for stdint datatype model...  $name" >&6
+   echo "$as_me:$LINENO: result: $ac_cv_data_model ($ac_cv_long_data_model, $n)" >&5
+echo "${ECHO_T}$ac_cv_data_model ($ac_cv_long_data_model, $n)" >&6
+
 fi
 
 if test "_$ac_cv_header_stdint_x" != "_" ; then
@@ -8410,7 +8589,7 @@ echo "${ECHO_T}$amanda_cv_awk_var_assignment" >&6
 
 
 
-if test "$amanda_cv_awk_var_assignment" = no; then
+if test "x$amanda_cv_awk_var_assignment" = xno; then
     NO_AMPLOT_MODE=true
     { echo "$as_me:$LINENO: WARNING: *** Your $awk cannot do command line variable assignment.  Amplot will not be installed." >&5
 echo "$as_me: WARNING: *** Your $awk cannot do command line variable assignment.  Amplot will not be installed." >&2;}
@@ -8845,8 +9024,7 @@ echo "$as_me: WARNING: *** $GNUTAR is not GNU tar, so it will not be used." >&2;
   esac
 fi
 
-if test "x$SAMBA_CLIENT" != "xno"
-then for ac_prog in smbclient
+for ac_prog in smbclient
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -8890,8 +9068,6 @@ fi
   test -n "$SAMBA_CLIENT" && break
 done
 
-else SAMBA_CLIENT=
-fi
 if test ! -z "$SAMBA_CLIENT"; then
   case "`\"$SAMBA_CLIENT\" '\\\\not.a.host.name\\notashare' -U nosuchuser -N -Tx /dev/null 2>&1`" in
   *"Unknown host"*)
@@ -8918,10 +9094,8 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
   fi
-
 fi
 
-
 for ac_prog in gzip
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
@@ -9655,7 +9829,7 @@ echo "${ECHO_T}$amanda_cv_dump_estimate" >&6
 echo "$as_me: WARNING: *** $DUMP is not executable, cannot run -E/-S test" >&2;}
        amanda_cv_dump_estimate=no
     fi
-    if test "$amanda_cv_dump_estimate" != no; then
+    if test "x$amanda_cv_dump_estimate" != xno; then
 
 cat >>confdefs.h <<_ACEOF
 #define HAVE_DUMP_ESTIMATE "$amanda_cv_dump_estimate"
@@ -9720,7 +9894,7 @@ echo "${ECHO_T}$amanda_cv_honor_nodump" >&6
 echo "$as_me: WARNING: *** $DUMP is not executable, cannot run -h test" >&2;}
        amanda_cv_honor_nodump=no
       fi
-      if test "$amanda_cv_honor_nodump" = yes; then
+      if test "x$amanda_cv_honor_nodump" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_HONOR_NODUMP 1
@@ -9975,160 +10149,2299 @@ if test -n "$VDUMP"; then
   echo "$as_me:$LINENO: result: $VDUMP" >&5
 echo "${ECHO_T}$VDUMP" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  test -n "$VDUMP" && break
-done
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$VDUMP" && break
+done
+
+for ac_prog in vrestore
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_VRESTORE+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $VRESTORE in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_VRESTORE="$VRESTORE" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $SYSLOCPATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_VRESTORE="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+VRESTORE=$ac_cv_path_VRESTORE
+
+if test -n "$VRESTORE"; then
+  echo "$as_me:$LINENO: result: $VRESTORE" >&5
+echo "${ECHO_T}$VRESTORE" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$VRESTORE" && break
+done
+
+if test "$VDUMP" -a "$VRESTORE"; then
+
+cat >>confdefs.h <<_ACEOF
+#define VDUMP "$VDUMP"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VRESTORE "$VRESTORE"
+_ACEOF
+
+fi
+
+if test "$PCAT"; then
+    AMPLOT_CAT_PACK="if(o==\"z\")print \"$PCAT\"; else"
+else
+    AMPLOT_CAT_PACK=
+fi
+if test "$COMPRESS"; then
+    AMPLOT_COMPRESS=$COMPRESS
+    AMPLOT_CAT_COMPRESS="if(o==\"Z\")print \"$COMPRESS -dc\"; else"
+else
+    AMPLOT_CAT_COMPRESS=
+fi
+if test "$GZIP"; then
+    AMPLOT_COMPRESS=$GZIP
+    AMPLOT_CAT_GZIP="if(o==\"gz\")print \"$GZIP -dc\"; else"
+else
+    AMPLOT_CAT_GZIP=
+fi
+
+
+
+
+
+# Determine the printf format characters to use when printing
+# values of type long long. This will normally be "ll", but where
+# the compiler treats "long long" as a alias for "long" and printf
+# doesn't know about "long long" use "l".  Hopefully the sprintf
+# will produce a inconsistant result in the later case.  If the compiler
+# fails due to seeing "%lld" we fall back to "l".
+#
+# Win32 uses "%I64d", but that's defined elsewhere since we don't use
+# configure on Win32.
+#
+echo "$as_me:$LINENO: checking printf format modifier for 64-bit integers" >&5
+echo $ECHO_N "checking printf format modifier for 64-bit integers... $ECHO_C" >&6
+if test "$cross_compiling" = yes; then
+  echo "$as_me:$LINENO: result: assuming target platform uses ll" >&5
+echo "${ECHO_T}assuming target platform uses ll" >&6
+       LL_FMT="%lld"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdio.h>
+main() {
+       long long int j = 0;
+       char buf[100];
+       buf[0] = 0;
+       sprintf(buf, "%lld", j);
+       exit((sizeof(long long int) != sizeof(long int))? 0 :
+            (strcmp(buf, "0") != 0));
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: ll" >&5
+echo "${ECHO_T}ll" >&6
+       LL_FMT="%lld"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+echo "$as_me:$LINENO: result: l" >&5
+echo "${ECHO_T}l" >&6
+       LL_FMT="%ld"
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define LL_FMT "$LL_FMT"
+_ACEOF
+
+
+
+GZIP=
+
+need_resetofs=yes
+echo "$as_me:$LINENO: checking for large file compilation CFLAGS" >&5
+echo $ECHO_N "checking for large file compilation CFLAGS... $ECHO_C" >&6
+if test "${amanda_cv_LFS_CFLAGS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       amanda_cv_LFS_CFLAGS=
+       if test "$GETCONF"; then
+           if $GETCONF ${GETCONF_LFS}_CFLAGS >/dev/null 2>&1; then
+               amanda_cv_LFS_CFLAGS=`$GETCONF ${GETCONF_LFS}_CFLAGS 2>/dev/null`
+               need_resetofs=no
+           fi
+       fi
+
+
+fi
+echo "$as_me:$LINENO: result: $amanda_cv_LFS_CFLAGS" >&5
+echo "${ECHO_T}$amanda_cv_LFS_CFLAGS" >&6
+echo "$as_me:$LINENO: checking for large file compilation LDFLAGS" >&5
+echo $ECHO_N "checking for large file compilation LDFLAGS... $ECHO_C" >&6
+if test "${amanda_cv_LFS_LDFLAGS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       amanda_cv_LFS_LDFLAGS=
+       if test "$GETCONF"; then
+           if $GETCONF ${GETCONF_LFS}_LDFLAGS >/dev/null 2>&1; then
+               amanda_cv_LFS_LDFLAGS=`$GETCONF ${GETCONF_LFS}_LDFLAGS 2>/dev/null`
+               need_resetofs=no
+           fi
+       fi
+
+
+fi
+echo "$as_me:$LINENO: result: $amanda_cv_LFS_LDFLAGS" >&5
+echo "${ECHO_T}$amanda_cv_LFS_LDFLAGS" >&6
+echo "$as_me:$LINENO: checking for large file compilation LIBS" >&5
+echo $ECHO_N "checking for large file compilation LIBS... $ECHO_C" >&6
+if test "${amanda_cv_LFS_LIBS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       amanda_cv_LFS_LIBS=
+       if test "$GETCONF"; then
+           if $GETCONF ${GETCONF_LFS}_LIBS >/dev/null 2>&1; then
+               amanda_cv_LFS_LIBS=`$GETCONF ${GETCONF_LFS}_LIBS 2>/dev/null`
+               need_resetofs=no
+           fi
+       fi
+
+
+fi
+echo "$as_me:$LINENO: result: $amanda_cv_LFS_LIBS" >&5
+echo "${ECHO_T}$amanda_cv_LFS_LIBS" >&6
+if test "x$need_resetofs" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_RESETOFS 1
+_ACEOF
+
+fi
+CFLAGS="$amanda_cv_LFS_CFLAGS $CFLAGS"
+CPPFLAGS="$amanda_cv_LFS_CFLAGS $CPPFLAGS"
+LDFLAGS="$amanda_cv_LFS_LDFLAGS $LDFLAGS"
+LIBS="$amanda_cv_LFS_LIBS $LIBS"
+
+echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6
+if test "${ac_cv_type_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((int *) 0)
+  return 0;
+if (sizeof (int))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_int=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6
+
+echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_int" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (int)); }
+unsigned long ulongval () { return (long) (sizeof (int)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (int))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (int))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (int))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_int=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for long" >&5
+echo $ECHO_N "checking for long... $ECHO_C" >&6
+if test "${ac_cv_type_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((long *) 0)
+  return 0;
+if (sizeof (long))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_long=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5
+echo "${ECHO_T}$ac_cv_type_long" >&6
+
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_long" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (long)); }
+unsigned long ulongval () { return (long) (sizeof (long)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (long))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (long))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (long))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_long=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for long long" >&5
+echo $ECHO_N "checking for long long... $ECHO_C" >&6
+if test "${ac_cv_type_long_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((long long *) 0)
+  return 0;
+if (sizeof (long long))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_long_long=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long_long=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5
+echo "${ECHO_T}$ac_cv_type_long_long" >&6
+
+echo "$as_me:$LINENO: checking size of long long" >&5
+echo $ECHO_N "checking size of long long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_long_long" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (long long)); }
+unsigned long ulongval () { return (long) (sizeof (long long)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (long long))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (long long))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (long long))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long_long=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_long_long=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for intmax_t" >&5
+echo $ECHO_N "checking for intmax_t... $ECHO_C" >&6
+if test "${ac_cv_type_intmax_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((intmax_t *) 0)
+  return 0;
+if (sizeof (intmax_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_intmax_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_intmax_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_intmax_t" >&5
+echo "${ECHO_T}$ac_cv_type_intmax_t" >&6
+
+echo "$as_me:$LINENO: checking size of intmax_t" >&5
+echo $ECHO_N "checking size of intmax_t... $ECHO_C" >&6
+if test "${ac_cv_sizeof_intmax_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_intmax_t" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (intmax_t))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (intmax_t))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (intmax_t))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (intmax_t))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (intmax_t))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_intmax_t=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (intmax_t), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (intmax_t), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (intmax_t)); }
+unsigned long ulongval () { return (long) (sizeof (intmax_t)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (intmax_t))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (intmax_t))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (intmax_t))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_intmax_t=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (intmax_t), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (intmax_t), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_intmax_t=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_intmax_t" >&5
+echo "${ECHO_T}$ac_cv_sizeof_intmax_t" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INTMAX_T $ac_cv_sizeof_intmax_t
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+  return 0;
+if (sizeof (off_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+
+echo "$as_me:$LINENO: checking size of off_t" >&5
+echo $ECHO_N "checking size of off_t... $ECHO_C" >&6
+if test "${ac_cv_sizeof_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_off_t" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (off_t))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (off_t))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (off_t))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (off_t))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-for ac_prog in vrestore
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_path_VRESTORE+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
 else
-  case $VRESTORE in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_VRESTORE="$VRESTORE" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $SYSLOCPATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_VRESTORE="$as_dir/$ac_word$ac_exec_ext"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-  ;;
-esac
+ac_lo= ac_hi=
 fi
-VRESTORE=$ac_cv_path_VRESTORE
-
-if test -n "$VRESTORE"; then
-  echo "$as_me:$LINENO: result: $VRESTORE" >&5
-echo "${ECHO_T}$VRESTORE" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-
-  test -n "$VRESTORE" && break
-done
-
-if test "$VDUMP" -a "$VRESTORE"; then
-
-cat >>confdefs.h <<_ACEOF
-#define VDUMP "$VDUMP"
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (off_t))) <= $ac_mid)];
+test_array [0] = 0
 
-
-cat >>confdefs.h <<_ACEOF
-#define VRESTORE "$VRESTORE"
+  ;
+  return 0;
+}
 _ACEOF
-
-fi
-
-if test "$PCAT"; then
-    AMPLOT_CAT_PACK="if(o==\"z\")print \"$PCAT\"; else"
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
 else
-    AMPLOT_CAT_PACK=
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
 fi
-if test "$COMPRESS"; then
-    AMPLOT_COMPRESS=$COMPRESS
-    AMPLOT_CAT_COMPRESS="if(o==\"Z\")print \"$COMPRESS -dc\"; else"
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_off_t=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (off_t), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (off_t), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
 else
-    AMPLOT_CAT_COMPRESS=
-fi
-if test "$GZIP"; then
-    AMPLOT_COMPRESS=$GZIP
-    AMPLOT_CAT_GZIP="if(o==\"gz\")print \"$GZIP -dc\"; else"
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
 else
-    AMPLOT_CAT_GZIP=
-fi
-
-
-
-
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (off_t)); }
+unsigned long ulongval () { return (long) (sizeof (off_t)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
 
-GZIP=
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (off_t))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (off_t))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (off_t))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
 
-need_resetofs=yes
-echo "$as_me:$LINENO: checking for large file compilation CFLAGS" >&5
-echo $ECHO_N "checking for large file compilation CFLAGS... $ECHO_C" >&6
-if test "${amanda_cv_LFS_CFLAGS+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_off_t=`cat conftest.val`
 else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-       amanda_cv_LFS_CFLAGS=
-       if test "$GETCONF"; then
-           if $GETCONF ${GETCONF_LFS}_CFLAGS >/dev/null 2>&1; then
-               amanda_cv_LFS_CFLAGS=`$GETCONF ${GETCONF_LFS}_CFLAGS 2>/dev/null`
-               need_resetofs=no
-           fi
-       fi
-
-
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (off_t), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (off_t), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
 fi
-echo "$as_me:$LINENO: result: $amanda_cv_LFS_CFLAGS" >&5
-echo "${ECHO_T}$amanda_cv_LFS_CFLAGS" >&6
-echo "$as_me:$LINENO: checking for large file compilation LDFLAGS" >&5
-echo $ECHO_N "checking for large file compilation LDFLAGS... $ECHO_C" >&6
-if test "${amanda_cv_LFS_LDFLAGS+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
-       amanda_cv_LFS_LDFLAGS=
-       if test "$GETCONF"; then
-           if $GETCONF ${GETCONF_LFS}_LDFLAGS >/dev/null 2>&1; then
-               amanda_cv_LFS_LDFLAGS=`$GETCONF ${GETCONF_LFS}_LDFLAGS 2>/dev/null`
-               need_resetofs=no
-           fi
-       fi
-
-
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $amanda_cv_LFS_LDFLAGS" >&5
-echo "${ECHO_T}$amanda_cv_LFS_LDFLAGS" >&6
-echo "$as_me:$LINENO: checking for large file compilation LIBS" >&5
-echo $ECHO_N "checking for large file compilation LIBS... $ECHO_C" >&6
-if test "${amanda_cv_LFS_LIBS+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+rm -f conftest.val
 else
-
-       amanda_cv_LFS_LIBS=
-       if test "$GETCONF"; then
-           if $GETCONF ${GETCONF_LFS}_LIBS >/dev/null 2>&1; then
-               amanda_cv_LFS_LIBS=`$GETCONF ${GETCONF_LFS}_LIBS 2>/dev/null`
-               need_resetofs=no
-           fi
-       fi
-
-
+  ac_cv_sizeof_off_t=0
 fi
-echo "$as_me:$LINENO: result: $amanda_cv_LFS_LIBS" >&5
-echo "${ECHO_T}$amanda_cv_LFS_LIBS" >&6
-if test "$need_resetofs" = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define NEED_RESETOFS 1
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_off_t" >&5
+echo "${ECHO_T}$ac_cv_sizeof_off_t" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_OFF_T $ac_cv_sizeof_off_t
 _ACEOF
 
-fi
-CFLAGS="$amanda_cv_LFS_CFLAGS $CFLAGS"
-CPPFLAGS="$amanda_cv_LFS_CFLAGS $CPPFLAGS"
-LDFLAGS="$amanda_cv_LFS_LDFLAGS $LDFLAGS"
-LIBS="$amanda_cv_LFS_LIBS $LIBS"
+
 
 # Check whether --enable-shared or --disable-shared was given.
 if test "${enable_shared+set}" = set; then
@@ -10317,7 +12630,7 @@ else
     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
       lt_cv_path_LD="$ac_dir/$ac_prog"
       # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some GNU ld's only accept -v.
+      # but apparently some variants of GNU ld only accept -v.
       # Break only if it was the GNU/non-GNU ld that we prefer.
       case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
       *GNU* | *'with BFD'*)
@@ -10351,7 +12664,7 @@ echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
 if test "${lt_cv_prog_gnu_ld+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
 case `$LD -v 2>&1 </dev/null` in
 *GNU* | *'with BFD'*)
   lt_cv_prog_gnu_ld=yes
@@ -10521,7 +12834,7 @@ gnu*)
 
 hpux10.20* | hpux11*)
   lt_cv_file_magic_cmd=/usr/bin/file
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
     lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
@@ -10664,7 +12977,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 10667 "configure"' > conftest.$ac_ext
+  echo '#line 12980 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -10707,7 +13020,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-    case "`/usr/bin/file conftest.o`" in
+    case `/usr/bin/file conftest.o` in
     *32-bit*)
       case $host in
         x86_64-*linux*)
@@ -11770,7 +14083,7 @@ fi
 
 
 # Provide some information about the compiler.
-echo "$as_me:11773:" \
+echo "$as_me:14086:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -11967,7 +14280,7 @@ else
     elif test -x /usr/sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
     else
-      lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
     fi
     # And add a safety zone
     lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
@@ -12282,7 +14595,7 @@ rm="rm -f"
 default_ofile=libtool
 can_build_shared=yes
 
-# All known linkers require a `.a' archive for static linking (except M$VC,
+# All known linkers require a `.a' archive for static linking (except MSVC,
 # which needs '.lib').
 libext=a
 ltmain="$ac_aux_dir/ltmain.sh"
@@ -12603,7 +14916,7 @@ else
       if test -n "$file_magic_test_file"; then
        case $deplibs_check_method in
        "file_magic "*)
-         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
          MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
          if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
            $EGREP "$file_magic_regex" > /dev/null; then
@@ -12665,7 +14978,7 @@ else
       if test -n "$file_magic_test_file"; then
        case $deplibs_check_method in
        "file_magic "*)
-         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
          MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
          if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
            $EGREP "$file_magic_regex" > /dev/null; then
@@ -12814,7 +15127,7 @@ else
    LDFLAGS="$LDFLAGS $lt_prog_compiler_static"
    printf "$lt_simple_link_test_code" > conftest.$ac_ext
    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
-     # The compiler can only warn and ignore the option if not recognized
+     # The linker can only warn and ignore the option if not recognized
      # So say no if there are warnings
      if test -s conftest.err; then
        # Append any errors to the config.log.
@@ -12869,14 +15182,14 @@ else
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12875: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15188: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:12879: \$? = $ac_status" >&5
+   echo "$as_me:15192: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -12959,7 +15272,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -13006,7 +15319,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
       lt_prog_compiler_wl='-Wl,'
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -13036,12 +15349,12 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
        lt_prog_compiler_pic='-KPIC'
        lt_prog_compiler_static='-static'
         ;;
-      pgcc* | pgf77* | pgf90*)
+      pgcc* | pgf77* | pgf90* | pgf95*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
        # which looks to be a dead project)
        lt_prog_compiler_wl='-Wl,'
        lt_prog_compiler_pic='-fpic'
-       lt_prog_compiler_static='-static'
+       lt_prog_compiler_static='-Bstatic'
         ;;
       ccc*)
         lt_prog_compiler_wl='-Wl,'
@@ -13131,14 +15444,14 @@ else
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13137: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15450: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13141: \$? = $ac_status" >&5
+   echo "$as_me:15454: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13165,7 +15478,7 @@ else
 fi
 
 fi
-case "$host_os" in
+case $host_os in
   # For platforms which do not support PIC, -DPIC is meaningless:
   *djgpp*)
     lt_prog_compiler_pic=
@@ -13193,14 +15506,14 @@ else
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13199: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15512: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13203: \$? = $ac_status" >&5
+   echo "$as_me:15516: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -13211,7 +15524,7 @@ else
        lt_cv_prog_compiler_c_o=yes
      fi
    fi
-   chmod u+w .
+   chmod u+w . 2>&5
    $rm conftest*
    # SGI C++ compiler will create directory out/ii_files/ for
    # template instantiation
@@ -13411,11 +15724,12 @@ EOF
        tmp_addflag=
        case $cc_basename,$host_cpu in
        pgcc*)                          # Portland Group C compiler
-         whole_archive_flag_spec=
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
          ;;
-       pgf77* | pgf90* )                       # Portland Group f77 and f90 compilers
-         whole_archive_flag_spec=
-         tmp_addflag=' -fpic -Mnomain' ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
        ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
          tmp_addflag=' -i_dynamic' ;;
        efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
@@ -13722,7 +16036,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          # Exported symbols can be pulled into shared objects from archives
          whole_archive_flag_spec=' '
          archive_cmds_need_lc=yes
-         # This is similar to how AIX traditionally builds it's shared libraries.
+         # This is similar to how AIX traditionally builds its shared libraries.
          archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
        fi
       fi
@@ -13762,7 +16076,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       ;;
 
     darwin* | rhapsody*)
-      case "$host_os" in
+      case $host_os in
         rhapsody* | darwin1.[012])
          allow_undefined_flag='${wl}-undefined ${wl}suppress'
          ;;
@@ -13791,7 +16105,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        output_verbose_link_cmd='echo'
         archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
       module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
       archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
       module_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
     else
@@ -13800,7 +16114,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          output_verbose_link_cmd='echo'
          archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
          module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
          archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           module_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -13866,7 +16180,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
     hpux10* | hpux11*)
       if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
          ;;
@@ -13875,7 +16189,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          ;;
        esac
       else
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
          ;;
@@ -13885,7 +16199,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        esac
       fi
       if test "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*)
          hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
          hardcode_libdir_flag_spec_ld='+b $libdir'
@@ -14344,7 +16658,8 @@ cygwin* | mingw* | pw32*)
       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
       dldir=$destdir/`dirname \$dlpath`~
       test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
       dlpath=$dir/\$dldll~
        $rm \$dlpath'
@@ -14397,7 +16712,7 @@ darwin* | rhapsody*)
   soname_spec='${libname}${release}${major}$shared_ext'
   shlibpath_overrides_runpath=yes
   shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
   # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
   if test "$GCC" = yes; then
     sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
@@ -14435,7 +16750,14 @@ kfreebsd*-gnu)
 freebsd* | dragonfly*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
   version_type=freebsd-$objformat
   case $version_type in
     freebsd-elf*)
@@ -14480,7 +16802,7 @@ hpux9* | hpux10* | hpux11*)
   version_type=sunos
   need_lib_prefix=no
   need_version=no
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     shrext_cmds='.so'
     hardcode_into_libs=yes
@@ -14577,31 +16899,10 @@ linux*)
   # before this can be enabled.
   hardcode_into_libs=yes
 
-  # find out which ABI we are using
-  libsuff=
-  case "$host_cpu" in
-  x86_64*|s390x*|powerpc64*)
-    echo '#line 14584 "configure"' > conftest.$ac_ext
-    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-      case `/usr/bin/file conftest.$ac_objext` in
-      *64-bit*)
-        libsuff=64
-        sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
-        ;;
-      esac
-    fi
-    rm -rf conftest*
-    ;;
-  esac
-
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -14663,7 +16964,11 @@ nto-qnx*)
 openbsd*)
   version_type=sunos
   need_lib_prefix=no
-  need_version=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
   shlibpath_var=LD_LIBRARY_PATH
@@ -15452,7 +17757,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 15455 "configure"
+#line 17760 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15518,7 +17823,7 @@ EOF
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&5 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
@@ -15550,7 +17855,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 15553 "configure"
+#line 17858 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15616,7 +17921,7 @@ EOF
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&5 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
@@ -15666,7 +17971,7 @@ test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
 # are all built from PIC.
-case "$host_os" in
+case $host_os in
 aix3*)
   test "$enable_shared" = yes && enable_static=no
   if test -n "$RANLIB"; then
@@ -16269,7 +18574,7 @@ postdeps_CXX=
 compiler_lib_search_path_CXX=
 
 # Source file extension for C++ test sources.
-ac_ext=cc
+ac_ext=cpp
 
 # Object file extension for compiled C++ test sources.
 objext=o
@@ -16405,7 +18710,7 @@ else
     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
       lt_cv_path_LD="$ac_dir/$ac_prog"
       # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some GNU ld's only accept -v.
+      # but apparently some variants of GNU ld only accept -v.
       # Break only if it was the GNU/non-GNU ld that we prefer.
       case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
       *GNU* | *'with BFD'*)
@@ -16439,7 +18744,7 @@ echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
 if test "${lt_cv_prog_gnu_ld+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
 case `$LD -v 2>&1 </dev/null` in
 *GNU* | *'with BFD'*)
   lt_cv_prog_gnu_ld=yes
@@ -16719,7 +19024,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        # Exported symbols can be pulled into shared objects from archives
        whole_archive_flag_spec_CXX=' '
        archive_cmds_need_lc_CXX=yes
-       # This is similar to how AIX traditionally builds it's shared libraries.
+       # This is similar to how AIX traditionally builds its shared libraries.
        archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
       fi
     fi
@@ -16758,7 +19063,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     fi
   ;;
       darwin* | rhapsody*)
-        case "$host_os" in
+        case $host_os in
         rhapsody* | darwin1.[012])
          allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
          ;;
@@ -16796,7 +19101,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
           archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
         fi
         module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
           if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
             archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           else
@@ -16809,7 +19114,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          output_verbose_link_cmd='echo'
           archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
           module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
           archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -16889,7 +19194,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     ;;
   hpux10*|hpux11*)
     if test $with_gnu_ld = no; then
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*)
        hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
        hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
@@ -16905,7 +19210,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
         ;;
       esac
     fi
-    case "$host_cpu" in
+    case $host_cpu in
     hppa*64*)
       hardcode_direct_CXX=no
       hardcode_shlibpath_var_CXX=no
@@ -16931,7 +19236,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        ld_shlibs_CXX=no
        ;;
       aCC*)
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
          ;;
@@ -16952,7 +19257,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       *)
        if test "$GXX" = yes; then
          if test $with_gnu_ld = no; then
-           case "$host_cpu" in
+           case $host_cpu in
            ia64*|hppa*64*)
              archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
              ;;
@@ -17048,12 +19353,12 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        ;;
       pgCC*)
         # Portland Group C++ compiler
-       archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
-       archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+       archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 
        hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
        export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
-       whole_archive_flag_spec_CXX=''
+       whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
         ;;
       cxx*)
        # Compaq C++
@@ -17285,10 +19590,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     case $cc_basename in
       CC*)
        # Sun C++ 4.2, 5.x and Centerline C++
+        archive_cmds_need_lc_CXX=yes
        no_undefined_flag_CXX=' -zdefs'
-       archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       archive_cmds_CXX='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
        archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-       $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
 
        hardcode_libdir_flag_spec_CXX='-R$libdir'
        hardcode_shlibpath_var_CXX=no
@@ -17308,15 +19614,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        esac
        link_all_deplibs_CXX=yes
 
-       # Commands to make compiler produce verbose output that lists
-       # what "hidden" libraries, object files and flags are used when
-       # linking a shared library.
-       #
-       # There doesn't appear to be a way to prevent this compiler from
-       # explicitly linking system object files so we need to strip them
-       # from the output so that they don't get included in the library
-       # dependencies.
-       output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       output_verbose_link_cmd='echo'
 
        # Archives containing C++ object files must be created using
        # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -17424,7 +19722,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   # The `*' in the case matches for architectures that use `case' in
   # $output_verbose_cmd can trigger glob expansion during the loop
   # eval without this substitution.
-  output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
 
   for p in `eval $output_verbose_link_cmd`; do
     case $p in
 
 $rm -f confest.$objext
 
+# PORTME: override above test on systems where it is broken
+case $host_os in
+solaris*)
+  case $cc_basename in
+  CC*)
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    postdeps_CXX='-lCstd -lCrun'
+    ;;
+  esac
+esac
+
+
 case " $postdeps_CXX " in
 *" -lc "*) archive_cmds_need_lc_CXX=no ;;
 esac
@@ -17555,7 +19867,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        ;;
       *)
@@ -17624,7 +19936,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
          aCC*)
            lt_prog_compiler_wl_CXX='-Wl,'
            lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
-           case "$host_cpu" in
+           case $host_cpu in
            hppa*64*|ia64*)
              # +Z the default
              ;;
@@ -17665,7 +19977,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
            # Portland Group C++ compiler.
            lt_prog_compiler_wl_CXX='-Wl,'
            lt_prog_compiler_pic_CXX='-fpic'
-           lt_prog_compiler_static_CXX='-static'
+           lt_prog_compiler_static_CXX='-Bstatic'
            ;;
          cxx*)
            # Compaq C++
@@ -17799,14 +20111,14 @@ else
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17805: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:20117: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17809: \$? = $ac_status" >&5
+   echo "$as_me:20121: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -17833,7 +20145,7 @@ else
 fi
 
 fi
-case "$host_os" in
+case $host_os in
   # For platforms which do not support PIC, -DPIC is meaningless:
   *djgpp*)
     lt_prog_compiler_pic_CXX=
@@ -17861,14 +20173,14 @@ else
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17867: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:20179: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17871: \$? = $ac_status" >&5
+   echo "$as_me:20183: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -17879,7 +20191,7 @@ else
        lt_cv_prog_compiler_c_o_CXX=yes
      fi
    fi
-   chmod u+w .
+   chmod u+w . 2>&5
    $rm conftest*
    # SGI C++ compiler will create directory out/ii_files/ for
    # template instantiation
@@ -18142,7 +20454,8 @@ cygwin* | mingw* | pw32*)
       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
       dldir=$destdir/`dirname \$dlpath`~
       test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
       dlpath=$dir/\$dldll~
        $rm \$dlpath'
@@ -18195,7 +20508,7 @@ darwin* | rhapsody*)
   soname_spec='${libname}${release}${major}$shared_ext'
   shlibpath_overrides_runpath=yes
   shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
   # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
   if test "$GCC" = yes; then
     sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
@@ -18233,7 +20546,14 @@ kfreebsd*-gnu)
 freebsd* | dragonfly*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
   version_type=freebsd-$objformat
   case $version_type in
     freebsd-elf*)
@@ -18278,7 +20598,7 @@ hpux9* | hpux10* | hpux11*)
   version_type=sunos
   need_lib_prefix=no
   need_version=no
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     shrext_cmds='.so'
     hardcode_into_libs=yes
@@ -18375,31 +20695,10 @@ linux*)
   # before this can be enabled.
   hardcode_into_libs=yes
 
-  # find out which ABI we are using
-  libsuff=
-  case "$host_cpu" in
-  x86_64*|s390x*|powerpc64*)
-    echo '#line 18382 "configure"' > conftest.$ac_ext
-    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-      case `/usr/bin/file conftest.$ac_objext` in
-      *64-bit*)
-        libsuff=64
-        sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
-        ;;
-      esac
-    fi
-    rm -rf conftest*
-    ;;
-  esac
-
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -18461,7 +20760,11 @@ nto-qnx*)
 openbsd*)
   version_type=sunos
   need_lib_prefix=no
-  need_version=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
   shlibpath_var=LD_LIBRARY_PATH
@@ -19250,7 +21553,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 19253 "configure"
+#line 21556 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19316,7 +21619,7 @@ EOF
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&5 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
@@ -19348,7 +21651,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 19351 "configure"
+#line 21654 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19414,7 +21717,7 @@ EOF
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&5 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
@@ -19970,7 +22273,7 @@ test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
 # are all built from PIC.
-case "$host_os" in
+case $host_os in
 aix3*)
   test "$enable_shared" = yes && enable_static=no
   if test -n "$RANLIB"; then
@@ -20058,7 +22361,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -20105,7 +22408,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
       lt_prog_compiler_wl_F77='-Wl,'
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -20135,12 +22438,12 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
        lt_prog_compiler_pic_F77='-KPIC'
        lt_prog_compiler_static_F77='-static'
         ;;
-      pgcc* | pgf77* | pgf90*)
+      pgcc* | pgf77* | pgf90* | pgf95*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
        # which looks to be a dead project)
        lt_prog_compiler_wl_F77='-Wl,'
        lt_prog_compiler_pic_F77='-fpic'
-       lt_prog_compiler_static_F77='-static'
+       lt_prog_compiler_static_F77='-Bstatic'
         ;;
       ccc*)
         lt_prog_compiler_wl_F77='-Wl,'
@@ -20230,14 +22533,14 @@ else
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:20236: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:22539: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:20240: \$? = $ac_status" >&5
+   echo "$as_me:22543: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -20264,7 +22567,7 @@ else
 fi
 
 fi
-case "$host_os" in
+case $host_os in
   # For platforms which do not support PIC, -DPIC is meaningless:
   *djgpp*)
     lt_prog_compiler_pic_F77=
@@ -20292,14 +22595,14 @@ else
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:20298: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:22601: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:20302: \$? = $ac_status" >&5
+   echo "$as_me:22605: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -20310,7 +22613,7 @@ else
        lt_cv_prog_compiler_c_o_F77=yes
      fi
    fi
-   chmod u+w .
+   chmod u+w . 2>&5
    $rm conftest*
    # SGI C++ compiler will create directory out/ii_files/ for
    # template instantiation
@@ -20510,11 +22813,12 @@ EOF
        tmp_addflag=
        case $cc_basename,$host_cpu in
        pgcc*)                          # Portland Group C compiler
-         whole_archive_flag_spec_F77=
+         whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
          ;;
-       pgf77* | pgf90* )                       # Portland Group f77 and f90 compilers
-         whole_archive_flag_spec_F77=
-         tmp_addflag=' -fpic -Mnomain' ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
        ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
          tmp_addflag=' -i_dynamic' ;;
        efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
@@ -20801,7 +23105,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          # Exported symbols can be pulled into shared objects from archives
          whole_archive_flag_spec_F77=' '
          archive_cmds_need_lc_F77=yes
-         # This is similar to how AIX traditionally builds it's shared libraries.
+         # This is similar to how AIX traditionally builds its shared libraries.
          archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
        fi
       fi
@@ -20841,7 +23145,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       ;;
 
     darwin* | rhapsody*)
-      case "$host_os" in
+      case $host_os in
         rhapsody* | darwin1.[012])
          allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
          ;;
@@ -20870,7 +23174,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        output_verbose_link_cmd='echo'
         archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
       module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
       archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
       module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
     else
@@ -20879,7 +23183,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          output_verbose_link_cmd='echo'
          archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
          module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
          archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -20945,7 +23249,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
     hpux10* | hpux11*)
       if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
          ;;
@@ -20954,7 +23258,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          ;;
        esac
       else
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
          ;;
@@ -20964,7 +23268,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        esac
       fi
       if test "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*)
          hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
          hardcode_libdir_flag_spec_ld_F77='+b $libdir'
@@ -21423,7 +23727,8 @@ cygwin* | mingw* | pw32*)
       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
       dldir=$destdir/`dirname \$dlpath`~
       test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
       dlpath=$dir/\$dldll~
        $rm \$dlpath'
@@ -21476,7 +23781,7 @@ darwin* | rhapsody*)
   soname_spec='${libname}${release}${major}$shared_ext'
   shlibpath_overrides_runpath=yes
   shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
   # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
   if test "$GCC" = yes; then
     sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
@@ -21514,7 +23819,14 @@ kfreebsd*-gnu)
 freebsd* | dragonfly*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
   version_type=freebsd-$objformat
   case $version_type in
     freebsd-elf*)
@@ -21559,7 +23871,7 @@ hpux9* | hpux10* | hpux11*)
   version_type=sunos
   need_lib_prefix=no
   need_version=no
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     shrext_cmds='.so'
     hardcode_into_libs=yes
@@ -21656,31 +23968,10 @@ linux*)
   # before this can be enabled.
   hardcode_into_libs=yes
 
-  # find out which ABI we are using
-  libsuff=
-  case "$host_cpu" in
-  x86_64*|s390x*|powerpc64*)
-    echo '#line 21663 "configure"' > conftest.$ac_ext
-    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-      case `/usr/bin/file conftest.$ac_objext` in
-      *64-bit*)
-        libsuff=64
-        sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
-        ;;
-      esac
-    fi
-    rm -rf conftest*
-    ;;
-  esac
-
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -21742,7 +24033,11 @@ nto-qnx*)
 openbsd*)
   version_type=sunos
   need_lib_prefix=no
-  need_version=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
   shlibpath_var=LD_LIBRARY_PATH
@@ -22434,14 +24729,14 @@ else
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:22440: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:24735: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:22444: \$? = $ac_status" >&5
+   echo "$as_me:24739: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -22524,7 +24819,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
     hpux*)
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -22571,7 +24866,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
       lt_prog_compiler_wl_GCJ='-Wl,'
       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
       # not for PA HP-UX.
-      case "$host_cpu" in
+      case $host_cpu in
       hppa*64*|ia64*)
        # +Z the default
        ;;
@@ -22601,12 +24896,12 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
        lt_prog_compiler_pic_GCJ='-KPIC'
        lt_prog_compiler_static_GCJ='-static'
         ;;
-      pgcc* | pgf77* | pgf90*)
+      pgcc* | pgf77* | pgf90* | pgf95*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
        # which looks to be a dead project)
        lt_prog_compiler_wl_GCJ='-Wl,'
        lt_prog_compiler_pic_GCJ='-fpic'
-       lt_prog_compiler_static_GCJ='-static'
+       lt_prog_compiler_static_GCJ='-Bstatic'
         ;;
       ccc*)
         lt_prog_compiler_wl_GCJ='-Wl,'
@@ -22696,14 +24991,14 @@ else
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    # The option is referenced via a variable to avoid confusing sed.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:22702: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:24997: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:22706: \$? = $ac_status" >&5
+   echo "$as_me:25001: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -22730,7 +25025,7 @@ else
 fi
 
 fi
-case "$host_os" in
+case $host_os in
   # For platforms which do not support PIC, -DPIC is meaningless:
   *djgpp*)
     lt_prog_compiler_pic_GCJ=
@@ -22758,14 +25053,14 @@ else
    # Note that $ac_compile itself does not contain backslashes and begins
    # with a dollar sign (not a hyphen), so the echo should work correctly.
    lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:22764: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:25059: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:22768: \$? = $ac_status" >&5
+   echo "$as_me:25063: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -22776,7 +25071,7 @@ else
        lt_cv_prog_compiler_c_o_GCJ=yes
      fi
    fi
-   chmod u+w .
+   chmod u+w . 2>&5
    $rm conftest*
    # SGI C++ compiler will create directory out/ii_files/ for
    # template instantiation
@@ -22976,11 +25271,12 @@ EOF
        tmp_addflag=
        case $cc_basename,$host_cpu in
        pgcc*)                          # Portland Group C compiler
-         whole_archive_flag_spec_GCJ=
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
          ;;
-       pgf77* | pgf90* )                       # Portland Group f77 and f90 compilers
-         whole_archive_flag_spec_GCJ=
-         tmp_addflag=' -fpic -Mnomain' ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
        ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
          tmp_addflag=' -i_dynamic' ;;
        efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
@@ -23287,7 +25583,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          # Exported symbols can be pulled into shared objects from archives
          whole_archive_flag_spec_GCJ=' '
          archive_cmds_need_lc_GCJ=yes
-         # This is similar to how AIX traditionally builds it's shared libraries.
+         # This is similar to how AIX traditionally builds its shared libraries.
          archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
        fi
       fi
@@ -23327,7 +25623,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       ;;
 
     darwin* | rhapsody*)
-      case "$host_os" in
+      case $host_os in
         rhapsody* | darwin1.[012])
          allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
          ;;
@@ -23356,7 +25652,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        output_verbose_link_cmd='echo'
         archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
       module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
       archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
       module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
     else
@@ -23365,7 +25661,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          output_verbose_link_cmd='echo'
          archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
          module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
-          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
          archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
           ;;
@@ -23431,7 +25727,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
     hpux10* | hpux11*)
       if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
          ;;
@@ -23440,7 +25736,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
          ;;
        esac
       else
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*|ia64*)
          archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
          ;;
@@ -23450,7 +25746,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
        esac
       fi
       if test "$with_gnu_ld" = no; then
-       case "$host_cpu" in
+       case $host_cpu in
        hppa*64*)
          hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
          hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
@@ -23909,7 +26205,8 @@ cygwin* | mingw* | pw32*)
       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
       dldir=$destdir/`dirname \$dlpath`~
       test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
       dlpath=$dir/\$dldll~
        $rm \$dlpath'
@@ -23962,7 +26259,7 @@ darwin* | rhapsody*)
   soname_spec='${libname}${release}${major}$shared_ext'
   shlibpath_overrides_runpath=yes
   shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
   # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
   if test "$GCC" = yes; then
     sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
@@ -24000,7 +26297,14 @@ kfreebsd*-gnu)
 freebsd* | dragonfly*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
   version_type=freebsd-$objformat
   case $version_type in
     freebsd-elf*)
@@ -24045,7 +26349,7 @@ hpux9* | hpux10* | hpux11*)
   version_type=sunos
   need_lib_prefix=no
   need_version=no
-  case "$host_cpu" in
+  case $host_cpu in
   ia64*)
     shrext_cmds='.so'
     hardcode_into_libs=yes
@@ -24142,31 +26446,10 @@ linux*)
   # before this can be enabled.
   hardcode_into_libs=yes
 
-  # find out which ABI we are using
-  libsuff=
-  case "$host_cpu" in
-  x86_64*|s390x*|powerpc64*)
-    echo '#line 24149 "configure"' > conftest.$ac_ext
-    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-      case `/usr/bin/file conftest.$ac_objext` in
-      *64-bit*)
-        libsuff=64
-        sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
-        ;;
-      esac
-    fi
-    rm -rf conftest*
-    ;;
-  esac
-
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -24228,7 +26511,11 @@ nto-qnx*)
 openbsd*)
   version_type=sunos
   need_lib_prefix=no
-  need_version=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
   shlibpath_var=LD_LIBRARY_PATH
@@ -25017,7 +27304,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 25020 "configure"
+#line 27307 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -25083,7 +27370,7 @@ EOF
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&5 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
@@ -25115,7 +27402,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 25118 "configure"
+#line 27405 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -25181,7 +27468,7 @@ EOF
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) 2>/dev/null
+    (./conftest; exit; ) >&5 2>/dev/null
     lt_status=$?
     case x$lt_status in
       x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
@@ -26508,167 +28795,30 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_off_t=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_type_off_t=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
-echo "${ECHO_T}$ac_cv_type_off_t" >&6
-if test $ac_cv_type_off_t = yes; then
-  :
-else
-
-cat >>confdefs.h <<_ACEOF
-#define off_t long
-_ACEOF
-
-fi
-
-echo "$as_me:$LINENO: checking for pid_t" >&5
-echo $ECHO_N "checking for pid_t... $ECHO_C" >&6
-if test "${ac_cv_type_pid_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-if ((pid_t *) 0)
-  return 0;
-if (sizeof (pid_t))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_type_pid_t=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_type_pid_t=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
-echo "${ECHO_T}$ac_cv_type_pid_t" >&6
-if test $ac_cv_type_pid_t = yes; then
-  :
-else
-
-cat >>confdefs.h <<_ACEOF
-#define pid_t int
-_ACEOF
-
-fi
-
-echo "$as_me:$LINENO: checking for size_t" >&5
-echo $ECHO_N "checking for size_t... $ECHO_C" >&6
-if test "${ac_cv_type_size_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-if ((size_t *) 0)
-  return 0;
-if (sizeof (size_t))
-  return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_type_size_t=yes
+  ac_cv_type_off_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_type_size_t=no
+ac_cv_type_off_t=no
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
-echo "${ECHO_T}$ac_cv_type_size_t" >&6
-if test $ac_cv_type_size_t = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
   :
 else
 
 cat >>confdefs.h <<_ACEOF
-#define size_t unsigned
+#define off_t long
 _ACEOF
 
 fi
 
-
-
-
-
-
-echo "$as_me:$LINENO: checking for ssize_t" >&5
-echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6
-if test "${ac_cv_type_ssize_t+set}" = set; then
+echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6
+if test "${ac_cv_type_pid_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -26681,9 +28831,9 @@ $ac_includes_default
 int
 main ()
 {
-if ((ssize_t *) 0)
+if ((pid_t *) 0)
   return 0;
-if (sizeof (ssize_t))
+if (sizeof (pid_t))
   return 0;
   ;
   return 0;
@@ -26711,31 +28861,30 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_ssize_t=yes
+  ac_cv_type_pid_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_type_ssize_t=no
+ac_cv_type_pid_t=no
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
-echo "${ECHO_T}$ac_cv_type_ssize_t" >&6
-if test $ac_cv_type_ssize_t = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6
+if test $ac_cv_type_pid_t = yes; then
   :
 else
 
 cat >>confdefs.h <<_ACEOF
-#define ssize_t int
+#define pid_t int
 _ACEOF
 
 fi
 
-
-echo "$as_me:$LINENO: checking for unsigned long long" >&5
-echo $ECHO_N "checking for unsigned long long... $ECHO_C" >&6
-if test "${ac_cv_type_unsigned_long_long+set}" = set; then
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -26748,9 +28897,9 @@ $ac_includes_default
 int
 main ()
 {
-if ((unsigned long long *) 0)
+if ((size_t *) 0)
   return 0;
-if (sizeof (unsigned long long))
+if (sizeof (size_t))
   return 0;
   ;
   return 0;
@@ -26778,31 +28927,28 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_unsigned_long_long=yes
+  ac_cv_type_size_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_type_unsigned_long_long=no
+ac_cv_type_size_t=no
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_long_long" >&5
-echo "${ECHO_T}$ac_cv_type_unsigned_long_long" >&6
-if test $ac_cv_type_unsigned_long_long = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_UNSIGNED_LONG_LONG 1
+#define size_t unsigned
 _ACEOF
 
-
 fi
 
 
-
-
-
-
 echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5
 echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6
 if test "${ac_cv_type_uid_t+set}" = set; then
@@ -27281,7 +29427,7 @@ rm -f conftest*
 fi
 echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
 echo "${ECHO_T}$ac_cv_type_socklen_t" >&6
-if test $ac_cv_type_socklen_t = no; then
+if test "x$ac_cv_type_socklen_t" = xno; then
 
 cat >>confdefs.h <<\_ACEOF
 #define socklen_t int
@@ -28368,6 +30514,7 @@ fi
 
 
 
+
 
 
 for ac_header in \
@@ -28423,6 +30570,7 @@ for ac_header in \
        sys/tape.h \
        sys/time.h \
        sys/types.h \
+       sys/uio.h \
        sys/vfs.h \
        sys/vfstab.h \
        syslog.h \
@@ -29308,8 +31456,8 @@ fi
 
 if test x"$ac_cv_header_sys_mtio_h" = x"yes" &&
    test x"$ac_cv_header_sys_scsi_impl_uscsi_h" = x"yes"; then
-       echo "$as_me:$LINENO: checking for Solaris like scsi support" >&5
-echo $ECHO_N "checking for Solaris like scsi support... $ECHO_C" >&6
+       echo "$as_me:$LINENO: checking for Solaris-like scsi support" >&5
+echo $ECHO_N "checking for Solaris-like scsi support... $ECHO_C" >&6
 if test "${amanda_cv_solaris_scsi+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -29596,6 +31744,7 @@ fi
        fi
 fi
 
+
 if test x"$ac_cv_header_sys_mtio_h" = x"yes" &&
    test x"$ac_cv_header_sys_scsiio_h" = x"yes"; then
     echo "$as_me:$LINENO: checking for BSD like scsi support" >&5
                        ;;
     *)
 
+echo "$as_me:$LINENO: checking for main in -lresolv" >&5
+echo $ECHO_N "checking for main in -lresolv... $ECHO_C" >&6
+if test "${ac_cv_lib_resolv_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_resolv_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_resolv_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_main" >&5
+echo "${ECHO_T}$ac_cv_lib_resolv_main" >&6
+if test $ac_cv_lib_resolv_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRESOLV 1
+_ACEOF
+
+  LIBS="-lresolv $LIBS"
+
+fi
+
+
 echo "$as_me:$LINENO: checking for main in -lnsl" >&5
 echo $ECHO_N "checking for main in -lnsl... $ECHO_C" >&6
 if test "${ac_cv_lib_nsl_main+set}" = set; then
@@ -30171,7 +32388,7 @@ _ACEOF
 
 fi
 
-if test "$ac_cv_lib_termcap_tgetent" != yes; then
+if test "x$ac_cv_lib_termcap_tgetent" != xyes; then
 
 echo "$as_me:$LINENO: checking for tgetent in -lcurses" >&5
 echo $ECHO_N "checking for tgetent in -lcurses... $ECHO_C" >&6
@@ -30246,7 +32463,7 @@ _ACEOF
 
 fi
 
-    if test "$ac_cv_lib_curses_tgetent" != yes; then
+    if test "x$ac_cv_lib_curses_tgetent" != xyes; then
 
 echo "$as_me:$LINENO: checking for tgetent in -lncurses" >&5
 echo $ECHO_N "checking for tgetent in -lncurses... $ECHO_C" >&6
 
     fi
 fi
-if test "$ac_cv_lib_termcap_tgetent" = yes ||
-   test "$ac_cv_lib_curses_tgetent" = yes ||
-   test "$ac_cv_lib_ncurses_tgetent" = yes; then
-
-echo "$as_me:$LINENO: checking for readline in -lreadline" >&5
+if test "x$ac_cv_lib_termcap_tgetent" = xyes ||
+   test "x$ac_cv_lib_curses_tgetent" = xyes ||
+   test "x$ac_cv_lib_ncurses_tgetent" = xyes; then
+    echo "$as_me:$LINENO: checking for readline in -lreadline" >&5
 echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6
 if test "${ac_cv_lib_readline_readline+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5
 echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6
 if test $ac_cv_lib_readline_readline = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBREADLINE 1
-_ACEOF
-
-  LIBS="-lreadline $LIBS"
+  READLINE_LIBS="-lreadline";
 
 fi
 
-    if test "$ac_cv_lib_readline_readline" != yes; then
+    if test "x$ac_cv_lib_readline_readline" != xyes; then
        { echo "$as_me:$LINENO: WARNING: *** No readline library, no history and command line editing in amrecover!" >&5
 echo "$as_me: WARNING: *** No readline library, no history and command line editing in amrecover!" >&2;}
     fi
@@ -30409,14 +32621,8 @@ else
 echo "$as_me: WARNING: *** No terminal library, no history and command line editing in amrecover!" >&2;}
 fi
 
-if test "$ac_cv_lib_readline_readline" = yes; then
-    READLINE_LIBS=-lreadline
-    LIBS=`echo $LIBS | sed s/-lreadline//`
-
-fi
-
-if test "$ac_cv_header_linux_zftape_h" = yes; then
-    if test "$ac_cv_header_vtblc_h" = yes; then
+if test "x$ac_cv_header_linux_zftape_h" = xyes; then
+    if test "x$ac_cv_header_vtblc_h" = xyes; then
 
 echo "$as_me:$LINENO: checking for main in -lvtblc" >&5
 echo $ECHO_N "checking for main in -lvtblc... $ECHO_C" >&6
@@ -30485,7 +32691,7 @@ _ACEOF
 
 fi
 
-        if test "$ac_cv_lib_vtblc_main" != yes; then
+        if test "x$ac_cv_lib_vtblc_main" != xyes; then
             { echo "$as_me:$LINENO: WARNING: *** vtblc library not found - no QIC volume table support!" >&5
 echo "$as_me: WARNING: *** vtblc library not found - no QIC volume table support!" >&2;}
         fi
@@ -30974,7 +33180,7 @@ LIBS="$save_LIBS"
 
 case "$DB_STYLE" in
     db)
-       if test "$ac_cv_header_db_h" = yes; then
+       if test "x$ac_cv_header_db_h" = xyes; then
 
 echo "$as_me:$LINENO: checking for main in -ldb" >&5
 echo $ECHO_N "checking for main in -ldb... $ECHO_C" >&6
@@ -31043,7 +33249,7 @@ _ACEOF
 
 fi
 
-           if test "$ac_cv_lib_db_main" = yes; then
+           if test "x$ac_cv_lib_db_main" = xyes; then
 
 echo "$as_me:$LINENO: checking for dbm_open in -ldb" >&5
 echo $ECHO_N "checking for dbm_open in -ldb... $ECHO_C" >&6
@@ -31118,7 +33324,7 @@ _ACEOF
 
 fi
 
-               if test "$ac_cv_lib_db_dbm_open" = yes; then
+               if test "x$ac_cv_lib_db_dbm_open" = xyes; then
                    DB_HEADER=db.h
                    DB_LIB=db
                else
@@ -31127,7 +33333,7 @@ fi
 echo "$as_me: WARNING: *** db database library requested but dbm_open not found in -ldb." >&2;}
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=db.h
                    DB_LIB=c
                else
@@ -31144,7 +33350,7 @@ echo "$as_me: WARNING: *** db database library requested but db.h not found." >&
        ;;
 
     dbm)
-       if test "$ac_cv_header_dbm_h" = yes; then
+       if test "x$ac_cv_header_dbm_h" = xyes; then
 
 echo "$as_me:$LINENO: checking for main in -ldbm" >&5
 echo $ECHO_N "checking for main in -ldbm... $ECHO_C" >&6
@@ -31213,7 +33419,7 @@ _ACEOF
 
 fi
 
-           if test "$ac_cv_lib_dbm_main" = yes; then
+           if test "x$ac_cv_lib_dbm_main" = xyes; then
 
 echo "$as_me:$LINENO: checking for dbm_open in -ldbm" >&5
 echo $ECHO_N "checking for dbm_open in -ldbm... $ECHO_C" >&6
@@ -31288,7 +33494,7 @@ _ACEOF
 
 fi
 
-               if test "$ac_cv_lib_dbm_dbm_open" = yes; then
+               if test "x$ac_cv_lib_dbm_dbm_open" = xyes; then
                    DB_HEADER=dbm.h
                    DB_LIB=dbm
                else
@@ -31297,7 +33503,7 @@ fi
 echo "$as_me: WARNING: *** dbm database library requested but dbm_open not found in -ldbm." >&2;}
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=dbm.h
                    DB_LIB=c
                else
@@ -31314,7 +33520,7 @@ echo "$as_me: WARNING: *** dbm database library requested but dbm.h not found."
        ;;
 
     gdbm)
-       if test "$ac_cv_header_ndbm_h" = yes; then
+       if test "x$ac_cv_header_ndbm_h" = xyes; then
 
 echo "$as_me:$LINENO: checking for main in -lgdbm" >&5
 echo $ECHO_N "checking for main in -lgdbm... $ECHO_C" >&6
@@ -31383,7 +33589,7 @@ _ACEOF
 
 fi
 
-           if test "$ac_cv_lib_gdbm_main" = yes; then
+           if test "x$ac_cv_lib_gdbm_main" = xyes; then
 
 echo "$as_me:$LINENO: checking for dbm_open in -lgdbm" >&5
 echo $ECHO_N "checking for dbm_open in -lgdbm... $ECHO_C" >&6
@@ -31458,7 +33664,7 @@ _ACEOF
 
 fi
 
-               if test "$ac_cv_lib_gdbm_dbm_open" = yes; then
+               if test "x$ac_cv_lib_gdbm_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=gdbm
                else
@@ -31467,7 +33673,7 @@ fi
 echo "$as_me: WARNING: *** gdbm database library requested but -lgdbm not found." >&2;}
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=c
                else
@@ -31484,7 +33690,7 @@ echo "$as_me: WARNING: *** gdbm database library requested but ndbm.h not found.
        ;;
 
     ndbm)
-       if test "$ac_cv_header_ndbm_h" = yes; then
+       if test "x$ac_cv_header_ndbm_h" = xyes; then
 
 echo "$as_me:$LINENO: checking for main in -lndbm" >&5
 echo $ECHO_N "checking for main in -lndbm... $ECHO_C" >&6
@@ -31553,7 +33759,7 @@ _ACEOF
 
 fi
 
-           if test "$ac_cv_lib_ndbm_main" = yes; then
+           if test "x$ac_cv_lib_ndbm_main" = xyes; then
 
 echo "$as_me:$LINENO: checking for dbm_open in -lndbm" >&5
 echo $ECHO_N "checking for dbm_open in -lndbm... $ECHO_C" >&6
@@ -31628,7 +33834,7 @@ _ACEOF
 
 fi
 
-               if test "$ac_cv_lib_ndbm_dbm_open" = yes; then
+               if test "x$ac_cv_lib_ndbm_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=ndbm
                else
@@ -31637,7 +33843,7 @@ fi
 echo "$as_me: WARNING: *** ndbm database library requested but -lndbm not found." >&2;}
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=c
                else
@@ -31666,7 +33872,7 @@ if test -z "$DB_STYLE"; then
 fi
 
 
-if test "$DB_STYLE" = text; then
+if test "x$DB_STYLE" = xtext; then
 
 cat >>confdefs.h <<\_ACEOF
 #define TEXTDB 1
@@ -31770,7 +33976,7 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_struct_datum" >&5
 echo "${ECHO_T}$amanda_cv_struct_datum" >&6
-    if test "$amanda_cv_struct_datum" = yes; then
+    if test "x$amanda_cv_struct_datum" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_STRUCT_DATUM 1
@@ -31817,7 +34023,7 @@ rm -f conftest*
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_have__posix2_re_dup_max" >&5
 echo "${ECHO_T}$amanda_cv_have__posix2_re_dup_max" >&6
-if test "$amanda_cv_have__posix2_re_dup_max" = yes; then
+if test "x$amanda_cv_have__posix2_re_dup_max" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE__POSIX2_RE_DUP_MAX 1
@@ -31854,7 +34060,7 @@ rm -f conftest*
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_have_char_min" >&5
 echo "${ECHO_T}$amanda_cv_have_char_min" >&6
-if test "$amanda_cv_have_char_min" = yes; then
+if test "x$amanda_cv_have_char_min" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_CHAR_MIN 1
@@ -31891,7 +34097,7 @@ rm -f conftest*
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_have_char_max" >&5
 echo "${ECHO_T}$amanda_cv_have_char_max" >&6
-if test "$amanda_cv_have_char_max" = yes; then
+if test "x$amanda_cv_have_char_max" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_CHAR_MAX 1
@@ -31928,7 +34134,7 @@ rm -f conftest*
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_have_char_bit" >&5
 echo "${ECHO_T}$amanda_cv_have_char_bit" >&6
-if test "$amanda_cv_have_char_bit" = yes; then
+if test "x$amanda_cv_have_char_bit" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_CHAR_BIT 1
 done
 
 
+ice_have_mkstemp=no
+
+for ac_func in mkstemp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ ice_have_mkstemp=yes
+fi
+done
+
+if test "${ice_have_mkstemp}" = yes; then
+echo "$as_me:$LINENO: checking for mkstemp declaration in stdlib.h" >&5
+echo $ECHO_N "checking for mkstemp declaration in stdlib.h... $ECHO_C" >&6
+if test "${ice_cv_have_mkstemp_decl+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ice_cv_have_mkstemp_decl=no
+ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
+ice_re_word='(^|[^a-zA-Z0-9_])'
+for header in stdlib.h; do
+# Check for ordinary declaration
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$header>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "${ice_re_word}mkstemp[       ]*\(" >/dev/null 2>&1; then
+  ice_cv_have_mkstemp_decl=yes
+fi
+rm -f conftest*
+
+if test "$ice_cv_have_mkstemp_decl" = yes; then
+       break
+fi
+# Check for "fixed" declaration like "getpid _PARAMS((int))"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$header>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "${ice_re_word}mkstemp[       ]*$ice_re_params\(\(" >/dev/null 2>&1; then
+  ice_cv_have_mkstemp_decl=yes
+fi
+rm -f conftest*
+
+if test "$ice_cv_have_mkstemp_decl" = yes; then
+       break
+fi
+done
+
+fi
+
+echo "$as_me:$LINENO: result: $ice_cv_have_mkstemp_decl" >&5
+echo "${ECHO_T}$ice_cv_have_mkstemp_decl" >&6
+if test "$ice_cv_have_mkstemp_decl" = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_MKSTEMP_DECL 1
+_ACEOF
+
+fi
+fi
+
+
 ice_have_mktemp=no
 
 for ac_func in mktemp
 done
 
 
+for ac_func in shquote
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
 ice_have_setresgid=no
 
 for ac_func in setresgid
@@ -43866,246 +46343,78 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
 
-
-       echo "$as_me:$LINENO: checking for shmdt() argument type" >&5
-echo $ECHO_N "checking for shmdt() argument type... $ECHO_C" >&6
-if test "${amanda_cv_shmdt_arg_type+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
-               if test "$ac_cv_func_shmget" = yes; then
-                   cat <<EOF >conftest.$ac_ext
-#include "confdefs.h"
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_IPC_H
-# include <sys/ipc.h>
-#endif
-#ifdef HAVE_SYS_SHM_H
-# include <sys/shm.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" void *shmat(int, void *, int);
-#else
-void *shmat();
-#endif
-
-int main()
-{
-    int i;
-    return 0;
-}
-EOF
-                   ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext >/dev/null 2>/dev/null
-                   if test $? = 0; then
-                       amanda_cv_shmdt_arg_type=void
-                   else
-                       amanda_cv_shmdt_arg_type=char
-                   fi
-                   rm -f conftest*
-               else
-                   amanda_cv_shmdt_arg_type=nothing
-               fi
-
-
-fi
-echo "$as_me:$LINENO: result: $amanda_cv_shmdt_arg_type" >&5
-echo "${ECHO_T}$amanda_cv_shmdt_arg_type" >&6
-
-cat >>confdefs.h <<_ACEOF
-#define SHM_ARG_TYPE $amanda_cv_shmdt_arg_type
-_ACEOF
-
-
-
-       case "$FORCE_MMAP" in
-       n | no)
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYSVSHM 1
-_ACEOF
-
-         ;;
-       esac
-
-
-fi
-done
-
-
-ice_have_shmat=no
-
-for ac_func in shmat
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error.  */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
-   builtin and then its argument prototype would still apply.  */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  eval "$as_ac_var=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
- ice_have_shmat=yes
-fi
-done
-
-if test "${ice_have_shmat}" = yes; then
-echo "$as_me:$LINENO: checking for shmat declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
-echo $ECHO_N "checking for shmat declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
-if test "${ice_cv_have_shmat_decl+set}" = set; then
+
+       echo "$as_me:$LINENO: checking for shmdt() argument type" >&5
+echo $ECHO_N "checking for shmdt() argument type... $ECHO_C" >&6
+if test "${amanda_cv_shmdt_arg_type+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
-ice_cv_have_shmat_decl=no
-ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
-ice_re_word='(^|[^a-zA-Z0-9_])'
-for header in sys/types.h sys/ipc.h sys/shm.h; do
-# Check for ordinary declaration
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$header>
+               if test "$ac_cv_func_shmget" = yes; then
+                   cat <<EOF >conftest.$ac_ext
+#include "confdefs.h"
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_IPC_H
+# include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_SHM_H
+# include <sys/shm.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" void *shmat(int, void *, int);
+#else
+void *shmat();
+#endif
+
+int main()
+{
+    int i;
+    return 0;
+}
+EOF
+                   ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext >/dev/null 2>/dev/null
+                   if test $? = 0; then
+                       amanda_cv_shmdt_arg_type=void
+                   else
+                       amanda_cv_shmdt_arg_type=char
+                   fi
+                   rm -f conftest*
+               else
+                   amanda_cv_shmdt_arg_type=nothing
+               fi
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmat[         ]*\(" >/dev/null 2>&1; then
-  ice_cv_have_shmat_decl=yes
-fi
-rm -f conftest*
 
-if test "$ice_cv_have_shmat_decl" = yes; then
-       break
 fi
-# Check for "fixed" declaration like "getpid _PARAMS((int))"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$header>
+echo "$as_me:$LINENO: result: $amanda_cv_shmdt_arg_type" >&5
+echo "${ECHO_T}$amanda_cv_shmdt_arg_type" >&6
 
+cat >>confdefs.h <<_ACEOF
+#define SHM_ARG_TYPE $amanda_cv_shmdt_arg_type
 _ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmat[         ]*$ice_re_params\(\(" >/dev/null 2>&1; then
-  ice_cv_have_shmat_decl=yes
-fi
-rm -f conftest*
 
-if test "$ice_cv_have_shmat_decl" = yes; then
-       break
-fi
-done
 
-fi
 
-echo "$as_me:$LINENO: result: $ice_cv_have_shmat_decl" >&5
-echo "${ECHO_T}$ice_cv_have_shmat_decl" >&6
-if test "$ice_cv_have_shmat_decl" = yes; then
+       case "$FORCE_MMAP" in
+       n | no)
 
-cat >>confdefs.h <<_ACEOF
-#define HAVE_SHMAT_DECL 1
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYSVSHM 1
 _ACEOF
 
+         ;;
+       esac
+
+
 fi
-fi
+done
 
 
-ice_have_shmctl=no
+ice_have_shmat=no
 
-for ac_func in shmctl
+for ac_func in shmat
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -44202,18 +46511,18 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
- ice_have_shmctl=yes
+ ice_have_shmat=yes
 fi
 done
 
-if test "${ice_have_shmctl}" = yes; then
-echo "$as_me:$LINENO: checking for shmctl declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
-echo $ECHO_N "checking for shmctl declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
-if test "${ice_cv_have_shmctl_decl+set}" = set; then
+if test "${ice_have_shmat}" = yes; then
+echo "$as_me:$LINENO: checking for shmat declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
+echo $ECHO_N "checking for shmat declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
+if test "${ice_cv_have_shmat_decl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
-ice_cv_have_shmctl_decl=no
+ice_cv_have_shmat_decl=no
 ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
 ice_re_word='(^|[^a-zA-Z0-9_])'
 for header in sys/types.h sys/ipc.h sys/shm.h; do
@@ -44228,12 +46537,12 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmctl[        ]*\(" >/dev/null 2>&1; then
-  ice_cv_have_shmctl_decl=yes
+  $EGREP "${ice_re_word}shmat[         ]*\(" >/dev/null 2>&1; then
+  ice_cv_have_shmat_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shmctl_decl" = yes; then
+if test "$ice_cv_have_shmat_decl" = yes; then
        break
 fi
 # Check for "fixed" declaration like "getpid _PARAMS((int))"
@@ -44247,33 +46556,33 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmctl[        ]*$ice_re_params\(\(" >/dev/null 2>&1; then
-  ice_cv_have_shmctl_decl=yes
+  $EGREP "${ice_re_word}shmat[         ]*$ice_re_params\(\(" >/dev/null 2>&1; then
+  ice_cv_have_shmat_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shmctl_decl" = yes; then
+if test "$ice_cv_have_shmat_decl" = yes; then
        break
 fi
 done
 
 fi
 
-echo "$as_me:$LINENO: result: $ice_cv_have_shmctl_decl" >&5
-echo "${ECHO_T}$ice_cv_have_shmctl_decl" >&6
-if test "$ice_cv_have_shmctl_decl" = yes; then
+echo "$as_me:$LINENO: result: $ice_cv_have_shmat_decl" >&5
+echo "${ECHO_T}$ice_cv_have_shmat_decl" >&6
+if test "$ice_cv_have_shmat_decl" = yes; then
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_SHMCTL_DECL 1
+#define HAVE_SHMAT_DECL 1
 _ACEOF
 
 fi
 fi
 
 
-ice_have_shmdt=no
+ice_have_shmctl=no
 
-for ac_func in shmdt
+for ac_func in shmctl
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -44370,18 +46679,18 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
- ice_have_shmdt=yes
+ ice_have_shmctl=yes
 fi
 done
 
-if test "${ice_have_shmdt}" = yes; then
-echo "$as_me:$LINENO: checking for shmdt declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
-echo $ECHO_N "checking for shmdt declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
-if test "${ice_cv_have_shmdt_decl+set}" = set; then
+if test "${ice_have_shmctl}" = yes; then
+echo "$as_me:$LINENO: checking for shmctl declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
+echo $ECHO_N "checking for shmctl declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
+if test "${ice_cv_have_shmctl_decl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
-ice_cv_have_shmdt_decl=no
+ice_cv_have_shmctl_decl=no
 ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
 ice_re_word='(^|[^a-zA-Z0-9_])'
 for header in sys/types.h sys/ipc.h sys/shm.h; do
@@ -44396,12 +46705,12 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmdt[         ]*\(" >/dev/null 2>&1; then
-  ice_cv_have_shmdt_decl=yes
+  $EGREP "${ice_re_word}shmctl[        ]*\(" >/dev/null 2>&1; then
+  ice_cv_have_shmctl_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shmdt_decl" = yes; then
+if test "$ice_cv_have_shmctl_decl" = yes; then
        break
 fi
 # Check for "fixed" declaration like "getpid _PARAMS((int))"
@@ -44415,33 +46724,33 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmdt[         ]*$ice_re_params\(\(" >/dev/null 2>&1; then
-  ice_cv_have_shmdt_decl=yes
+  $EGREP "${ice_re_word}shmctl[        ]*$ice_re_params\(\(" >/dev/null 2>&1; then
+  ice_cv_have_shmctl_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shmdt_decl" = yes; then
+if test "$ice_cv_have_shmctl_decl" = yes; then
        break
 fi
 done
 
 fi
 
-echo "$as_me:$LINENO: result: $ice_cv_have_shmdt_decl" >&5
-echo "${ECHO_T}$ice_cv_have_shmdt_decl" >&6
-if test "$ice_cv_have_shmdt_decl" = yes; then
+echo "$as_me:$LINENO: result: $ice_cv_have_shmctl_decl" >&5
+echo "${ECHO_T}$ice_cv_have_shmctl_decl" >&6
+if test "$ice_cv_have_shmctl_decl" = yes; then
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_SHMDT_DECL 1
+#define HAVE_SHMCTL_DECL 1
 _ACEOF
 
 fi
 fi
 
 
-ice_have_shmget=no
+ice_have_shmdt=no
 
-for ac_func in shmget
+for ac_func in shmdt
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -44538,18 +46847,18 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
- ice_have_shmget=yes
+ ice_have_shmdt=yes
 fi
 done
 
-if test "${ice_have_shmget}" = yes; then
-echo "$as_me:$LINENO: checking for shmget declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
-echo $ECHO_N "checking for shmget declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
-if test "${ice_cv_have_shmget_decl+set}" = set; then
+if test "${ice_have_shmdt}" = yes; then
+echo "$as_me:$LINENO: checking for shmdt declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
+echo $ECHO_N "checking for shmdt declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
+if test "${ice_cv_have_shmdt_decl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
-ice_cv_have_shmget_decl=no
+ice_cv_have_shmdt_decl=no
 ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
 ice_re_word='(^|[^a-zA-Z0-9_])'
 for header in sys/types.h sys/ipc.h sys/shm.h; do
@@ -44564,12 +46873,12 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmget[        ]*\(" >/dev/null 2>&1; then
-  ice_cv_have_shmget_decl=yes
+  $EGREP "${ice_re_word}shmdt[         ]*\(" >/dev/null 2>&1; then
+  ice_cv_have_shmdt_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shmget_decl" = yes; then
+if test "$ice_cv_have_shmdt_decl" = yes; then
        break
 fi
 # Check for "fixed" declaration like "getpid _PARAMS((int))"
@@ -44583,55 +46892,33 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shmget[        ]*$ice_re_params\(\(" >/dev/null 2>&1; then
-  ice_cv_have_shmget_decl=yes
+  $EGREP "${ice_re_word}shmdt[         ]*$ice_re_params\(\(" >/dev/null 2>&1; then
+  ice_cv_have_shmdt_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shmget_decl" = yes; then
+if test "$ice_cv_have_shmdt_decl" = yes; then
        break
 fi
 done
 
 fi
 
-echo "$as_me:$LINENO: result: $ice_cv_have_shmget_decl" >&5
-echo "${ECHO_T}$ice_cv_have_shmget_decl" >&6
-if test "$ice_cv_have_shmget_decl" = yes; then
+echo "$as_me:$LINENO: result: $ice_cv_have_shmdt_decl" >&5
+echo "${ECHO_T}$ice_cv_have_shmdt_decl" >&6
+if test "$ice_cv_have_shmdt_decl" = yes; then
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_SHMGET_DECL 1
+#define HAVE_SHMDT_DECL 1
 _ACEOF
 
 fi
 fi
 
 
-if test "$ac_cv_func_mmap_fixed_mapped" != yes; then
-    case "$FORCE_MMAP" in
-    n | no)
-       if test "$ac_cv_func_shmget" != yes; then
-           { echo "$as_me:$LINENO: WARNING: *** Neither shmget() nor mmap() found!" >&5
-echo "$as_me: WARNING: *** Neither shmget() nor mmap() found!" >&2;}
-           { echo "$as_me:$LINENO: WARNING: *** This system will not support the Amanda server." >&5
-echo "$as_me: WARNING: *** This system will not support the Amanda server." >&2;}
-           NO_SERVER_MODE=true
-       fi
-      ;;
-    y | ye | yes)
-       { echo "$as_me:$LINENO: WARNING: *** --with-mmap used on a system with no mmap() support!" >&5
-echo "$as_me: WARNING: *** --with-mmap used on a system with no mmap() support!" >&2;}
-       { echo "$as_me:$LINENO: WARNING: *** This system will not support the Amanda server." >&5
-echo "$as_me: WARNING: *** This system will not support the Amanda server." >&2;}
-       NO_SERVER_MODE=true
-      ;;
-    esac
-fi
-
-
-ice_have_shquote=no
+ice_have_shmget=no
 
-for ac_func in shquote
+for ac_func in shmget
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -44728,21 +47015,21 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
- ice_have_shquote=yes
+ ice_have_shmget=yes
 fi
 done
 
-if test "${ice_have_shquote}" = yes; then
-echo "$as_me:$LINENO: checking for shquote declaration in stdlib.h" >&5
-echo $ECHO_N "checking for shquote declaration in stdlib.h... $ECHO_C" >&6
-if test "${ice_cv_have_shquote_decl+set}" = set; then
+if test "${ice_have_shmget}" = yes; then
+echo "$as_me:$LINENO: checking for shmget declaration in sys/types.h sys/ipc.h sys/shm.h" >&5
+echo $ECHO_N "checking for shmget declaration in sys/types.h sys/ipc.h sys/shm.h... $ECHO_C" >&6
+if test "${ice_cv_have_shmget_decl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
-ice_cv_have_shquote_decl=no
+ice_cv_have_shmget_decl=no
 ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
 ice_re_word='(^|[^a-zA-Z0-9_])'
-for header in stdlib.h; do
+for header in sys/types.h sys/ipc.h sys/shm.h; do
 # Check for ordinary declaration
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -44754,12 +47041,12 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shquote[       ]*\(" >/dev/null 2>&1; then
-  ice_cv_have_shquote_decl=yes
+  $EGREP "${ice_re_word}shmget[        ]*\(" >/dev/null 2>&1; then
+  ice_cv_have_shmget_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shquote_decl" = yes; then
+if test "$ice_cv_have_shmget_decl" = yes; then
        break
 fi
 # Check for "fixed" declaration like "getpid _PARAMS((int))"
@@ -44773,30 +47060,51 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "${ice_re_word}shquote[       ]*$ice_re_params\(\(" >/dev/null 2>&1; then
-  ice_cv_have_shquote_decl=yes
+  $EGREP "${ice_re_word}shmget[        ]*$ice_re_params\(\(" >/dev/null 2>&1; then
+  ice_cv_have_shmget_decl=yes
 fi
 rm -f conftest*
 
-if test "$ice_cv_have_shquote_decl" = yes; then
+if test "$ice_cv_have_shmget_decl" = yes; then
        break
 fi
 done
 
 fi
 
-echo "$as_me:$LINENO: result: $ice_cv_have_shquote_decl" >&5
-echo "${ECHO_T}$ice_cv_have_shquote_decl" >&6
-if test "$ice_cv_have_shquote_decl" = yes; then
+echo "$as_me:$LINENO: result: $ice_cv_have_shmget_decl" >&5
+echo "${ECHO_T}$ice_cv_have_shmget_decl" >&6
+if test "$ice_cv_have_shmget_decl" = yes; then
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_SHQUOTE_DECL 1
+#define HAVE_SHMGET_DECL 1
 _ACEOF
 
 fi
 fi
 
 
+if test "x$ac_cv_func_mmap_fixed_mapped" != xyes; then
+    case "$FORCE_MMAP" in
+    n | no)
+       if test "x$ac_cv_func_shmget" != xyes; then
+           { echo "$as_me:$LINENO: WARNING: *** Neither shmget() nor mmap() found!" >&5
+echo "$as_me: WARNING: *** Neither shmget() nor mmap() found!" >&2;}
+           { echo "$as_me:$LINENO: WARNING: *** This system will not support the Amanda server." >&5
+echo "$as_me: WARNING: *** This system will not support the Amanda server." >&2;}
+           NO_SERVER_MODE=true
+       fi
+      ;;
+    y | ye | yes)
+       { echo "$as_me:$LINENO: WARNING: *** --with-mmap used on a system with no mmap() support!" >&5
+echo "$as_me: WARNING: *** --with-mmap used on a system with no mmap() support!" >&2;}
+       { echo "$as_me:$LINENO: WARNING: *** This system will not support the Amanda server." >&5
+echo "$as_me: WARNING: *** This system will not support the Amanda server." >&2;}
+       NO_SERVER_MODE=true
+      ;;
+    esac
+fi
+
 
 ice_have_snprintf=no
 
@@ -49015,6 +51323,286 @@ done
 
 
 
+for ac_func in writev
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
+ice_have_writev=no
+
+for ac_func in writev
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ ice_have_writev=yes
+fi
+done
+
+if test "${ice_have_writev}" = yes; then
+echo "$as_me:$LINENO: checking for writev declaration in unistd.h sys/uio.h" >&5
+echo $ECHO_N "checking for writev declaration in unistd.h sys/uio.h... $ECHO_C" >&6
+if test "${ice_cv_have_writev_decl+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ice_cv_have_writev_decl=no
+ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*'
+ice_re_word='(^|[^a-zA-Z0-9_])'
+for header in unistd.h sys/uio.h; do
+# Check for ordinary declaration
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$header>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "${ice_re_word}writev[        ]*\(" >/dev/null 2>&1; then
+  ice_cv_have_writev_decl=yes
+fi
+rm -f conftest*
+
+if test "$ice_cv_have_writev_decl" = yes; then
+       break
+fi
+# Check for "fixed" declaration like "getpid _PARAMS((int))"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$header>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "${ice_re_word}writev[        ]*$ice_re_params\(\(" >/dev/null 2>&1; then
+  ice_cv_have_writev_decl=yes
+fi
+rm -f conftest*
+
+if test "$ice_cv_have_writev_decl" = yes; then
+       break
+fi
+done
+
+fi
+
+echo "$as_me:$LINENO: result: $ice_cv_have_writev_decl" >&5
+echo "${ECHO_T}$ice_cv_have_writev_decl" >&6
+if test "$ice_cv_have_writev_decl" = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_WRITEV_DECL 1
+_ACEOF
+
+fi
+fi
+
+
 for ac_func in strcasecmp
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 done
 
 
-if test "$ac_cv_func_fnmatch" != yes -a "$USE_QUICK_AND_DIRTY_ESTIMATES" != yes ; then
-    { echo "$as_me:$LINENO: WARNING: --with-qde and no fnmatch -- gnutar exclude files will not work" >&5
-echo "$as_me: WARNING: --with-qde and no fnmatch -- gnutar exclude files will not work" >&2;}
+# Check whether --enable-largefile or --disable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+  enableval="$enable_largefile"
+
+fi;
+if test "$enable_largefile" != no; then
+
+  echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_largefile_CC=' -n32'; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_file_offset_bits=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_file_offset_bits=64; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
 fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6
+if test "$ac_cv_sys_file_offset_bits" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+
+fi
+rm -f conftest*
+  echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_large_files+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_large_files=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_large_files=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6
+if test "$ac_cv_sys_large_files" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+
+fi
+rm -f conftest*
+fi
+
 
 echo "$as_me:$LINENO: checking disk device prefixes" >&5
 echo $ECHO_N "checking disk device prefixes... $ECHO_C" >&6
@@ -49409,7 +52357,7 @@ dfline=`(
     df / | while read line; do
        set -- $line
        while test $# -gt 0; do
-           if test "$1" = "/"; then
+           if test "x$1" = "x/"; then
                echo $line
                break 2
            fi
@@ -49548,7 +52496,7 @@ fi
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_posix_filelocking" >&5
 echo "${ECHO_T}$amanda_cv_posix_filelocking" >&6
-if test "$amanda_cv_posix_filelocking" = yes; then
+if test "x$amanda_cv_posix_filelocking" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define USE_POSIX_FCNTL 1
@@ -49613,7 +52561,7 @@ fi
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_flock_filelocking" >&5
 echo "${ECHO_T}$amanda_cv_flock_filelocking" >&6
-    if test "$amanda_cv_flock_filelocking" = yes; then
+    if test "x$amanda_cv_flock_filelocking" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define USE_FLOCK 1
@@ -49679,7 +52627,7 @@ fi
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_lockf_filelocking" >&5
 echo "${ECHO_T}$amanda_cv_lockf_filelocking" >&6
-    if test "$amanda_cv_lockf_filelocking" = yes; then
+    if test "x$amanda_cv_lockf_filelocking" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define USE_LOCKF 1
@@ -49748,7 +52696,7 @@ fi
 fi
 echo "$as_me:$LINENO: result: $amanda_cv_lnlock_filelocking" >&5
 echo "${ECHO_T}$amanda_cv_lnlock_filelocking" >&6
-    if test "$amanda_cv_lnlock_filelocking" = yes; then
+    if test "x$amanda_cv_lnlock_filelocking" = xyes; then
 
 cat >>confdefs.h <<\_ACEOF
 #define USE_LNLOCK 1
@@ -49882,6 +52830,16 @@ else
 fi
 
 
+
+if test x"$SSH_SECURITY_SET" = x"true"; then
+  WANT_SSH_SECURITY_TRUE=
+  WANT_SSH_SECURITY_FALSE='#'
+else
+  WANT_SSH_SECURITY_TRUE='#'
+  WANT_SSH_SECURITY_FALSE=
+fi
+
+
 case "${FORCE_USE_RUNDUMP-${USE_RUNDUMP}}" in
 y |  ye | yes)
 cat >>confdefs.h <<\_ACEOF
@@ -49901,7 +52859,98 @@ LTLIBOBJS=`echo "$LIBOBJS" |
 LTALLOCA=`echo "$ALLOCA" | sed 's/\.'"${ac_objext}"'/\.lo/g'`
 
 
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ac_config_files="$ac_config_files amplot/amcat.awk amplot/amplot.sh amplot/Makefile changer-src/chg-manual.sh changer-src/chg-multi.sh changer-src/chg-mtx.sh changer-src/chg-chs.sh changer-src/chg-rth.pl changer-src/chg-chio.pl changer-src/chg-zd-mtx.sh changer-src/Makefile changer-src/chg-juke.sh changer-src/chg-rait.sh changer-src/chg-null.sh changer-src/chg-mcutil.sh changer-src/chg-disk.sh changer-src/chg-iomega.pl client-src/patch-system.sh client-src/Makefile common-src/versuff.c common-src/Makefile example/amanda.conf example/Makefile example/amanda.conf.chg-scsi example/chg-scsi-linux.conf example/chg-scsi-solaris.conf example/chg-scsi-hpux.conf example/chg-mcutil.conf man/Makefile docs/Makefile recover-src/Makefile restore-src/Makefile server-src/amcheckdb.sh server-src/amcleanup.sh server-src/amdump.sh server-src/amfreetapes.sh server-src/amoverview.pl server-src/amrmtape.sh server-src/amtoc.pl server-src/amverify.sh server-src/Makefile server-src/amstatus.pl server-src/amverifyrun.sh tape-src/Makefile config/Makefile Makefile"
+## This stuff is needed for the documentation.
+DOC_BUILD_DATE=`date '+%d-%m-%Y'`
+
+
+
+# Check whether --with-xsltproc or --without-xsltproc was given.
+if test "${with_xsltproc+set}" = set; then
+  withval="$with_xsltproc"
+   case "$withval" in
+        y | ye | yes)
+          USE_XSLTPROC=yes;;
+        n | no)
+          USE_XSLTPROC=no;;
+        *)
+          USE_XSLTPROC=yes;
+          XSLTPROC="$withval";;
+      esac
+
+else
+   USE_XSLTPROC=maybe;
+fi;
+
+
+
+# This looks bad, but && and || have equal precedence in shells, so
+# actually it's all OK.
+if test "$USE_XSLTPROC" = "yes" || test "$USE_XSLTPROC" = "maybe" && \
+   test -z "$XSLTPROC"; then
+    # Extract the first word of "xsltproc", so it can be a program name with args.
+set dummy xsltproc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_XSLTPROC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $XSLTPROC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XSLTPROC="$XSLTPROC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XSLTPROC="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+XSLTPROC=$ac_cv_path_XSLTPROC
+
+if test -n "$XSLTPROC"; then
+  echo "$as_me:$LINENO: result: $XSLTPROC" >&5
+echo "${ECHO_T}$XSLTPROC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    if test -n "$XSLTPROC"; then
+        USE_XSLTPROC=yes;
+    else
+        if test "$USE_XSLTPROC" = yes; then
+           { { echo "$as_me:$LINENO: error: can't find xsltproc, but running with --with-xsltproc." >&5
+echo "$as_me: error: can't find xsltproc, but running with --with-xsltproc." >&2;}
+   { (exit 1); exit 1; }; }
+        else
+           USE_XSLTPROC=no;
+        fi
+    fi
+fi
+
+
+
+if test "$USE_XSLTPROC" = yes; then
+  HAVE_XSLTPROC_TRUE=
+  HAVE_XSLTPROC_FALSE='#'
+else
+  HAVE_XSLTPROC_TRUE='#'
+  HAVE_XSLTPROC_FALSE=
+fi
+
+
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ac_config_files="$ac_config_files amplot/amcat.awk amplot/amplot.sh amplot/Makefile changer-src/chg-manual.sh changer-src/chg-multi.sh changer-src/chg-mtx.sh changer-src/chg-chs.sh changer-src/chg-rth.pl changer-src/chg-chio.pl changer-src/chg-zd-mtx.sh changer-src/Makefile changer-src/chg-juke.sh changer-src/chg-rait.sh changer-src/chg-null.sh changer-src/chg-mcutil.sh changer-src/chg-disk.sh changer-src/chg-iomega.pl client-src/patch-system.sh client-src/Makefile dumper-src/gnutar.pl dumper-src/generic-dumper.pl dumper-src/Makefile common-src/versuff.c common-src/Makefile example/amanda.conf example/Makefile example/chg-mcutil.conf man/Makefile docs/Makefile recover-src/Makefile restore-src/Makefile server-src/amcheckdb.sh server-src/amcleanup.sh server-src/amdump.sh server-src/amfreetapes.sh server-src/amoverview.pl server-src/amrmtape.sh server-src/amtoc.pl server-src/amverify.sh server-src/Makefile server-src/amstatus.pl server-src/amverifyrun.sh server-src/amcrypt.sh server-src/amaespipe.sh tape-src/Makefile config/Makefile Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -50092,6 +53141,20 @@ echo "$as_me: error: conditional \"WANT_SETUID_CLIENT\" was never defined.
 Usually this means the macro was only invoked conditionally." >&2;}
    { (exit 1); exit 1; }; }
 fi
+if test -z "${WANT_SSH_SECURITY_TRUE}" && test -z "${WANT_SSH_SECURITY_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"WANT_SSH_SECURITY\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"WANT_SSH_SECURITY\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${HAVE_XSLTPROC_TRUE}" && test -z "${HAVE_XSLTPROC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"HAVE_XSLTPROC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAVE_XSLTPROC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
 
 : ${CONFIG_STATUS=./config.status}
 ac_clean_files_save=$ac_clean_files
@@ -50538,8 +53601,8 @@ ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
 ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
 ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
 ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
-ac_cv_stdint_char_model="$ac_cv_stdint_char_model"
-ac_cv_stdint_long_model="$ac_cv_stdint_long_model"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
 ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
 ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
 ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
   "changer-src/chg-iomega.pl" ) CONFIG_FILES="$CONFIG_FILES changer-src/chg-iomega.pl" ;;
   "client-src/patch-system.sh" ) CONFIG_FILES="$CONFIG_FILES client-src/patch-system.sh" ;;
   "client-src/Makefile" ) CONFIG_FILES="$CONFIG_FILES client-src/Makefile" ;;
+  "dumper-src/gnutar.pl" ) CONFIG_FILES="$CONFIG_FILES dumper-src/gnutar.pl" ;;
+  "dumper-src/generic-dumper.pl" ) CONFIG_FILES="$CONFIG_FILES dumper-src/generic-dumper.pl" ;;
+  "dumper-src/Makefile" ) CONFIG_FILES="$CONFIG_FILES dumper-src/Makefile" ;;
   "common-src/versuff.c" ) CONFIG_FILES="$CONFIG_FILES common-src/versuff.c" ;;
   "common-src/Makefile" ) CONFIG_FILES="$CONFIG_FILES common-src/Makefile" ;;
   "example/amanda.conf" ) CONFIG_FILES="$CONFIG_FILES example/amanda.conf" ;;
   "example/Makefile" ) CONFIG_FILES="$CONFIG_FILES example/Makefile" ;;
-  "example/amanda.conf.chg-scsi" ) CONFIG_FILES="$CONFIG_FILES example/amanda.conf.chg-scsi" ;;
-  "example/chg-scsi-linux.conf" ) CONFIG_FILES="$CONFIG_FILES example/chg-scsi-linux.conf" ;;
-  "example/chg-scsi-solaris.conf" ) CONFIG_FILES="$CONFIG_FILES example/chg-scsi-solaris.conf" ;;
-  "example/chg-scsi-hpux.conf" ) CONFIG_FILES="$CONFIG_FILES example/chg-scsi-hpux.conf" ;;
   "example/chg-mcutil.conf" ) CONFIG_FILES="$CONFIG_FILES example/chg-mcutil.conf" ;;
   "man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
   "docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
@@ -50597,6 +53659,8 @@ do
   "server-src/Makefile" ) CONFIG_FILES="$CONFIG_FILES server-src/Makefile" ;;
   "server-src/amstatus.pl" ) CONFIG_FILES="$CONFIG_FILES server-src/amstatus.pl" ;;
   "server-src/amverifyrun.sh" ) CONFIG_FILES="$CONFIG_FILES server-src/amverifyrun.sh" ;;
+  "server-src/amcrypt.sh" ) CONFIG_FILES="$CONFIG_FILES server-src/amcrypt.sh" ;;
+  "server-src/amaespipe.sh" ) CONFIG_FILES="$CONFIG_FILES server-src/amaespipe.sh" ;;
   "tape-src/Makefile" ) CONFIG_FILES="$CONFIG_FILES tape-src/Makefile" ;;
   "config/Makefile" ) CONFIG_FILES="$CONFIG_FILES config/Makefile" ;;
   "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
@@ -50729,6 +53793,7 @@ s,@VERSION_MINOR@,$VERSION_MINOR,;t t
 s,@VERSION_PATCH@,$VERSION_PATCH,;t t
 s,@VERSION_COMMENT@,$VERSION_COMMENT,;t t
 s,@VERSION_SUFFIX@,$VERSION_SUFFIX,;t t
+s,@DUMPER_DIR@,$DUMPER_DIR,;t t
 s,@CONFIG_DIR@,$CONFIG_DIR,;t t
 s,@USE_VERSION_SUFFIXES@,$USE_VERSION_SUFFIXES,;t t
 s,@CLIENT_SCRIPTS_OPT@,$CLIENT_SCRIPTS_OPT,;t t
@@ -50742,6 +53807,7 @@ s,@DEFAULT_TAPE_DEVICE@,$DEFAULT_TAPE_DEVICE,;t t
 s,@DEFAULT_RAW_TAPE_DEVICE@,$DEFAULT_RAW_TAPE_DEVICE,;t t
 s,@DEFAULT_CHANGER_DEVICE@,$DEFAULT_CHANGER_DEVICE,;t t
 s,@GNUTAR_LISTED_INCREMENTAL_DIRX@,$GNUTAR_LISTED_INCREMENTAL_DIRX,;t t
+s,@GNUTAR_LISTED_INCREMENTAL_DIR@,$GNUTAR_LISTED_INCREMENTAL_DIR,;t t
 s,@MAXTAPEBLOCKSIZE@,$MAXTAPEBLOCKSIZE,;t t
 s,@AMANDA_TMPDIR@,$AMANDA_TMPDIR,;t t
 s,@AMANDA_DBGDIR@,$AMANDA_DBGDIR,;t t
@@ -50799,6 +53865,7 @@ s,@AMPLOT_COMPRESS@,$AMPLOT_COMPRESS,;t t
 s,@AMPLOT_CAT_GZIP@,$AMPLOT_CAT_GZIP,;t t
 s,@AMPLOT_CAT_COMPRESS@,$AMPLOT_CAT_COMPRESS,;t t
 s,@AMPLOT_CAT_PACK@,$AMPLOT_CAT_PACK,;t t
+s,@LL_FMT@,$LL_FMT,;t t
 s,@LN_S@,$LN_S,;t t
 s,@ECHO@,$ECHO,;t t
 s,@ac_ct_AR@,$ac_ct_AR,;t t
@@ -50847,8 +53914,14 @@ s,@WANT_RUNTIME_PSEUDO_RELOC_TRUE@,$WANT_RUNTIME_PSEUDO_RELOC_TRUE,;t t
 s,@WANT_RUNTIME_PSEUDO_RELOC_FALSE@,$WANT_RUNTIME_PSEUDO_RELOC_FALSE,;t t
 s,@WANT_SETUID_CLIENT_TRUE@,$WANT_SETUID_CLIENT_TRUE,;t t
 s,@WANT_SETUID_CLIENT_FALSE@,$WANT_SETUID_CLIENT_FALSE,;t t
+s,@WANT_SSH_SECURITY_TRUE@,$WANT_SSH_SECURITY_TRUE,;t t
+s,@WANT_SSH_SECURITY_FALSE@,$WANT_SSH_SECURITY_FALSE,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
 s,@LTALLOCA@,$LTALLOCA,;t t
+s,@DOC_BUILD_DATE@,$DOC_BUILD_DATE,;t t
+s,@XSLTPROC@,$XSLTPROC,;t t
+s,@HAVE_XSLTPROC_TRUE@,$HAVE_XSLTPROC_TRUE,;t t
+s,@HAVE_XSLTPROC_FALSE@,$HAVE_XSLTPROC_FALSE,;t t
 CEOF
 
 _ACEOF
@@ -51543,7 +54616,10 @@ echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
 echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
 if test "_$ac_cv_header_stdint_t" != "_" ; then
 echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
-fi
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
 
 cat >>$ac_stdint <<STDINT_EOF
 
@@ -51603,9 +54679,9 @@ fi
 echo "" >>$ac_stdint
 
 echo "/* which type model has been detected */" >>$ac_stdint
-if test "_$ac_cv_stdint_char_model" != "_" ; then
-echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_stdint_char_model" >>$ac_stdint
-echo "#define   _STDINT_LONG_MODEL" "$ac_cv_stdint_long_model" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define   _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
 else
 echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
 echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
@@ -51690,6 +54766,7 @@ typedef u_int64_t uint64_t;
 /* .. here are some common heuristics using compiler runtime specifics */
 #if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 
@@ -51703,12 +54780,14 @@ typedef unsigned __int64 uint64_t;
 /* note: all ELF-systems seem to have loff-support which needs 64-bit */
 #if !defined _NO_LONGLONG
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 #endif
 
 #elif defined __alpha || (defined __mips && defined _ABIN32)
 #if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
 typedef long int64_t;
 typedef unsigned long uint64_t;
 #endif
@@ -51791,6 +54870,7 @@ typedef          int     int32_t;
 /* assuming the system has a "long long" */
 #ifndef _HAVE_UINT64_T
 #define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
 typedef unsigned long long uint64_t;
 typedef          long long  int64_t;
 #endif
@@ -51876,12 +54956,87 @@ typedef           long   intptr_t;
 #endif
 #endif
 
+/* The ISO C99 standard specifies that in C++ implementations these
+   should only be defined if explicitly requested.  */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed.  */
+# define INT8_C(c)      c
+# define INT16_C(c)     c
+# define INT32_C(c)     c
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INT64_C(c)    c ## L
+# else
+#  define INT64_C(c)    c ## LL
+# endif
+
+/* Unsigned.  */
+# define UINT8_C(c)     c ## U
+# define UINT16_C(c)    c ## U
+# define UINT32_C(c)    c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define UINT64_C(c)   c ## UL
+# else
+#  define UINT64_C(c)   c ## ULL
+# endif
+
+/* Maximal type.  */
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INTMAX_C(c)   c ## L
+#  define UINTMAX_C(c)  c ## UL
+# else
+#  define INTMAX_C(c)   c ## LL
+#  define UINTMAX_C(c)  c ## ULL
+# endif
+
+  /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types.  */
+# define INT8_MIN               (-128)
+# define INT16_MIN              (-32767-1)
+# define INT32_MIN              (-2147483647-1)
+# define INT64_MIN              (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types.  */
+# define INT8_MAX               (127)
+# define INT16_MAX              (32767)
+# define INT32_MAX              (2147483647)
+# define INT64_MAX              (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types.  */
+# define UINT8_MAX              (255)
+# define UINT16_MAX             (65535)
+# define UINT32_MAX             (4294967295U)
+# define UINT64_MAX             (__UINT64_C(18446744073709551615))
+
+/* Minimum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MIN         INT8_MIN
+# define INT_LEAST16_MIN        INT16_MIN
+# define INT_LEAST32_MIN        INT32_MIN
+# define INT_LEAST64_MIN        INT64_MIN
+/* Maximum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MAX         INT8_MAX
+# define INT_LEAST16_MAX        INT16_MAX
+# define INT_LEAST32_MAX        INT32_MAX
+# define INT_LEAST64_MAX        INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size.  */
+# define UINT_LEAST8_MAX        UINT8_MAX
+# define UINT_LEAST16_MAX       UINT16_MAX
+# define UINT_LEAST32_MAX       UINT32_MAX
+# define UINT_LEAST64_MAX       UINT64_MAX
+
   /* shortcircuit*/
 #endif
   /* once */
 #endif
 #endif
 STDINT_EOF
+fi
     if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
       { echo "$as_me:$LINENO: $ac_stdint_h is unchanged" >&5
 echo "$as_me: $ac_stdint_h is unchanged" >&6;}
index ff7e4901c46490a2deb720ab4f96ea92f0fafba3..e56c7b857fd69b260fe1b138ea685d12f15c76b5 100644 (file)
@@ -14,10 +14,10 @@ AC_DEFINE_UNQUOTED(CONFIGURE_COMMAND,"$CONFIGURE_COMMAND",
          [Saves the original ./configure command line arguments])
 AC_SUBST(CONFIGURE_COMMAND)
 
-AM_INIT_AUTOMAKE(amanda, 2.4.5p1)
+AM_INIT_AUTOMAKE(amanda, 2.5.0)
 AM_CONFIG_HEADER(config/config.h)
 
-AC_PREREQ(2.59)                dnl Minimum Autoconf version required.
+AC_PREREQ(2.57)                dnl Minimum Autoconf version required.
 
 if test -f "$srcdir/SNAPSHOT"; then
   cat < "$srcdir/SNAPSHOT"
@@ -61,11 +61,22 @@ SYSPATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb:/usr/bsd:/etc:/usr/etc"
 LOCPATH=`(
     test "x$prefix" = xNONE && prefix=$ac_default_prefix
     test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
-    eval echo "$libexecdir:$PATH:/usr/local/sbin:/usr/local/bin"
+    eval echo "$libexecdir:$PATH:/usr/local/sbin:/usr/local/bin:/usr/ccs/bin"
 )`
 SYSLOCPATH="$SYSPATH:$LOCPATH"
 LOCSYSPATH="$LOCPATH:$SYSPATH"
 
+AC_ARG_WITH(cflags,
+    [  --with-cflags=CFLAGS   arguments to the c compiler (-Wall, -g, etc)],
+    [
+       case "$withval" in
+       "" | y | ye | yes | n | no)
+           AC_MSG_ERROR([*** You must supply an argument to the --with-includes option.])
+           ;;
+       esac
+       CFLAGS="$withval"
+    ])
+
 AC_ARG_WITH(includes,
     [  --with-includes=DIR    site header files for readline, etc in DIR],
     [
@@ -102,7 +113,7 @@ if test "$LIBRARY_DIRS"; then
        for dir in $LIBRARY_DIRS; do
            if test -d "$dir"; then
                case "$target" in
-                 *-solaris2*)
+                 *-solaris2*,*-netbsd*)
                        AMANDA_LDFLAGS="$AMANDA_LDFLAGS -R$dir"
                        ;;
                esac
@@ -113,8 +124,31 @@ if test "$LIBRARY_DIRS"; then
        done
 fi
 
+AC_ARG_WITH(dumperdir,
+    [  --with-dumperdir=DIR   where we install the dumpers [[EPREFIX/dumper]]],
+    [
+       case "$withval" in
+       "" | y | ye | yes | n | no)
+           AC_MSG_ERROR([*** You must supply an argument to the --with-dumperdir option.])
+         ;;
+       esac
+       DUMPER_DIR="$withval"
+    ], [
+        test "x$prefix" = xNONE && prefix=$ac_default_prefix
+        test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
+        DUMPER_DIR=$exec_prefix/dumper
+    ]
+)
+DUMPER_DIR=`(
+    test "x$prefix" = xNONE && prefix=$ac_default_prefix
+    test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
+    eval echo "$DUMPER_DIR"
+)`
+AC_DEFINE_UNQUOTED(DUMPER_DIR,"$DUMPER_DIR",[Directory in which dumper interfaces should be installed and searched. ])
+AC_SUBST(DUMPER_DIR)
+
 AC_ARG_WITH(configdir,
-    [  --with-configdir=DIR   runtime config files in DIR [sysconfdir/amanda]],
+    [  --with-configdir=DIR   runtime config files in DIR [[sysconfdir/amanda]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -124,7 +158,7 @@ AC_ARG_WITH(configdir,
          ;;
        esac
     ],
-    : ${CONFIG_DIR=$sysconfdir/amanda}
+    : ${CONFIG_DIR="$sysconfdir/amanda"}
 )
 CONFIG_DIR=`(
     test "x$prefix" = xNONE && prefix=$ac_default_prefix
@@ -162,7 +196,7 @@ y | ye | yes)
 
     program_suffix="-$VERSION"
     # This is from the output of configure.in.
-    if test "$program_transform_name" = s,x,x,; then
+    if test "x$program_transform_name" = xs,x,x,; then
        program_transform_name=
     else
        # Double any \ or $.  echo might interpret backslashes.
@@ -172,14 +206,14 @@ EOF_SED
        program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
        rm -f conftestsed
     fi
-    test "$program_prefix" != NONE &&
+    test "x$program_prefix" != xNONE &&
        program_transform_name="s,^,${program_prefix},; $program_transform_name"
     # Use a double $ so make ignores it.
-    test "$program_suffix" != NONE &&
+    test "x$program_suffix" != xNONE &&
        program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
 
     # sed with no file args requires a program.
-    test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+    test "x$program_transform_name" = "" && program_transform_name="xs,x,x,"
     # Remove empty command
     cat <<\EOF_SED > conftestsed
 s,\;\;,\;,g; s,\; \$,,g; s,\;$,,g
@@ -291,7 +325,7 @@ AC_ARG_WITH(amrecover,
 )
 
 AC_ARG_WITH(index-server,
-   [  --with-index-server=HOST default amanda index server [`uname -n`]],
+   [  --with-index-server=HOST default amanda index server [[`uname -n`]]],
    [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -322,7 +356,7 @@ n | no) :
 esac
 
 AC_ARG_WITH(user,
-    [  --with-user=USER       force execution to USER on client systems [required]],
+    [  --with-user=USER       force execution to USER on client systems [[required]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -341,7 +375,7 @@ AC_DEFINE_UNQUOTED(CLIENT_LOGIN,"$CLIENT_LOGIN",
 AC_SUBST(CLIENT_LOGIN)
 
 AC_ARG_WITH(group,
-    [  --with-group=GROUP     group allowed to execute setuid-root programs [required]],
+    [  --with-group=GROUP     group allowed to execute setuid-root programs [[required]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -358,7 +392,7 @@ fi
 AC_SUBST(SETUID_GROUP)
 
 AC_ARG_WITH(owner,
-    [  --with-owner=USER       force ownership of files to USER [default == --with-user value]],
+    [  --with-owner=USER       force ownership of files to USER [[default == --with-user value]]],
     [
         case "$withval" in
         "" | y | ye | yes | n | no)
@@ -387,7 +421,7 @@ AC_ARG_WITH(rundump,
 )
 
 AC_ARG_WITH(config,
-   [  --with-config=CONFIG   default configuration [DailySet1]],
+   [  --with-config=CONFIG   default configuration [[DailySet1]]],
    [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -404,7 +438,7 @@ AC_DEFINE_UNQUOTED(DEFAULT_CONFIG,"$DEFAULT_CONFIG",
 AC_SUBST(DEFAULT_CONFIG)
 
 AC_ARG_WITH(tape-server,
-    [  --with-tape-server=HOST default restoring tape server is HOST [same as --with-index-server]],
+    [  --with-tape-server=HOST default restoring tape server is HOST [[same as --with-index-server]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -440,8 +474,8 @@ AC_ARG_WITH(tape-device,
            dnl bytes are returned upon reading to the next tape mark,
            dnl instead of returning an error.  Look for devices that have
            dnl a 'b' in their name.
-           tape_dev=/dev/null
-           nr_tape_dev=/dev/null
+           tape_dev=null:
+           nr_tape_dev=null:
            if test -d /dev/rmt; then
 
                dnl See if we can find two devices, one being the norewind
@@ -530,7 +564,7 @@ AC_ARG_WITH(norew-tape,
     ],)
 
 AC_ARG_WITH(changer-device,
-    [  --with-changer-device=ARG default tape changer device [/dev/ch0 if it exists]],
+    [  --with-changer-device=ARG default tape changer device [[/dev/ch0 if it exists]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -584,7 +618,7 @@ y |  ye | yes) AC_DEFINE(HAVE_BROKEN_FSF,1,[Define this if issuing a fsf on a ta
 esac
 
 AC_ARG_WITH(gnutar,
-    [  --with-gnutar[=PROG]     use PROG as GNU tar executable [default: looks for one]],
+    [  --with-gnutar[[=PROG]]      use PROG as GNU tar executable [[default: looks for one]]],
     [
        case "$withval" in
            /*) GNUTAR="$withval";;
@@ -595,28 +629,13 @@ AC_ARG_WITH(gnutar,
     ]
 )
 
-AC_ARG_WITH(qde,
-    [   --with-qde                use quick-and-dirty estimates for gnutar ],
-    USE_QUICK_AND_DIRTY_ESTIMATES=$withval,
-    : ${USE_QUICK_AND_DIRTY_ESTIMATES=no}
-)
-case "$USE_QUICK_AND_DIRTY_ESTIMATES" in
-n | no) : USE_QUICK_AND_DIRTY_ESTIMATES=no;;
-y |  ye | yes) : USE_QUICK_AND_DIRTY_ESTIMATES=yes
-       AC_DEFINE(USE_QUICK_AND_DIRTY_ESTIMATES,1,[ Define if you want to use amqde instead of gnutar for estimates ])
-  ;;
-*) AC_MSG_ERROR([*** You must not supply an argument to --with-qde option.])
-  ;;
-esac
-
-
 AC_ARG_WITH(smbclient,
-    [  --with-smbclient[=PROG]   use PROG as Samba's smbclient executable [default: looks for one]],
+    [  --with-smbclient[[=PROG]]   use PROG as Samba's smbclient executable [[default: looks for one]]],
     [
        case "$withval" in
            /*) SAMBA_CLIENT="$withval";;
            y|ye|yes) :;;
-           n|no) SAMBA_CLIENT="no";;
+           n|no) SAMBA_CLIENT=;;
            *)  AC_MSG_ERROR([*** You must supply a full pathname to --with-smbclient]);;
        esac
     ]
@@ -629,7 +648,7 @@ AC_ARG_WITH(samba-user,
 )
 
 AC_ARG_WITH(gnutar-listdir,
-   [  --with-gnutar-listdir=DIR  gnutar directory lists go in DIR [localstatedir/amanda/gnutar-lists]],
+   [  --with-gnutar-listdir=DIR  gnutar directory lists go in DIR [[localstatedir/amanda/gnutar-lists]]],
    [
        case "$withval" in
            n | no)             unset GNUTAR_LISTDIR ;;
@@ -638,7 +657,7 @@ AC_ARG_WITH(gnutar-listdir,
            *)                  AC_MSG_ERROR([*** You must supply a full pathname to --with-gnutar-listdir])
        esac
     ],
-    : ${GNUTAR_LISTDIR=$localstatedir/amanda/gnutar-lists}
+    : ${GNUTAR_LISTDIR="$localstatedir/amanda/gnutar-lists"}
 )
 if test "$GNUTAR_LISTDIR"; then
     GNUTAR_LISTDIR=`(
@@ -657,6 +676,8 @@ AC_ARG_WITH(gnutar-listed-incremental,
    [    AC_MSG_ERROR([*** The gnutar-listed-incremental option was deprecated, use gnutar-listdir instead])
    ]
 )
+GNUTAR_LISTED_INCREMENTAL_DIR=$GNUTAR_LISTDIR
+AC_SUBST(GNUTAR_LISTED_INCREMENTAL_DIR)
 
 AC_ARG_WITH(bsd-security,
     [  --without-bsd-security do not use BSD rsh/rlogin style security],
@@ -688,6 +709,25 @@ y |  ye | yes) :
   ;;
 esac
 
+dnl Specify --with-dbmalloc if you desire dbmalloc to be linked in
+
+AC_ARG_WITH(dbmalloc,
+    [  --with-dbmalloc=DIR  Location of dbmalloc libs and headers],
+    DBMALLOC="$withval",
+    : ${DBMALLOC=no}
+)
+
+case "$DBMALLOC" in
+n | no)
+    DBMALLOCCFLAGS=""
+    DBMALLOCLIBS=""
+    ;;
+*) 
+    DBMALLOCCFLAGS="-I$DBMALLOC -DUSE_DBMALLOC"
+    DBMALLOCLIBS="-L$DBMALLOC -ldbmalloc"
+    ;;
+esac
+
 dnl Specify --with-krb4-security if Kerberos software is in somewhere
 dnl other than the listed KRB4_SPOTS.  We only compile kerberos support in
 dnl if the right files are there.
@@ -695,7 +735,7 @@ dnl if the right files are there.
 : ${KRB4_SPOTS="/usr/kerberos /usr/cygnus /usr /opt/kerberos"}
 
 AC_ARG_WITH(krb4-security,
-    [  --with-krb4-security=DIR   Location of Kerberos software [/usr/kerberos /usr/cygnus /usr /opt/kerberos]],
+    [  --with-krb4-security=DIR   Location of Kerberos software [[/usr/kerberos /usr/cygnus /usr /opt/kerberos]]],
     KRB4_SECURITY="$withval",
     : ${KRB4_SECURITY=no}
 )
@@ -709,7 +749,7 @@ y | ye | yes) : ;;
 esac
 
 AC_MSG_CHECKING(for Kerberos and Amanda kerberos4 bits)
-if test "${KRB4_SECURITY}" = yes -a -f  ${srcdir-.}/common-src/krb4-security.c ; then
+if test "x${KRB4_SECURITY}" = xyes -a -f  ${srcdir-.}/common-src/krb4-security.c ; then
     for dir in $KRB4_SPOTS; do
        if test -f ${dir}/lib/libkrb.a -a -f ${dir}/lib/libdes.a ; then
            #
@@ -728,12 +768,9 @@ if test "${KRB4_SECURITY}" = yes -a -f  ${srcdir-.}/common-src/krb4-security.c ;
            fi
            KRB4LDFLAGS=-L$dir/lib
            KRB4LIBS="-lkrb -ldes"
-           if test -f ${dir}/lib/libcom_err.a ; then
+           if test -f ${dir}/lib/libcom_err.a; then
                KRB4LIBS="$KRB4LIBS -lcom_err"
            fi
-           if test -f ${dir}/lib/libroken.a ; then
-               KRB4LIBS="$KRB4LIBS -lroken"
-           fi
            break
        elif test -f ${dir}/lib/libkrb4.a &&
             test -f ${dir}/lib/libcrypto.a &&
@@ -753,36 +790,45 @@ if test "${KRB4_SECURITY}" = yes -a -f  ${srcdir-.}/common-src/krb4-security.c ;
                KRB4LIBS="-lkrb4 -lcrypto -ldes425"
            fi
            break
-       elif test -f ${dir}/lib/libkrb4.dylib &&
-            test -f ${dir}/lib/libcrypto.dylib &&
-            test -f ${dir}/lib/libdes425.dylib ; then
-           #
-           # This is Kerberos 5 with Kerberos 4 back-support for Mac OS X.
-           #
-           AC_MSG_RESULT(found in $dir)
-           KRB4_SECURITY=yes
-           AC_DEFINE(KRB4_SECURITY, 1, [Enable Kerberos security. ])
-           KRB4INCLUDES="-I$dir/include -I$dir/include/kerberosIV"
-           KRB4LDFLAGS=-L$dir/lib
-           if test -f ${dir}/lib/libkrb5.dylib &&
-               test -f ${dir}/lib/libcom_err.dylib; then
-               KRB4LIBS="-lkrb4 -lkrb5 -lcrypto -ldes425 -lcom_err"
-           else
-               KRB4LIBS="-lkrb4 -lcrypto -ldes425"
-           fi
-           break
        fi
     done
 
-    if test "$KRB4LDFLAGS" = "" ; then
-       AC_MSG_ERROR([*** Kerberos IV not found.])
+    if test "x$KRB4LDFLAGS" = "x" ; then
+       AC_MSG_RESULT(no libraries found)
     fi
 else
     AC_MSG_RESULT(no)
 fi
 
+AC_ARG_WITH(rsh-security,
+    [  --with-rsh-security use rsh as a transport],
+    RSH_SECURITY=$withval,
+    : ${RSH_SECURITY=yes}
+)
+case "$RSH_SECURITY" in
+n | no) : ;;
+y |  ye | yes) AC_DEFINE(RSH_SECURITY,1,[Define if RSH transport should be enabled. ])
+  ;;
+*) AC_MSG_ERROR([*** You must not supply an argument the to --with-rsh-security option.])
+  ;;
+esac
+
+AC_ARG_WITH(ssh-security,
+    [  --with-ssh-security use ssh as a transport],
+    SSH_SECURITY=$withval,
+    : ${SSH_SECURITY=no}
+)
+case "$SSH_SECURITY" in
+n | no) : ;;
+y |  ye | yes) AC_DEFINE(SSH_SECURITY,1,[Define if SSH transport should be enabled. ])
+              SSH_SECURITY_SET=true
+  ;;
+*) AC_MSG_ERROR([*** You must not supply an argument the to --with-ssh-security option.])
+  ;;
+esac
+
 AC_ARG_WITH(server-principal,
-    [    --with-server-principal=ARG    server host principal  ["amanda"]],
+    [    --with-server-principal=ARG    server host principal  [["amanda"]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -798,7 +844,7 @@ AC_ARG_WITH(server-principal,
 AC_DEFINE_UNQUOTED(SERVER_HOST_PRINCIPLE,"$SERVER_HOST_PRINCIPLE",[The Kerberos server principle. ])
 
 AC_ARG_WITH(server-instance,
-    [    --with-server-instance=ARG     server host instance   ["amanda"]],
+    [    --with-server-instance=ARG     server host instance   [["amanda"]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -813,7 +859,7 @@ AC_ARG_WITH(server-instance,
 AC_DEFINE_UNQUOTED(SERVER_HOST_INSTANCE,"$SERVER_HOST_INSTANCE",[The Kerberos server instance. ])
 
 AC_ARG_WITH(server-keyfile,
-    [    --with-server-keyfile=ARG      server host key file   ["/.amanda"]],
+    [    --with-server-keyfile=ARG      server host key file   [["/.amanda"]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -828,7 +874,7 @@ AC_ARG_WITH(server-keyfile,
 AC_DEFINE_UNQUOTED(SERVER_HOST_KEY_FILE,"$SERVER_HOST_KEY_FILE",[The Kerberos server key file. ])
 
 AC_ARG_WITH(client-principal,
-    [    --with-client-principal=ARG    client host principal  ["rcmd"]],
+    [    --with-client-principal=ARG    client host principal  [["rcmd"]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -843,7 +889,7 @@ AC_ARG_WITH(client-principal,
 AC_DEFINE_UNQUOTED(CLIENT_HOST_PRINCIPLE,"$CLIENT_HOST_PRINCIPLE",[The Kerberos client host principle. ])
 
 AC_ARG_WITH(client-instance,
-    [    --with-client-instance=ARG     client host instance   [HOSTNAME_INSTANCE]],
+    [    --with-client-instance=ARG     client host instance   [[HOSTNAME_INSTANCE]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -858,7 +904,7 @@ AC_ARG_WITH(client-instance,
 AC_DEFINE_UNQUOTED(CLIENT_HOST_INSTANCE,$CLIENT_HOST_INSTANCE,[The Kerberos client host instance. ])
 
 AC_ARG_WITH(client-keyfile,
-    [    --with-client-keyfile=ARG      client host key file   [KEYFILE]],
+    [    --with-client-keyfile=ARG      client host key file   [[KEYFILE]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -872,14 +918,14 @@ AC_ARG_WITH(client-keyfile,
 )
 
 # Assume it's either KEYFILE (defined in krb.h), or a string filename...
-if test "$CLIENT_HOST_KEY_FILE" != "KEYFILE"; then
+if test "x$CLIENT_HOST_KEY_FILE" != "xKEYFILE"; then
   CLIENT_HOST_KEY_FILE="\"$CLIENT_HOST_KEY_FILE\""
 fi
 
 AC_DEFINE_UNQUOTED(CLIENT_HOST_KEY_FILE,$CLIENT_HOST_KEY_FILE,[The Kerberos client host key file. ])
 
 AC_ARG_WITH(ticket-lifetime,
-    [    --with-ticket-lifetime=ARG     ticket lifetime        [128]],
+    [    --with-ticket-lifetime=ARG     ticket lifetime        [[128]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -893,15 +939,91 @@ AC_ARG_WITH(ticket-lifetime,
 )
 AC_DEFINE_UNQUOTED(TICKET_LIFETIME,$TICKET_LIFETIME,[The Kerberos ticket lifetime. ])
 
+dnl Specify --with-krb5-security if Kerberos software is in somewhere
+dnl other than the listed KRB5_SPOTS.  We only compile kerberos support in
+dnl if the right files are there.
+
+: ${KRB5_SPOTS="/usr/kerberos /usr/cygnus /usr /opt/kerberos"}
+
+AC_ARG_WITH(krb5-security,
+    [  --with-krb5-security=DIR   Location of Kerberos V software [[/usr/kerberos /usr/cygnus /usr /opt/kerberos]]],
+    KRB5_SECURITY="$withval",
+    : ${KRB5_SECURITY=no}
+)
+
+case "$KRB5_SECURITY" in
+n | no) KRB5_SECURITY=no
+        KRB5_SPOTS=""
+       ;;
+y | ye | yes) : ;;
+*) KRB5_SPOTS="$KRB5_SECURITY"
+   KRB5_SECURITY=yes
+   ;;
+esac
+
+# if found, force the static versions of these libs (.a) by linking directly
+# with the .a files.  I don't know how to get -R dependancies checked
+# in autoconf at this time. -kashmir
+AC_MSG_CHECKING(for Kerberos V)
+KRB5_DIR_FOUND=""
+KRB5_CFLAGS=""
+for dir in $KRB5_SPOTS; do
+    k5libdir=${dir}/lib
+    if test -f ${k5libdir}/libkrb5.a -a -f ${k5libdir}/libgssapi_krb5.a -a -f ${k5libdir}/libcom_err.a; then
+       if test -f ${k5libdir}/libcrypto.a; then
+           K5CRYPTO=${k5libdir}/libcrypto.a
+       elif test -f ${k5libdir}/libk5crypto.a; then
+           K5CRYPTO=${k5libdir}/libk5crypto.a
+       else
+           K5CRYPTO=""
+       fi
+       KRB5_DIR_FOUND=$dir
+       KRB5LIBS="${k5libdir}/libgssapi_krb5.a ${k5libdir}/libkrb5.a $K5CRYPTO ${k5libdir}/libcom_err.a"
+       KRB5CFLAGS=""
+       break
+    elif test -f ${k5libdir}/libkrb5.a -a -f ${k5libdir}/libasn1.a -a -f ${k5libdir}/libgssapi.a; then
+       KRB5_DIR_FOUND=$dir
+       KRB5LIBS="${k5libdir}/libgssapi.a ${k5libdir}/libkrb5.a ${k5libdir}/libasn1.a"
+       KRB5_CFLAGS="-DKRB5_HEIMDAL_INCLUDES"
+       break
+    fi
+done
+
+if test "$KRB5_DIR_FOUND"; then
+       AC_MSG_RESULT(found in $KRB5_DIR_FOUND)
+       KRB5_SECURITY=yes
+       AC_DEFINE(KRB5_SECURITY,1,[Define if Kerberos 5 security is to be enabled. ])
+       #
+       # some OS's, such as NetBSD, stick krb5 includes out of the way...
+       # should probably just use autoconf to look for various include
+       # options and set them, but don't quite want to do that until I've
+       # dug into it a bit more.
+       #
+       if test -d "$KRB5_DIR_FOUND/krb5" ; then
+               KRB5INCLUDES="-I$KRB5_DIR_FOUND/include/krb5"
+       else
+               KRB5INCLUDES="-I$KRB5_DIR_FOUND/include"
+       fi
+       if test "$KRB5_CFLAGS" ; then
+               KRB5INCLUDES="$KRB5INCLUDES $KRB5_CFLAGS"
+       fi
+       KRB5LDFLAGS=-L$k5libdir
+       break
+fi
+
+if test "x$KRB5LDFLAGS" = "x" ; then
+    AC_MSG_RESULT(no krb5 system libraries found)
+fi
+
 
 AC_ARG_WITH(portrange,
-    [  --with-portrange=low,high     bind unreserved TCP server sockets to ports within this range [unlimited]],
+    [  --with-portrange=low,high     bind unreserved TCP server sockets to ports within this range [[unlimited]]],
     [
        TCPPORTRANGE="$withval"
     ]
 )
 AC_ARG_WITH(tcpportrange,
-    [  --with-tcpportrange=low,high  bind unreserved TCP server sockets to ports within this range [unlimited]],
+    [  --with-tcpportrange=low,high  bind unreserved TCP server sockets to ports within this range [[unlimited]]],
     [
        TCPPORTRANGE="$withval"
     ]
@@ -926,7 +1048,7 @@ if test x"${TCPPORTRANGE+set}" = x"set"; then
 fi
 
 AC_ARG_WITH(udpportrange,
-    [  --with-udpportrange=low,high  bind reserved UDP server sockets to ports within this range [unlimited]],
+    [  --with-udpportrange=low,high  bind reserved UDP server sockets to ports within this range [[unlimited]]],
     [
        UDPPORTRANGE="$withval"
     ]
@@ -962,7 +1084,7 @@ AC_DEFINE_UNQUOTED(MAX_TAPE_BLOCK_KB,($MAXTAPEBLOCKSIZE),[Maximum size of a tape
 AC_SUBST(MAXTAPEBLOCKSIZE)
 
 AC_ARG_WITH(db,
-    [  --with-db={text,db,dbm,gdbm,ndbm} use the selected database format [text]],
+    [  --with-db={text,db,dbm,gdbm,ndbm} use the selected database format [[text]]],
     [
        case "$withval" in
        "" | y | ye | yes | n | no)
@@ -1022,7 +1144,7 @@ y |  ye | yes) AC_DEFINE(ASSERTIONS,1,[Define if you want assertion checking. ])
 esac
 
 AC_ARG_WITH(tmpdir,
-    [  --with-tmpdir[=/temp/dir] area Amanda can use for temp files [/tmp/amanda]],
+    [  --with-tmpdir[=/temp/dir] area Amanda can use for temp files [[/tmp/amanda]]],
     tmpdir="$withval",
     : ${tmpdir=yes}
 )
@@ -1043,7 +1165,7 @@ AC_DEFINE_UNQUOTED(AMANDA_TMPDIR,"$AMANDA_TMPDIR",[The directory in which Amanda
 AC_SUBST(AMANDA_TMPDIR)
 
 AC_ARG_WITH(debugging,
-    [  --with[out]-debugging[=/debug/dir] [do not] record runtime debugging information in specified directory [--with-tmpdir]],
+    [  --with[[out]]-debugging[[=/debug/dir]] [[do not]] record runtime debugging information in specified directory [[--with-tmpdir]]],
     debugging="$withval",
     : ${debugging=yes}
 )
@@ -1054,8 +1176,8 @@ debugging=`(
 )`
 case "$debugging" in
 n | no) AMANDA_DBGDIR="";;
-y |  ye | yes) AMANDA_DBGDIR="$AMANDA_TMPDIR" ;;
-/*) AMANDA_DBGDIR="$debugging" ;;
+y |  ye | yes) AMANDA_DBGDIR="$AMANDA_TMPDIR";;
+/*) AMANDA_DBGDIR="$debugging";;
 *) AC_MSG_ERROR([*** You must supply a full pathname to --with-debugging option.])
   ;;
 esac
@@ -1067,7 +1189,7 @@ case "$AMANDA_DBGDIR" in
 esac
 
 AC_ARG_WITH(debug_days,
-    [  --with-debug-days=NN    number of days to keep debugging files [default=4]],
+    [  --with-debug-days=NN    number of days to keep debugging files [[default=4]]],
     debug_days="$withval",
     : ${debug_days=4}
 )
@@ -1082,7 +1204,7 @@ AC_DEFINE_UNQUOTED(AMANDA_DEBUG_DAYS,$AMANDA_DEBUG_DAYS,[Number of days to keep
 AC_SUBST(AMANDA_DEBUG_DAYS)
 
 AC_ARG_WITH(testing,
-    [  --with-testing[=suffix] use alternate service names],
+    [  --with-testing[[=suffix]] use alternate service names],
     TESTING="$withval",
     : ${TESTING=no}
 )
@@ -1172,6 +1294,8 @@ case "$target" in
                        ;;
   *-pc-linux-*)
                        ;;
+  x86_64-*-linux-*)
+                       ;;
   alpha*-*-linux-*)
                        ;;
   sparc*-*-linux-*)
@@ -1247,10 +1371,10 @@ if test -n "$xenix_tapeio"; then
   AC_DEFINE(XENIX_TAPEIO,1,[Define on XENIX/ISC. ])
 fi
 
-AMANDA_CFLAGS="$AMANDA_CFLAGS $KRB4INCLUDES"
-AMANDA_CPPFLAGS="$AMANDA_CPPFLAGS $KRB4INCLUDES"
-AMANDA_LDFLAGS="$AMANDA_LDFLAGS $KRB4LDFLAGS"
-AMANDA_LIBS="$KRB4LIBS $AMANDA_LIBS"
+AMANDA_CFLAGS="$AMANDA_CFLAGS $KRB4INCLUDES $KRB5INCLUDES $DBMALLOCCFLAGS"
+AMANDA_CPPFLAGS="$AMANDA_CPPFLAGS $KRB4INCLUDES $KRB5INCLUDES $DBMALLOCINCLUDES"
+AMANDA_LDFLAGS="$AMANDA_LDFLAGS $KRB4LDFLAGS $KRB5LDFLAGS"
+AMANDA_LIBS="$KRB4LIBS $KRB5LIBS $DBMALLOCLIBS $AMANDA_LIBS"
 CFLAGS="$CFLAGS $AMANDA_CFLAGS"
 CPPFLAGS="$CPPFLAGS $AMANDA_CPPFLAGS"
 LDFLAGS="$LDFLAGS $AMANDA_LDFLAGS"
@@ -1271,7 +1395,7 @@ AC_PATH_PROGS(AR,ar,,$LOCSYSPATH)
 
 AC_PROG_AWK
 AMANDA_PROG_AWK_VAR
-if test "$amanda_cv_awk_var_assignment" = no; then
+if test "x$amanda_cv_awk_var_assignment" = xno; then
     NO_AMPLOT_MODE=true
     AC_MSG_WARN([*** Your $awk cannot do command line variable assignment.  Amplot will not be installed.])
 fi
@@ -1311,10 +1435,7 @@ if test ! -z "$GNUTAR"; then
   esac
 fi
 
-if test "x$SAMBA_CLIENT" != "xno"
-then AC_PATH_PROGS(SAMBA_CLIENT,smbclient,,$LOCSYSPATH)
-else SAMBA_CLIENT=
-fi
+AC_PATH_PROGS(SAMBA_CLIENT,smbclient,,$LOCSYSPATH)
 if test ! -z "$SAMBA_CLIENT"; then
   case "`\"$SAMBA_CLIENT\" '\\\\not.a.host.name\\notashare' -U nosuchuser -N -Tx /dev/null 2>&1`" in
   *"Unknown host"*)
@@ -1333,10 +1454,8 @@ if test ! -z "$SAMBA_CLIENT"; then
     AC_DEFINE_UNQUOTED(SAMBA_VERSION, $smbversion,
       [Not the actual samba version, just a number that should be increased whenever we start to rely on a new samba feature. ])
   fi
-
 fi
 
-
 AC_PATH_PROGS(GZIP,gzip,,$LOCSYSPATH)
 if test "$GZIP"; then
     AC_DEFINE(HAVE_GZIP,1,[Define if Amanda is using the gzip program. ])
@@ -1463,7 +1582,7 @@ if test "$DUMP" -a "$RESTORE"; then
        AC_MSG_WARN([*** $DUMP is not executable, cannot run -E/-S test])
        amanda_cv_dump_estimate=no
     fi
-    if test "$amanda_cv_dump_estimate" != no; then
+    if test "x$amanda_cv_dump_estimate" != xno; then
        AC_DEFINE_UNQUOTED(HAVE_DUMP_ESTIMATE, "$amanda_cv_dump_estimate",[Define to the string that enables dump estimates. ])
     fi
 
@@ -1501,7 +1620,7 @@ if test "$DUMP" -a "$RESTORE"; then
        AC_MSG_WARN([*** $DUMP is not executable, cannot run -h test])
        amanda_cv_honor_nodump=no
       fi
-      if test "$amanda_cv_honor_nodump" = yes; then
+      if test "x$amanda_cv_honor_nodump" = xyes; then
        AC_DEFINE(HAVE_HONOR_NODUMP,1,[Define this if dump accepts -h for honoring nodump. ])
       fi
     ])
@@ -1556,6 +1675,38 @@ AC_SUBST(AMPLOT_CAT_GZIP)
 AC_SUBST(AMPLOT_CAT_COMPRESS)
 AC_SUBST(AMPLOT_CAT_PACK)
 
+# Determine the printf format characters to use when printing
+# values of type long long. This will normally be "ll", but where
+# the compiler treats "long long" as a alias for "long" and printf
+# doesn't know about "long long" use "l".  Hopefully the sprintf
+# will produce a inconsistant result in the later case.  If the compiler
+# fails due to seeing "%lld" we fall back to "l".
+#
+# Win32 uses "%I64d", but that's defined elsewhere since we don't use
+# configure on Win32.
+#
+AC_MSG_CHECKING(printf format modifier for 64-bit integers)
+AC_TRY_RUN([
+#include <stdio.h>
+main() {
+       long long int j = 0;
+       char buf[100];
+       buf[0] = 0;
+       sprintf(buf, "%lld", j);
+       exit((sizeof(long long int) != sizeof(long int))? 0 :
+            (strcmp(buf, "0") != 0));
+} 
+],
+       [AC_MSG_RESULT(ll)
+       LL_FMT="%lld"],
+       [AC_MSG_RESULT(l)
+       LL_FMT="%ld"],
+       [AC_MSG_RESULT(assuming target platform uses ll)
+       LL_FMT="%lld"])
+AC_DEFINE_UNQUOTED(LL_FMT,"$LL_FMT",
+  [Format for a long long printf. ])
+AC_SUBST(LL_FMT)
+
 dnl Empty GZIP so that make dist works.
 GZIP=
 
@@ -1601,7 +1752,7 @@ AC_CACHE_CHECK(
        fi
     ]
 )
-if test "$need_resetofs" = yes; then
+if test "x$need_resetofs" = xyes; then
     AC_DEFINE(NEED_RESETOFS,1,[Define if we have to reset tape offsets when reacing 2GB. ])
 fi
 CFLAGS="$amanda_cv_LFS_CFLAGS $CFLAGS"
@@ -1609,6 +1760,12 @@ CPPFLAGS="$amanda_cv_LFS_CFLAGS $CPPFLAGS"
 LDFLAGS="$amanda_cv_LFS_LDFLAGS $LDFLAGS"
 LIBS="$amanda_cv_LFS_LIBS $LIBS"
 
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(long long)
+AC_CHECK_SIZEOF(intmax_t)
+AC_CHECK_SIZEOF(off_t)
+
 AM_PROG_LIBTOOL
 AC_SUBST(LIBTOOL_DEPS)
 
@@ -1620,26 +1777,6 @@ AC_TYPE_OFF_T
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
 
-dnl We don't have an acconfig.h template since we moved all define templates
-dnl into the third argument of AC_DEFINE.  However, AC_CHECK_TYPE calls
-dnl AC_DEFINE without such an argument, so autoheader complains about no
-dnl template being available.  This is an ugly work-around.
-
-pushdef([AC_DEFINE_SAVED],defn([AC_DEFINE]))
-pushdef([AC_DEFINE],[AC_DEFINE_SAVED([$1],[$2],[Define to $2 if $1 is not defined])])
-
-AC_CHECK_TYPE(ssize_t, int)
-
-dnl there is a push to avoid depending on long longs, so in general it's
-dnl better to convert numbers to kilobytes for consistancies sake.  This
-dnl is primarily checked for for client-src/amqde.c
-AC_CHECK_TYPES(unsigned long long)
-
-popdef([AC_DEFINE])
-popdef([AC_DEFINE_SAVED])
-
-dnl End ugly AC_CHECK_TYPE work-around.
-
 AC_TYPE_UID_T
 AC_TYPE_SIGNAL
 AC_STRUCT_TM
@@ -1661,7 +1798,7 @@ changequote([,]), [#include <sys/types.h>
 #endif
 #include <$3>], ac_cv_type_$1=yes, ac_cv_type_$1=no)])dnl
 AC_MSG_RESULT($ac_cv_type_$1)
-if test $ac_cv_type_$1 = no; then
+if test "x$ac_cv_type_$1" = xno; then
   AC_DEFINE($1, $2, [Define if $1 is not a standard system type])
 fi
 ])
@@ -1726,6 +1863,7 @@ AC_CHECK_HEADERS(\
        sys/tape.h \
        sys/time.h \
        sys/types.h \
+       sys/uio.h \
        sys/vfs.h \
        sys/vfstab.h \
        syslog.h \
@@ -1868,7 +2006,7 @@ dnl Solaris  SCSI
 dnl
 if test x"$ac_cv_header_sys_mtio_h" = x"yes" &&
    test x"$ac_cv_header_sys_scsi_impl_uscsi_h" = x"yes"; then 
-       AC_CACHE_CHECK([for Solaris like scsi support],
+       AC_CACHE_CHECK([for Solaris-like scsi support],
        amanda_cv_solaris_scsi,
        [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 #include <sys/types.h>
@@ -1933,6 +2071,7 @@ if test x"$ac_cv_header_cam_cam_h" = x"yes";then
        fi
 fi
 
+
 dnl
 dnl BSD SCSI
 dnl
@@ -1982,6 +2121,7 @@ case "$target" in
                        AC_CHECK_LIB(socket,main)
                        ;;
     *)
+                       AC_CHECK_LIB(resolv,main)
                        AC_CHECK_LIB(nsl,main)
                        AC_CHECK_LIB(socket,main)
                        AC_CHECK_LIB(sun,main)
@@ -1989,33 +2129,29 @@ case "$target" in
 esac
 
 AC_CHECK_LIB(termcap,tgetent)
-if test "$ac_cv_lib_termcap_tgetent" != yes; then
+if test "x$ac_cv_lib_termcap_tgetent" != xyes; then
     AC_CHECK_LIB(curses,tgetent)
-    if test "$ac_cv_lib_curses_tgetent" != yes; then
+    if test "x$ac_cv_lib_curses_tgetent" != xyes; then
        AC_CHECK_LIB(ncurses,tgetent)
     fi
 fi
-if test "$ac_cv_lib_termcap_tgetent" = yes ||
-   test "$ac_cv_lib_curses_tgetent" = yes ||
-   test "$ac_cv_lib_ncurses_tgetent" = yes; then
-    AC_CHECK_LIB(readline,readline)
-    if test "$ac_cv_lib_readline_readline" != yes; then
+if test "x$ac_cv_lib_termcap_tgetent" = xyes ||
+   test "x$ac_cv_lib_curses_tgetent" = xyes ||
+   test "x$ac_cv_lib_ncurses_tgetent" = xyes; then
+    AC_CHECK_LIB(readline,readline,
+       READLINE_LIBS="-lreadline"; AC_SUBST(READLINE_LIBS)
+    )
+    if test "x$ac_cv_lib_readline_readline" != xyes; then
        AC_MSG_WARN([*** No readline library, no history and command line editing in amrecover!])
     fi
 else
     AC_MSG_WARN([*** No terminal library, no history and command line editing in amrecover!])
 fi
 
-if test "$ac_cv_lib_readline_readline" = yes; then
-    READLINE_LIBS=-lreadline
-    LIBS=`echo $LIBS | sed s/-lreadline//`
-    AC_SUBST(READLINE_LIBS)
-fi
-
-if test "$ac_cv_header_linux_zftape_h" = yes; then
-    if test "$ac_cv_header_vtblc_h" = yes; then
+if test "x$ac_cv_header_linux_zftape_h" = xyes; then
+    if test "x$ac_cv_header_vtblc_h" = xyes; then
         AC_CHECK_LIB(vtblc,main)
-        if test "$ac_cv_lib_vtblc_main" != yes; then
+        if test "x$ac_cv_lib_vtblc_main" != xyes; then
             AC_MSG_WARN([*** vtblc library not found - no QIC volume table support!])
         fi
     else
@@ -2116,11 +2252,11 @@ LIBS="$save_LIBS"
 
 case "$DB_STYLE" in
     db)
-       if test "$ac_cv_header_db_h" = yes; then
+       if test "x$ac_cv_header_db_h" = xyes; then
            AC_CHECK_LIB(db,main)
-           if test "$ac_cv_lib_db_main" = yes; then
+           if test "x$ac_cv_lib_db_main" = xyes; then
                AC_CHECK_LIB(db,dbm_open)
-               if test "$ac_cv_lib_db_dbm_open" = yes; then
+               if test "x$ac_cv_lib_db_dbm_open" = xyes; then
                    DB_HEADER=db.h
                    DB_LIB=db
                else
@@ -2128,7 +2264,7 @@ case "$DB_STYLE" in
                    AC_MSG_WARN([*** db database library requested but dbm_open not found in -ldb.])
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=db.h
                    DB_LIB=c
                else
@@ -2143,11 +2279,11 @@ case "$DB_STYLE" in
        ;;
 
     dbm)
-       if test "$ac_cv_header_dbm_h" = yes; then
+       if test "x$ac_cv_header_dbm_h" = xyes; then
            AC_CHECK_LIB(dbm,main)
-           if test "$ac_cv_lib_dbm_main" = yes; then
+           if test "x$ac_cv_lib_dbm_main" = xyes; then
                AC_CHECK_LIB(dbm,dbm_open)
-               if test "$ac_cv_lib_dbm_dbm_open" = yes; then
+               if test "x$ac_cv_lib_dbm_dbm_open" = xyes; then
                    DB_HEADER=dbm.h
                    DB_LIB=dbm
                else
@@ -2155,7 +2291,7 @@ case "$DB_STYLE" in
                    AC_MSG_WARN([*** dbm database library requested but dbm_open not found in -ldbm.])
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=dbm.h
                    DB_LIB=c
                else
@@ -2170,11 +2306,11 @@ case "$DB_STYLE" in
        ;;
 
     gdbm)
-       if test "$ac_cv_header_ndbm_h" = yes; then
+       if test "x$ac_cv_header_ndbm_h" = xyes; then
            AC_CHECK_LIB(gdbm,main)
-           if test "$ac_cv_lib_gdbm_main" = yes; then
+           if test "x$ac_cv_lib_gdbm_main" = xyes; then
                AC_CHECK_LIB(gdbm,dbm_open)
-               if test "$ac_cv_lib_gdbm_dbm_open" = yes; then
+               if test "x$ac_cv_lib_gdbm_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=gdbm
                else
@@ -2182,7 +2318,7 @@ case "$DB_STYLE" in
                    AC_MSG_WARN([*** gdbm database library requested but -lgdbm not found.])
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=c
                else
@@ -2197,11 +2333,11 @@ case "$DB_STYLE" in
        ;;
 
     ndbm)
-       if test "$ac_cv_header_ndbm_h" = yes; then
+       if test "x$ac_cv_header_ndbm_h" = xyes; then
            AC_CHECK_LIB(ndbm,main)
-           if test "$ac_cv_lib_ndbm_main" = yes; then
+           if test "x$ac_cv_lib_ndbm_main" = xyes; then
                AC_CHECK_LIB(ndbm,dbm_open)
-               if test "$ac_cv_lib_ndbm_dbm_open" = yes; then
+               if test "x$ac_cv_lib_ndbm_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=ndbm
                else
@@ -2209,7 +2345,7 @@ case "$DB_STYLE" in
                    AC_MSG_WARN([*** ndbm database library requested but -lndbm not found.])
                fi
            else
-               if test "$ac_cv_lib_c_dbm_open" = yes; then
+               if test "x$ac_cv_lib_c_dbm_open" = xyes; then
                    DB_HEADER=ndbm.h
                    DB_LIB=c
                else
@@ -2239,52 +2375,52 @@ if test -z "$DB_STYLE"; then
     DB_LIB=
 fi
 
-dnl if test -z "$DB_STYLE" -a "$ac_cv_header_ndbm_h" = yes; then
+dnl if test -z "$DB_STYLE" -a "x$ac_cv_header_ndbm_h" = xyes; then
 dnl     AC_CHECK_LIB(ndbm,dbm_open)
-dnl     if test "$ac_cv_lib_ndbm_dbm_open" = yes; then
+dnl     if test "x$ac_cv_lib_ndbm_dbm_open" = xyes; then
 dnl    DB_STYLE=ndbm
 dnl    DB_HEADER=ndbm.h
 dnl    DB_LIB=ndbm
-dnl     elif test "$ac_cv_lib_c_dbm_open" = yes; then
+dnl     elif test "x$ac_cv_lib_c_dbm_open" = xyes; then
 dnl    DB_STYLE=ndbm
 dnl    DB_HEADER=ndbm.h
 dnl    DB_LIB=c
 dnl    fi
 dnl fi
 dnl
-dnl if test -z "$DB_STYLE" -a "$ac_cv_header_db_h" = yes; then
+dnl if test -z "$DB_STYLE" -a "x$ac_cv_header_db_h" = xyes; then
 dnl    AC_CHECK_LIB(db,dbm_open)
-dnl    if test "$ac_cv_lib_db_dbm_open" = yes; then
+dnl    if test "x$ac_cv_lib_db_dbm_open" = xyes; then
 dnl    DB_STYLE=db
 dnl    DB_HEADER=db.h
 dnl    DB_LIB=db
-dnl    elif test "$ac_cv_lib_c_dbm_open" = yes; then
+dnl    elif test "x$ac_cv_lib_c_dbm_open" = xyes; then
 dnl    DB_STYLE=db
 dnl    DB_HEADER=db.h
 dnl    DB_LIB=c
 dnl    fi
 dnl fi
 dnl
-dnl if test -z "$DB_STYLE" -a "$ac_cv_header_dbm_h" = yes; then
+dnl if test -z "$DB_STYLE" -a "x$ac_cv_header_dbm_h" = xyes; then
 dnl    AC_CHECK_LIB(dbm,dbm_open)
-dnl    if test "$ac_cv_lib_db_dbm_open" = yes; then
+dnl    if test "x$ac_cv_lib_db_dbm_open" = xyes; then
 dnl    DB_STYLE=dbm
 dnl    DB_HEADER=dbm.h
 dnl    DB_LIB=dbm
-dnl    elif test "$ac_cv_lib_c_dbm_open" = yes; then
+dnl    elif test "x$ac_cv_lib_c_dbm_open" = xyes; then
 dnl    DB_STYLE=dbm
 dnl    DB_HEADER=dbm.h
 dnl    DB_LIB=c
 dnl    fi
 dnl fi
 dnl
-dnl if test -z "$DB_STYLE" -a "$ac_cv_header_ndbm_h" = yes; then
+dnl if test -z "$DB_STYLE" -a "x$ac_cv_header_ndbm_h" = xyes; then
 dnl    AC_CHECK_LIB(gdbm,dbm_open)
-dnl    if test "$ac_cv_lib_gdbm_dbm_open" = yes; then
+dnl    if test "x$ac_cv_lib_gdbm_dbm_open" = xyes; then
 dnl    DB_STYLE=gdbm
 dnl    DB_HEADER=ndbm.h
 dnl    DB_LIB=gdbm
-dnl    elif test "$ac_cv_lib_c_dbm_open" = yes; then
+dnl    elif test "x$ac_cv_lib_c_dbm_open" = xyes; then
 dnl    DB_STYLE=gdbm
 dnl    DB_HEADER=ndbm.h
 dnl    DB_LIB=c
@@ -2292,7 +2428,7 @@ dnl    fi
 dnl fi
 dnl
 dnl if test -z "$DB_STYLE"; then
-dnl    if test "$ac_cv_lib_c_dbm_open" = yes; then
+dnl    if test "x$ac_cv_lib_c_dbm_open" = xyes; then
 dnl    AC_MSG_WARN([*** A dbm_open() routine was found in -lc, but no header])
 dnl    AC_MSG_WARN([*** files exist.  Please remedy the situation.])
 dnl    else
@@ -2307,7 +2443,7 @@ dnl    DB_HEADER=
 dnl    DB_LIB=
 dnl fi
 
-if test "$DB_STYLE" = text; then
+if test "x$DB_STYLE" = xtext; then
     AC_DEFINE(TEXTDB,1,[Define to enable the text-based database format. ])
 else
     AC_MSG_CHECKING([for database])
@@ -2340,7 +2476,7 @@ else
                ]])],[amanda_cv_struct_datum=yes],[amanda_cv_struct_datum=no
            ])
        ])
-    if test "$amanda_cv_struct_datum" = yes; then
+    if test "x$amanda_cv_struct_datum" = xyes; then
        AC_DEFINE(HAVE_STRUCT_DATUM,1,[Define if the database header declares struct datum. ])
     fi
 fi
@@ -2362,7 +2498,7 @@ AC_CACHE_CHECK(whether _POSIX2_RE_DUP_MAX is defined,
   yes
 #endif
 ], amanda_cv_have__posix2_re_dup_max=yes, amanda_cv_have__posix2_re_dup_max=no))
-if test "$amanda_cv_have__posix2_re_dup_max" = yes; then
+if test "x$amanda_cv_have__posix2_re_dup_max" = xyes; then
     AC_DEFINE(HAVE__POSIX2_RE_DUP_MAX,1,[Define if limits.h defines _POSIX2_RE_DUP_MAX. ])
 fi
 
@@ -2374,7 +2510,7 @@ AC_CACHE_CHECK(whether CHAR_MIN is defined,
   yes
 #endif
 ], amanda_cv_have_char_min=yes, amanda_cv_have_char_min=no))
-if test "$amanda_cv_have_char_min" = yes; then
+if test "x$amanda_cv_have_char_min" = xyes; then
     AC_DEFINE(HAVE_CHAR_MIN,1,[Define if limits.h defines CHAR_MIN. ])
 fi
 
@@ -2386,7 +2522,7 @@ AC_CACHE_CHECK(whether CHAR_MAX is defined,
   yes
 #endif
 ], amanda_cv_have_char_max=yes, amanda_cv_have_char_max=no))
-if test "$amanda_cv_have_char_max" = yes; then
+if test "x$amanda_cv_have_char_max" = xyes; then
     AC_DEFINE(HAVE_CHAR_MAX,1,[Define if limits.h defines CHAR_MAX. ])
 fi
 
@@ -2398,7 +2534,7 @@ AC_CACHE_CHECK(whether CHAR_BIT is defined,
   yes
 #endif
 ], amanda_cv_have_char_bit=yes, amanda_cv_have_char_bit=no))
-if test "$amanda_cv_have_char_bit" = yes; then
+if test "x$amanda_cv_have_char_bit" = xyes; then
     AC_DEFINE(HAVE_CHAR_BIT,1,[Define if limits.h defines CHAR_BIT. ])
 fi
 
@@ -2449,6 +2585,7 @@ AC_REPLACE_FUNCS(memmove)
 ICE_CHECK_DECL(memmove,string.h strings.h)
 ICE_CHECK_DECL(memset,string.h strings.h)
 AC_CHECK_FUNCS(mkdir)
+ICE_CHECK_DECL(mkstemp,stdlib.h)
 ICE_CHECK_DECL(mktemp,stdlib.h)
 AC_REPLACE_FUNCS(mktime)
 ICE_CHECK_DECL(mktime,time.h sys/time.h)
@@ -2474,6 +2611,8 @@ ICE_CHECK_DECL(sendto,sys/types.h sys/socket.h)
 ICE_CHECK_DECL(setegid,unistd.h)
 ICE_CHECK_DECL(seteuid,unistd.h)
 AC_CHECK_FUNCS(setmntent)
+AC_CHECK_FUNCS(shquote)
+
 ICE_CHECK_DECL(setresgid,unistd.h)
 ICE_CHECK_DECL(setresuid,unistd.h)
 
@@ -2502,10 +2641,10 @@ ICE_CHECK_DECL(shmctl,sys/types.h sys/ipc.h sys/shm.h)
 ICE_CHECK_DECL(shmdt,sys/types.h sys/ipc.h sys/shm.h)
 ICE_CHECK_DECL(shmget,sys/types.h sys/ipc.h sys/shm.h)
 
-if test "$ac_cv_func_mmap_fixed_mapped" != yes; then
+if test "x$ac_cv_func_mmap_fixed_mapped" != xyes; then
     case "$FORCE_MMAP" in
     n | no)
-       if test "$ac_cv_func_shmget" != yes; then
+       if test "x$ac_cv_func_shmget" != xyes; then
            AC_MSG_WARN([*** Neither shmget() nor mmap() found!])
            AC_MSG_WARN([*** This system will not support the Amanda server.])
            NO_SERVER_MODE=true
@@ -2519,8 +2658,6 @@ if test "$ac_cv_func_mmap_fixed_mapped" != yes; then
     esac
 fi
 
-ICE_CHECK_DECL(shquote, stdlib.h)
-
 dnl Some systems have snprintf but not vsnprintf.  If either snprintf or
 dnl vsnprintf are missing, then use the snprintf.c we provide.
 ICE_CHECK_DECL(snprintf,stdio.h)
@@ -2559,14 +2696,14 @@ ICE_CHECK_DECL(vprintf,stdio.h stdlib.h)
 ICE_CHECK_DECL(vsprintf,stdio.h stdlib.h)
 AC_CHECK_FUNC(wait4)
 AC_REPLACE_FUNCS(waitpid)
+AC_REPLACE_FUNCS(writev)
+ICE_CHECK_DECL(writev, unistd.h sys/uio.h)
 AC_REPLACE_FUNCS(strcasecmp)
 ICE_CHECK_DECL(strcasecmp,string.h strings.h)
 
 AC_CHECK_FUNCS(fnmatch)
 
-if test "$ac_cv_func_fnmatch" != yes -a "$USE_QUICK_AND_DIRTY_ESTIMATES" != yes ; then
-    AC_MSG_WARN([--with-qde and no fnmatch -- gnutar exclude files will not work])
-fi
+AC_SYS_LARGEFILE
 
 dnl disk device prefixes
 AC_MSG_CHECKING(disk device prefixes)
@@ -2578,7 +2715,7 @@ dfline=`(
     df / | while read line; do
        set -- $line
        while test $# -gt 0; do
-           if test "$1" = "/"; then
+           if test "x$1" = "x/"; then
                echo $line
                break 2
            fi
@@ -2671,7 +2808,7 @@ AC_CACHE_CHECK(
 ])
     rm -f /tmp/conftest.lock
 ])
-if test "$amanda_cv_posix_filelocking" = yes; then
+if test "x$amanda_cv_posix_filelocking" = xyes; then
     AC_DEFINE(USE_POSIX_FCNTL,1,[Define to use Posix fcntl for file locking.])
     HAS_WORKING_FILE_LOCK=1
 fi
@@ -2695,7 +2832,7 @@ if test -z "$HAS_WORKING_FILE_LOCK"; then
 ])
        rm -f /tmp/conftest.lock
 ])
-    if test "$amanda_cv_flock_filelocking" = yes; then
+    if test "x$amanda_cv_flock_filelocking" = xyes; then
        AC_DEFINE(USE_FLOCK,1,[Define to use flock for file locking.])
        HAS_WORKING_FILE_LOCK=1
     fi
@@ -2720,7 +2857,7 @@ if test -z "$HAS_WORKING_FILE_LOCK"; then
 ])
        rm -f /tmp/conftest.lock
 ])
-    if test "$amanda_cv_lockf_filelocking" = yes; then
+    if test "x$amanda_cv_lockf_filelocking" = xyes; then
        AC_DEFINE(USE_LOCKF,1,[Define to use lockf for file locking.])
        HAS_WORKING_FILE_LOCK=1
     fi
@@ -2748,7 +2885,7 @@ if test -z "$HAS_WORKING_FILE_LOCK"; then
 ])
        rm -f /tmp/conftest.lock
 ])
-    if test "$amanda_cv_lnlock_filelocking" = yes; then
+    if test "x$amanda_cv_lnlock_filelocking" = xyes; then
        AC_DEFINE(USE_LNLOCK,1,[Define to use a hard-link based approach for file locking.])
        HAS_WORKING_FILE_LOCK=1
     fi
@@ -2777,6 +2914,7 @@ AM_CONDITIONAL(WANT_CHG_SCSI, test x"$NO_SCSI_CHANGER_MODE" != x"true")
 AM_CONDITIONAL(WANT_CHIO_SCSI, test x"$NO_CHIO_CHANGER_MODE" != x"true")
 AM_CONDITIONAL(WANT_RUNTIME_PSEUDO_RELOC, test x"$NEED_RUNTIME_PSEUDO_RELOC" = x"true")
 AM_CONDITIONAL(WANT_SETUID_CLIENT, test x"$NEED_SETUID_CLIENT" != x"false")
+AM_CONDITIONAL(WANT_SSH_SECURITY, test x"$SSH_SECURITY_SET" = x"true")
 
 case "${FORCE_USE_RUNDUMP-${USE_RUNDUMP}}" in
 y |  ye | yes) AC_DEFINE(USE_RUNDUMP,1,[Define to invoke rundump (setuid-root) instead of DUMP program directly. ]);;
@@ -2793,6 +2931,44 @@ AC_SUBST(LTLIBOBJS)
 LTALLOCA=`echo "$ALLOCA" | sed 's/\.'"${ac_objext}"'/\.lo/g'`
 AC_SUBST(LTALLOCA)
 
+## This stuff is needed for the documentation.
+DOC_BUILD_DATE=`date '+%d-%m-%Y'`
+AC_SUBST(DOC_BUILD_DATE)
+
+AC_ARG_WITH(xsltproc,
+    [  --without-built-manpages Do not build manpages from XML source.],
+    [ case "$withval" in
+        y | ye | yes)
+          USE_XSLTPROC=yes;;
+        n | no)
+          USE_XSLTPROC=no;;
+        *)
+          USE_XSLTPROC=yes;
+          XSLTPROC="$withval";;
+      esac
+    ],
+    [ USE_XSLTPROC=maybe; ])
+
+AC_DEFUN([AC_PATH_XSLTPROC], [AC_PATH_PROG(XSLTPROC, xsltproc)])
+
+# This looks bad, but && and || have equal precedence in shells, so
+# actually it's all OK.
+if test "$USE_XSLTPROC" = "yes" || test "$USE_XSLTPROC" = "maybe" && \
+   test -z "$XSLTPROC"; then
+    AC_PATH_XSLTPROC
+    if test -n "$XSLTPROC"; then
+        USE_XSLTPROC=yes;
+    else
+        if test "$USE_XSLTPROC" = yes; then
+           AC_MSG_ERROR([can't find xsltproc, but running with --with-xsltproc.])
+        else
+           USE_XSLTPROC=no;
+        fi
+    fi
+fi
+
+AM_CONDITIONAL(HAVE_XSLTPROC, test "$USE_XSLTPROC" = yes)
+
 AC_CONFIG_FILES([\
        amplot/amcat.awk                amplot/amplot.sh                \
        amplot/Makefile                                                 \
@@ -2807,11 +2983,12 @@ AC_CONFIG_FILES([\
                                                                        \
        client-src/patch-system.sh      client-src/Makefile             \
                                                                        \
+        dumper-src/gnutar.pl           dumper-src/generic-dumper.pl    \
+       dumper-src/Makefile                                             \
+                                                                       \
        common-src/versuff.c            common-src/Makefile             \
                                                                        \
        example/amanda.conf             example/Makefile                \
-       example/amanda.conf.chg-scsi    example/chg-scsi-linux.conf     \
-       example/chg-scsi-solaris.conf   example/chg-scsi-hpux.conf      \
        example/chg-mcutil.conf                                         \
                                                                        \
        man/Makefile                                                    \
@@ -2827,7 +3004,8 @@ AC_CONFIG_FILES([\
        server-src/amoverview.pl        server-src/amrmtape.sh          \
        server-src/amtoc.pl             server-src/amverify.sh          \
        server-src/Makefile             server-src/amstatus.pl          \
-       server-src/amverifyrun.sh                                       \
+       server-src/amverifyrun.sh       server-src/amcrypt.sh           \
+       server-src/amaespipe.sh                                         \
                                                                        \
        tape-src/Makefile                                               \
                                                                        \
diff --git a/contrib/gsc/README b/contrib/gsc/README
new file mode 100644 (file)
index 0000000..209c51c
--- /dev/null
@@ -0,0 +1,60 @@
+# $Id: README,v 1.1 2001/04/15 11:12:37 ant Exp $
+# Copyright (c) 1997 by Matthew Jacob
+#
+#      This software is free software; you can redistribute it and/or
+#      modify it under the terms of the GNU Library General Public
+#      License as published by the Free Software Foundation; version 2.
+#
+#      This software is distributed in the hope that it will be useful,
+#      but WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#      Library General Public License for more details.
+#
+#      You should have received a copy of the GNU Library General Public
+#      License along with this software; if not, write to the Free
+#      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#      The author may be reached via electronic communications at
+#
+#              mjacob@feral.com
+#
+#      or, via United States Postal Address
+#
+#              Matthew Jacob
+#              1831 Castro Street
+#              San Francisco, CA, 94131
+
+I. Installation Steps
+
+
+1. cfggsc, defgsc, ucfggsc, gsc.cat go into /usr/lib/methods
+2. gscdd goes into /usr/lib/drivers
+3. As root, do:
+
+       odmadd gsc.add
+
+II. Configuration Steps
+
+       mkdev -c generic -s scsi -t gsc -pscsiN -wT,L
+
+where N is the Nth scsi bus, T is target, L is lun.
+
+This should create a /dev/gscM for this device.
+
+You can use tstinq to run a test inquiry command.
+Use lsdev -C to see what gets configured.
+
+III. Removal steps
+
+1. Do
+       rmdev -d -l gscM
+
+for M = 0..M-1 to remove and undefine all gsc devices.
+
+2. Do, as root,
+
+       odmdelete -o PdDv -q uniquetype=generic/scsi/gsc
+
+3. Remove files installed in I. above.
+
+
diff --git a/contrib/gsc/cfggsc.c b/contrib/gsc/cfggsc.c
new file mode 100644 (file)
index 0000000..b2471cf
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * $Id: cfggsc.c,v 1.1 2001/04/15 11:12:37 ant Exp $
+ * Copyright (c) 1997 by Matthew Jacob
+ *
+ *     This software is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Library General Public
+ *     License as published by the Free Software Foundation; version 2.
+ *
+ *     This software is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Library General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Library General Public
+ *     License along with this software; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *     The author may be reached via electronic communications at
+ *
+ *             mjacob@feral.com
+ *
+ *     or, via United States Postal Address
+ *
+ *             Matthew Jacob
+ *             1831 Castro Street
+ *             San Francisco, CA, 94131
+ */
+
+
+#include <stdio.h>
+#include <sys/scsi.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/devinfo.h>
+#include <sys/device.h>
+#include <sys/cfgodm.h>
+#include <cf.h>
+#include <sys/cfgdb.h>
+#include <fcntl.h>
+#include <sys/sysconfig.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/mode.h>
+
+#include "gscdds.h"
+
+extern mid_t loadext(char *, int, int);
+
+static int verbose;
+static struct gsc_ddsinfo ddsinfo;
+
+int main(int a, char **v);
+static void check_add_sockets(dev_t, int, char *, char *);
+static int has_driver_get_vpd(char *, int, char *);
+
+#define MKNOD_MODE S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
+
+#define        vprintf if (verbose) printf
+
+
+static void
+err_exit(char exitcode)
+{
+    odm_close_class(CuDv_CLASS);
+    odm_close_class(PdDv_CLASS);
+    odm_terminate();
+    exit(exitcode);
+}
+
+int
+main(int a, char **v)
+{
+    extern char *optarg;
+    char sstring[256], bufname[256], conns[NAMESIZE], *ptr, *lname;
+    struct Class *cprp, *cusdev, *predev;
+    struct CuDvDr dpr, *dprp;
+    struct CuDv parobj, cusobj, hdobj, *xprp;
+    struct PdDv preobj;
+    struct CuAt *attrobj;
+    int rc, c, errflg, ipl_phase, unit, munit, howmany, lun, domake;
+    dev_t ctl;
+    long major;
+    int *mlist;
+    mid_t kmid;
+    struct cfg_dd dd;
+
+    lname = NULL;
+    errflg = 0;
+    ipl_phase = RUNTIME_CFG;
+    (void) memset((void *) &ddsinfo, 0, sizeof ddsinfo);
+
+    while ((c = getopt(a, v, "l:12v")) != EOF) {
+       switch (c) {
+       case 'l':
+           if (lname != NULL)
+               errflg++;
+           lname = optarg;
+           break;
+       case 'v':
+           verbose++;
+           break;
+       case '1':
+           if (ipl_phase != RUNTIME_CFG)
+               errflg++;
+           ipl_phase = PHASE1;
+           break;
+       case '2':
+           if (ipl_phase != RUNTIME_CFG)
+               errflg++;
+           ipl_phase = PHASE2;
+           break;
+       default:
+           errflg++;
+       }
+    }
+    if (errflg)
+       exit (E_ARGS);
+    if (lname == NULL)
+       exit(E_LNAME);
+
+    if (odm_initialize() == -1) {
+       return (E_ODMINIT);
+    }
+
+    /* lock the database */
+    if (odm_lock("/etc/objrepos/config_lock",0) == -1)
+       err_exit(E_ODMLOCK);
+
+    /* open customized devices object class */
+    if ((int)(cusdev = odm_open_class(CuDv_CLASS)) == -1)
+       err_exit(E_ODMOPEN);
+
+    /* search for customized object with this logical name */
+    sprintf(sstring, "name = '%s'", lname);
+    rc = (int) odm_get_first(cusdev, sstring, &cusobj);
+    if (rc == 0) {
+       /* No CuDv object with this name */
+       err_exit(E_NOCuDv);
+    } else if (rc == -1) {
+       /* ODM failure */
+       err_exit(E_ODMGET);
+    }
+
+    /* open predefined devices object class */
+    if ((int)(predev = odm_open_class(PdDv_CLASS)) == -1)
+       err_exit(E_ODMOPEN);
+
+    /* get predefined device object for this logical name */
+    sprintf(sstring, "uniquetype = '%s'", cusobj.PdDvLn_Lvalue);
+    rc = (int)odm_get_first(predev, sstring, &preobj);
+    if (rc == 0) {
+       /* No PdDv object for this device */
+       err_exit(E_NOPdDv);
+    } else if (rc == -1) {
+       /* ODM failure */
+       err_exit(E_ODMGET);
+    }
+    /* close predefined device object class */
+    if (odm_close_class(predev) == -1)
+       err_exit(E_ODMCLOSE);
+
+    if (ipl_phase != RUNTIME_CFG)
+       setleds(preobj.led);
+
+    /*
+     * Now, if the device is already configured, we're
+     * pretty much done.
+     */
+    if (cusobj.status == AVAILABLE) {
+       /* close customized device object class */
+       if (odm_close_class(cusdev) == -1)
+               err_exit(E_ODMCLOSE);
+       odm_terminate();
+       return(E_OK);
+    }
+    if (cusobj.status != DEFINED) {
+       vprintf("bad state: %d\n", cusobj.status);
+       err_exit(E_DEVSTATE);
+    }
+
+    /* get the device's parent object */
+    sprintf(sstring, "name = '%s'", cusobj.parent);
+    rc = (int) odm_get_first(cusdev, sstring, &parobj);
+    if (rc == 0) {
+       /* Parent device not in CuDv */
+       err_exit(E_NOCuDvPARENT);
+    } else if (rc == -1) {
+       /* ODM failure */
+       err_exit(E_ODMGET);
+    }
+
+    /* Parent MUST be available to continue */
+    if (parobj.status != AVAILABLE)
+       err_exit(E_PARENTSTATE);
+
+
+    /* make sure that no other devices are configured     */
+    /* at this location                                   */
+    sprintf(sstring, "parent = '%s' AND location='%s' AND status=%d",
+           cusobj.parent, cusobj.location, AVAILABLE);
+    rc = (int) odm_get_first(cusdev, sstring, &cusobj);
+    if (rc == -1) {
+       /* odm failure */
+       err_exit(E_ODMGET);
+    } else if (rc) {
+       /* Error: device config'd at this location */
+       err_exit(E_AVAILCONNECT);
+    }
+
+    memcpy(conns, cusobj.location, NAMESIZE);
+    vprintf("now fool with luns: location is %s\n", conns);
+    ptr = conns;
+    while (*ptr && ptr < &conns[NAMESIZE])
+       ptr++;
+    ptr--;
+    if (ptr < &conns[1]) {
+       err_exit(E_BADATTR);
+    }
+    lun = *ptr - '0';
+    vprintf("I see lun %d\n", lun);
+    if (lun < 0 || lun >= 8)
+       err_exit(E_INVCONNECT);
+    ddsinfo.lun = lun;
+    /*
+     * Generate Target
+     */
+    if (ptr[-1] == ',') {
+       *(--ptr) = 0;
+    } else {
+       *ptr = 0;
+    }
+    while (ptr > conns && *ptr != '-')
+       ptr--;
+    if (*ptr == '-')
+       ptr++;
+    ddsinfo.target = strtol(ptr, (char **) NULL, 0);
+    vprintf("I see tgt %d ptr = %d\n", ddsinfo.target, ptr - conns);
+
+    /*
+     * Generate dev_t for adapter
+     */
+    cprp = odm_open_class(CuDvDr_CLASS) ;
+    sprintf(sstring, "value3 = %s", cusobj.parent);
+    rc = (int) odm_get_obj(cprp, sstring, &dpr, TRUE);
+    if (rc == 0) {
+       err_exit(E_NOCuDvPARENT);
+    } else if (rc == -1) {
+       err_exit(E_ODMGET);
+    }
+    ddsinfo.busid = (dev_t) makedev(atoi(dpr.value1), atoi(dpr.value2));
+    vprintf("I see %d.%d for connecting adapter\n",
+       major(ddsinfo.busid), minor(ddsinfo.busid));
+
+    /*
+     * Get unit number out of logical name
+     */
+
+    ptr = lname;
+    ptr += strlen(preobj.prefix);
+    unit = atoi(ptr);
+    vprintf("I see %d as unit\n", unit);
+
+    /*
+     * Okay, now that we have the pertinent information that we'll
+     * need (adapter dev_t, device type, target, lbits, shareable,
+     * unit number), we can look into actually loading/configuring the
+     * current driver.
+     */
+    (void) sprintf(bufname, "/dev/%s", lname);
+
+    /*
+     * Get or generate major number..
+     */
+    if ((major = (long) genmajor(preobj.DvDr)) == -1) {
+       odm_terminate();
+       return (E_MAJORNO);
+    }
+    vprintf("major is %d\n", major);
+
+    /*
+     * Let's see if this is the first time through. If it's
+     * the first time through, getminor will return NULL
+     * or won't have any minors in the list.
+     */
+    mlist = getminor(major, &howmany, preobj.DvDr);
+    vprintf("getminor: %x and howmany %d for %s\n", mlist, howmany,
+               preobj.DvDr);
+
+    domake = 1;
+    if (mlist != NULL && howmany != 0) {
+       /*
+        * We have a list of minors already.
+        * See if we already have the minor
+        * we want defined.
+        */
+       for (c = 0; c < howmany; c++) {
+           if (mlist[c] == unit) {
+               vprintf("unit %d already has minor\n", unit);
+               domake = 0;
+               break;
+           }
+       }
+    }
+
+    if (domake) {
+       (void) unlink(bufname);
+       /*
+        * Now create the minor number that will match the unit number.
+        * We really don't care whether genminor succeeds, since
+        * we've alreay unlinked the device node.
+        */
+       mlist = genminor(preobj.DvDr, major, unit, 1, 1, 1);
+       if (mlist == (long *) NULL) {
+           err_exit(E_MINORNO);
+       }
+       vprintf("making %s as %d.%d with minor returned as %d\n",
+               bufname, major, unit, *mlist);
+       if (mknod(bufname, MKNOD_MODE, makedev(major, unit))) {
+           err_exit(E_MKSPECIAL);
+       }
+    } else {
+       (void) mknod(bufname, MKNOD_MODE, makedev(major, unit));
+    }
+
+    /*
+     * Load the driver....
+     */
+    kmid = loadext(preobj.DvDr, TRUE, FALSE);
+    if (!kmid) {
+       err_exit(E_LOADEXT);
+    }
+
+    /*
+     * And configure the driver...
+     */
+    dd.kmid = kmid;
+    dd.devno = makedev(major, unit);
+    dd.cmd = CFG_INIT;
+    dd.ddsptr = (caddr_t) &ddsinfo;
+    dd.ddslen = sizeof (ddsinfo);
+
+    if (sysconfig(SYS_CFGDD, &dd, sizeof (dd)) == CONF_FAIL) {
+       int saverr = errno;
+       /*
+        * Unload driver...
+        */
+       (void) loadext(preobj.DvDr, FALSE, FALSE);
+       switch(saverr) {
+       case ENODEV:
+               err_exit(E_WRONGDEVICE);
+               /* NOTREACHED */
+               break;
+       case EBUSY:
+               err_exit(E_AVAILCONNECT);
+               /* NOTREACHED */
+               break;
+       case EINVAL:
+       default:
+               err_exit(E_CFGINIT);
+               /* NOTREACHED */
+               break;
+       }
+    }
+
+    /* now mark the device as available */
+    cusobj.status = AVAILABLE;
+    if (odm_change_obj(CuDv_CLASS, &cusobj) == -1) {
+       /*
+        * Unconfigure driver (for this instance)...
+        */
+       dd.kmid = 0;
+       dd.ddsptr = (caddr_t) NULL;
+       dd.ddslen = (int ) 0;
+       dd.cmd = CFG_TERM;
+       (void) sysconfig(SYS_CFGDD, &dd, sizeof (dd));
+       /*
+        * Unload driver...
+        */
+       (void) loadext(preobj.DvDr, FALSE, FALSE);
+       err_exit (E_ODMUPDATE);
+    }
+
+
+    (void) odm_terminate();
+    return (E_OK);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff --git a/contrib/gsc/defgsc.c b/contrib/gsc/defgsc.c
new file mode 100644 (file)
index 0000000..fb4d733
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * $Id: defgsc.c,v 1.1 2001/04/15 11:12:37 ant Exp $
+ * Copyright (c) 1997 by Matthew Jacob
+ *
+ *     This software is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Library General Public
+ *     License as published by the Free Software Foundation; version 2.
+ *
+ *     This software is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Library General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Library General Public
+ *     License along with this software; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *     The author may be reached via electronic communications at
+ *
+ *             mjacob@feral.com
+ *
+ *     or, via United States Postal Address
+ *
+ *             Matthew Jacob
+ *             1831 Castro Street
+ *             San Francisco, CA, 94131
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/cfgdb.h>
+#include <sys/cfgodm.h>
+#include <cf.h>
+
+static const char *triple = "type = '%s' AND class = '%s' AND subclass = '%s'";
+static const char *utype =
+       "uniquetype = '%s' and connkey = '%s' and connwhere = '%s'";
+
+static void
+err_exit(char exitcode)
+{
+    odm_close_class(CuDv_CLASS);
+    odm_close_class(PdDv_CLASS);
+    odm_terminate();
+    exit(exitcode);
+}
+
+int
+main(int a, char **v)
+{
+    extern int optind;
+    extern char *optarg;
+    char *class, *subclass, *type, *parent, *connect;
+    char sstring[256], lname[256];
+    char parent_loc[LOCSIZE];
+    struct Class *cusdev;
+    struct PdDv PdDv;
+    struct PdCn PdCn;
+    struct CuDv CuDv;
+    int seqno, rc, errflg, c;
+
+    errflg = 0;
+
+    class = subclass = type = NULL;
+    parent = connect = NULL;
+
+    while ((c = getopt(a, v, "p:w:c:s:t:")) != EOF) {
+       switch (c) {
+       case 'c':
+           if (class != NULL)
+               errflg++;
+           class = optarg;
+           break;
+       case 's':
+           if (subclass != NULL)
+               errflg++;
+           subclass = optarg;
+           break;
+       case 't':
+           if (type != NULL)
+               errflg++;
+           type = optarg;
+           break;
+       case 'w':
+           if (connect != NULL)
+               errflg++;
+           connect = optarg;
+           break;
+       case 'p':
+           if (parent != NULL)
+               errflg++;
+           parent = optarg;
+           break;
+       default:
+           errflg++;
+       }
+    }
+    if (errflg) {
+       exit(E_ARGS);
+    }
+
+    /*
+     * Verify that we have the right triple and all of it specified.
+     */
+    if (class == NULL || subclass == NULL || type == NULL) {
+       exit(E_TYPE);
+    }
+    if (strcmp(class, "generic") ||
+       strcmp(subclass, "scsi") ||
+       strcmp(type, "gsc")) {
+       exit(E_TYPE);
+    }
+    /*
+     * Verify that a parent and a connection address was specified
+     */
+    if (parent == NULL || connect == NULL) {
+       exit(E_PARENT);
+    }
+
+    /*
+     * Open up ODM.
+     */
+    if (odm_initialize() == -1) {
+       exit(E_ODMINIT);
+    }
+    if (odm_lock("/etc/objrepos/config_lock", 0) == -1) {
+       err_exit(E_ODMLOCK);
+    }
+    /*
+     * Get the PreDefined Device Object
+     */
+    (void) sprintf(sstring, triple, type, class, subclass);
+    rc = (int) odm_get_first(PdDv_CLASS, sstring, &PdDv);
+    if (rc == 0) {
+       err_exit(E_NOPdDv);
+    } else if (rc == -1) {
+       err_exit(E_ODMGET);
+    }
+
+    /*
+     * Open the Customized Device data base
+     */
+    if ((int) (cusdev = odm_open_class(CuDv_CLASS)) == -1) {
+       err_exit(E_ODMOPEN);
+    }
+    /*
+     * Check parent device
+     */
+    (void) sprintf(sstring, "name = '%s'", parent);
+    rc = (int) odm_get_first(cusdev, sstring, &CuDv);
+    if (rc == 0) {
+       err_exit(E_NOCuDvPARENT);
+    } else if (rc == -1) {
+       err_exit(E_ODMGET);
+    }
+    (void) memset(parent_loc, 0, sizeof parent_loc);
+    (void) strncpy(parent_loc, CuDv.location, sizeof CuDv.location);
+    (void) sprintf(sstring, utype, CuDv.PdDvLn_Lvalue, subclass , connect);
+    rc = (int) odm_get_first(PdCn_CLASS, sstring, &PdCn);
+    if (rc == 0) {
+       err_exit(E_INVCONNECT);
+    } else if (rc == -1) {
+       err_exit(E_ODMGET);
+    }
+
+    /*
+     * Generate a name.
+     */
+
+    /* generate logical name for device */
+    if ((seqno = genseq(PdDv.prefix)) < 0) {
+       err_exit(E_MAKENAME);
+    }
+    (void) sprintf(lname, "%s%d", PdDv.prefix, seqno);
+    (void) sprintf(sstring, "name = '%s'", lname);
+    rc = (int) odm_get_first(cusdev, sstring, &CuDv);
+    if (rc == -1) {
+       err_exit(E_ODMGET);
+    } else if (rc != 0) {
+       /*
+        * Name already exists
+        */
+       err_exit(E_LNAME);
+    }
+    /* Put device name into new CuDv object */
+    (void) strcpy(CuDv.name, lname);
+
+    /*
+     * Fill in remainder of new customized device object
+     */
+
+    /*
+     * Location codes for SCSI devices consists of 4 pairs of
+     * digits separated by hyphens. The first two pairs of digits 
+     * identify the adapter's slot number. The last two pairs of
+     * digits identify the adapter connector number and the scsi
+     * connection address. As far as I can tell, there never
+     * is a non-zero value on the connector number for SCSI
+     * adapters.
+     *
+     * This is further complicated by a slight difference in
+     * this naming convention where Model 320 and Model 220
+     * machines define the parent (adapter) location as 00-00-0S,
+     * so we'll detect that variant.
+     *
+     * This can also be further complicated by the fact that
+     * connection addresses changed between AIX Release 3.2.X
+     * and AIX Release 4.X, where the trailing digit pair went
+     * from a simple two digits (Target ID adjacent to Logical
+     * Unit Number) to two digits separated by a comma. However,
+     * since that is an argument passed in via the command line,
+     * we can say, "Not our problem," and drive onwards.
+     */
+    if (strlen(parent_loc) <= 5) {
+       (void) sprintf(CuDv.location, "%s-00-%s", parent_loc, connect);
+    } else {
+       (void) sprintf(CuDv.location, "%s-%s", parent_loc, connect);
+    }
+
+    CuDv.status = DEFINED;
+    CuDv.chgstatus = PdDv.chgstatus;
+    strcpy(CuDv.ddins, PdDv.DvDr);
+    strcpy(CuDv.PdDvLn_Lvalue, PdDv.uniquetype);
+    strcpy(CuDv.parent, parent);
+    strcpy(CuDv.connwhere, connect);
+
+    if (odm_add_obj(cusdev, &CuDv) == -1) {
+       err_exit(E_ODMADD);
+    }
+    if (odm_close_class(CuDv_CLASS) == -1) {
+       err_exit(E_ODMCLOSE);
+    }
+    odm_terminate();
+    /*
+     * Device defined successfully.
+     * Print device name to stdout with a space appended.
+     */
+    fprintf(stdout, "%s ", CuDv.name);
+    exit(E_OK);
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+n * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff --git a/contrib/gsc/gsc.add b/contrib/gsc/gsc.add
new file mode 100644 (file)
index 0000000..2c0e3fb
--- /dev/null
@@ -0,0 +1,52 @@
+*
+* $Id: gsc.add,v 1.1 2001/04/15 11:12:37 ant Exp $
+* Copyright (c) 1997 by Matthew Jacob
+*
+*      This software is free software; you can redistribute it and/or
+*      modify it under the terms of the GNU Library General Public
+*      License as published by the Free Software Foundation; version 2.
+*
+*      This software is distributed in the hope that it will be useful,
+*      but WITHOUT ANY WARRANTY; without even the implied warranty of
+*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+*      Library General Public License for more details.
+*
+*      You should have received a copy of the GNU Library General Public
+*      License along with this software; if not, write to the Free
+*      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*      The author may be reached via electronic communications at
+*
+*              mjacob@feral.com
+*
+*      or, via United States Postal Address
+*
+*              Matthew Jacob
+*              1831 Castro Street
+*              San Francisco, CA, 94131
+
+PdDv:
+       class = "generic"
+       subclass = "scsi"
+       type = "gsc"
+       prefix = "gsc"
+       devid = ""
+       base = 1
+       has_vpd = 0
+       detectable = 1
+       chgstatus = 0
+       bus_ext = 0
+       fru = 1
+       led = 1234
+       catalog = "gsc.cat"
+       setno = 1
+       msgno = 1
+       DvDr        = "gscdd"
+       Define      = "/usr/lib/methods/defgsc"
+       Configure   = "/usr/lib/methods/cfggsc"
+       Change      = ""
+       Unconfigure = "/usr/lib/methods/ucfggsc"
+       Undefine    = "/usr/lib/methods/undefine"
+       Start       = ""
+       Stop        = ""
+       uniquetype = "generic/scsi/gsc"
diff --git a/contrib/gsc/gscdd.c b/contrib/gsc/gscdd.c
new file mode 100644 (file)
index 0000000..5e39a3a
--- /dev/null
@@ -0,0 +1,822 @@
+/*
+ * $Id: gscdd.c,v 1.1 2001/04/15 11:12:37 ant Exp $
+ * Copyright (c) 1996, 1997 by Matthew Jacob
+ *
+ *     This software is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Library General Public
+ *     License as published by the Free Software Foundation; version 2.
+ *
+ *     This software is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Library General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Library General Public
+ *     License along with this software; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *     The author may be reached via electronic communications at
+ *
+ *             mjacob@feral.com
+ *
+ *     or, via United States Postal Address
+ *
+ *             Matthew Jacob
+ *             1831 Castro Street
+ *             San Francisco, CA, 94131
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/sysmacros.h>
+#include <sys/syspest.h>
+#include <sys/ioctl.h>
+#include <sys/i_machine.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/devinfo.h>
+#include <sys/lockl.h>
+#include <sys/device.h>
+#include <sys/uio.h>
+#include <sys/watchdog.h>
+#include <sys/errids.h>
+#include <sys/trchkid.h>
+#include <sys/priv.h>
+#include <sys/iostat.h>
+#include <sys/bootrecord.h>
+#include <sys/scsi.h>
+#include <sys/malloc.h>
+#include <sys/sleep.h>
+#include <sys/fp_io.h>
+#include <sys/pin.h>
+#include <sys/lock_alloc.h>
+#define        DD_LOCK 37
+#include "gscdds.h"
+
+static int strlen(char *s) { char *p = s; while (*p) p++; return p - s; }
+static void memset(void *x, int val, size_t amt)
+{ char *p = (char *)x; while (--amt) *p++ = (char) val; }
+static void memcpy(void *dst, void *src, size_t amt)
+ { char *dest = dst, *source = src; while (--amt) *dest++ = *source++; }
+#define        bcopy(src, dst, nbytes) memcpy(dst, src, nbytes)
+
+/*
+ * Local Definitions
+ */
+
+#define        HKWD_GSC_DD     0x66600000
+
+#define        _COM_TRACE(b, var)      \
+       var = strlen(b); trcgenk(0, HKWD_GSC_DD, var, var, b)
+
+#define        Trace0(val, str)        \
+       if (scudebug >= val) { \
+               int icxq; \
+               _COM_TRACE(str, icxq); \
+       }
+#define        Trace1(val, fmt, arg1)  \
+       if (scudebug >= val) { \
+               int icxq; char buf[256]; \
+               (void) sprintf(buf, fmt, arg1); \
+               _COM_TRACE(buf, icxq); \
+       }
+#define        Trace2(val, fmt, arg1, arg2)    \
+       if (scudebug >= val) { \
+               int icxq; char buf[256]; \
+               (void) sprintf(buf, fmt, arg1, arg2); \
+               _COM_TRACE(buf, icxq); \
+       }
+#define        Trace3(val, fmt, arg1, arg2, arg3)      \
+       if (scudebug >= val) { \
+               int icxq; char buf[256]; \
+               (void) sprintf(buf, fmt, arg1, arg2, arg3); \
+               _COM_TRACE(buf, icxq); \
+       }
+#define        Trace4(val, fmt, arg1, arg2, arg3, arg4)        \
+       if (scudebug >= val) { \
+               int icxq; char buf[256]; \
+               (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4); \
+               _COM_TRACE(buf, icxq); \
+       }
+
+#define        Trace5(val, fmt, arg1, arg2, arg3, arg4, arg5)  \
+       if (scudebug >= val) { \
+               int icxq; char buf[256]; \
+               (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5); \
+               _COM_TRACE(buf, icxq); \
+       }
+
+#define        Trace6(val, fmt, arg1, arg2, arg3, arg4, arg5, arg6)    \
+       if (scudebug >= val) { \
+               int icxq; char buf[256]; \
+               (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); \
+               _COM_TRACE(buf, icxq); \
+       }
+
+#define        MJ_RTN(VAL)     simple_unlock(&sp->dd_lock); return (VAL)
+
+typedef struct {
+    struct sc_buf scsibuf;
+    uint index;
+} gsc_buf_t;
+
+typedef struct {
+    Simple_lock dd_lock;
+    Simple_lock buf_lock;
+    struct file *fp;           /* file pointer */
+    gsc_buf_t cbuf;
+#define        cmdbuf cbuf.scsibuf     /* buffer for command */
+    gsc_buf_t rbuf;
+#define rqsbuf rbuf.scsibuf    /* buffer for request sense */
+    dev_t dev;                 /* Adapter dev */
+    u_char tgt;                        /* target ID */
+    u_char lun;                        /* logical unit */
+    u_char isopen;             /* device is open */
+    u_char iscfg;              /* non-zero to show this as configured */
+    u_char unstart;            /* stop device on unconfigure */
+    u_char needresume;         /* needs an SC_RESUME with next command */
+} gsc_softc_t;
+
+/*
+ * External References
+ */
+extern int copyin(void *, void *, int);
+extern int copyout(void *, void *, int);
+extern int devstrat(struct buf *);
+extern int nodev(void);
+extern void setuerror(int);
+
+
+/*
+ * Device Driver Entry Points
+ */
+int gsc_config(dev_t, int, struct uio *);
+static int gsc_open(dev_t);
+static int gsc_close(dev_t);
+static int gsc_ioctl(dev_t, int, void *, ulong);
+static void gscdd_intr(struct buf *);
+
+/*
+ * Static Data
+ */
+static int scudebug = 10;
+static int nunits = 0;
+static gsc_softc_t softinfo[MAX_UNITS] = { 0 };
+lock_t config_lock = { LOCK_AVAIL };
+
+
+/*
+ * Local Function Prototypes
+ */
+
+static int gsopen(gsc_softc_t *);
+static void gsclose(gsc_softc_t *, dev_t);
+static int gsccmd(dev_t, scmd_t *, ulong);
+static int make_rqs(gsc_softc_t *, char, char *, int, int);
+
+/*
+ * Configuration Routines
+ */
+
+int
+gsc_config(dev_t devno, int cmd, struct uio * uiop)
+{
+    struct gsc_ddsinfo ddsinfo;
+    gsc_softc_t *sp;
+    int result, i, unit;
+    extern int nodev();
+    static struct devsw gsc_dsw = {
+       gsc_open,       /* entry point for open routine */
+       gsc_close,      /* entry point for close routine */
+       nodev,          /* entry point for read routine */
+       nodev,          /* entry point for write routine */
+       gsc_ioctl,      /* entry point for ioctl routine */
+       nodev,          /* entry point for strategy routine */
+       0,              /* pointer to tty device structure */
+       nodev,          /* entry point for select routine */
+       gsc_config,     /* entry point for config routine */
+       nodev,          /* entry point for print routine */
+       nodev,          /* entry point for dump routine */
+       nodev,          /* entry point for mpx routine */
+       nodev,          /* entry point for revoke routine */
+       NULL,           /* pointer to device specific data */
+       NULL,           /* select pointer */
+       DEV_MPSAFE
+    };
+
+    if (lockl(&config_lock, LOCK_SHORT) != LOCK_SUCC) {
+       return (EINVAL);
+    }
+    unit = minor(devno);
+    if (unit < 0 || unit >= MAX_UNITS) {
+       Trace2(0, "%d: bad unit %d", __LINE__, unit);
+       result = EINVAL;
+       unlockl(&config_lock);
+       return (result);
+    }
+
+    switch (cmd) {
+    case CFG_INIT:
+       Trace2(2, "CFG_INIT: unit %d nunit %d\n", unit, nunits);
+       /*
+        * Initialize softinfo, first time around.
+        */
+       if (nunits == 0) {
+           memset(softinfo, 0, sizeof (softinfo));
+       }
+       /*
+        * Copy in DDS information
+        */
+       uiomove((caddr_t) &ddsinfo, sizeof ddsinfo, UIO_WRITE, uiop);
+       sp = &softinfo[unit];
+       if (sp->iscfg) {
+           Trace1(0, "CFG_INIT: unit %d already configd", unit);
+           result = EBUSY;
+           break;
+       }
+       lock_alloc(&sp->dd_lock, LOCK_ALLOC_PIN, DD_LOCK, -1);
+       lock_alloc(&sp->buf_lock, LOCK_ALLOC_PIN, DD_LOCK, -1);
+       simple_lock_init(&sp->dd_lock);
+       sp->dev = ddsinfo.busid;
+       sp->tgt = ddsinfo.target;
+       sp->lun = ddsinfo.lun;
+       sp->cbuf.index = sp->rbuf.index = unit;
+       /*
+        * If this is the first time through:
+        *   Add entry to the device switch table to call this driver
+        *   Pin driver code.
+        */
+       if (nunits == 0) {
+           result = devswadd(devno, &gsc_dsw);
+           if (result != 0) {
+               Trace1(0, "CFG_INIT: devswadd result: %d", result);
+               break;
+           }
+           result = pincode((int (*) ()) gscdd_intr);
+           if (result) {
+               Trace1(0, "CFG_INIT: pincode result: %d", result);
+               devswdel(devno);
+               break;
+           }
+       }
+       sp->iscfg = 1;
+       result = gsopen(sp);
+       if (result) {
+           Trace2(0, "CFG_INIT: gsopen returns %d for unit %d", result, unit);
+           sp->iscfg = 0;
+           gsclose(sp, devno);
+           break;
+       }
+       if (nunits <= unit)
+           nunits = unit + 1;
+       sp->iscfg = 1;
+       break;
+
+    case CFG_TERM:
+       Trace1(2, "CFG_TERM unit %d", unit);
+       result = 0;
+       sp = &softinfo[unit];
+       if (sp->iscfg == 0) {
+           Trace1(0, "CFG_TERM: unit %d not already configd", unit);
+           result = ENXIO;
+           break;
+       } else if (sp->isopen) {
+           Trace1(0, "CFG_TERM: unit %d open", unit);
+           result = EBUSY;
+           break;
+       }
+       sp->iscfg = 0;  /* block further actions */
+       gsclose(sp, devno);
+       break;
+
+    default:
+       result = EINVAL;
+       break;
+    }
+    unlockl(&config_lock);
+    return (result);
+}
+
+/*
+ * Validate that devno is indeed for a SCSI adapter, and set up stuff for it.
+ */
+static int
+gsopen(gsc_softc_t * sp)
+{
+    struct file *fp;
+    int r;
+    struct devinfo di;
+
+    Trace2(2, "gsopen: %d.%d", major(sp->dev), minor(sp->dev));
+    sp->fp = NULL;
+    r = fp_opendev(sp->dev, DREAD|DWRITE|DKERNEL, NULL, 0, &fp);
+    if (r) {
+       Trace3(0, "%d: fp_opendev unit %d=%d", __LINE__, sp->cbuf.index, r);
+       return (r);
+    }
+    r = fp_ioctl(fp, IOCINFO, (caddr_t) &di, NULL);
+    if (r) {
+       Trace3(0, "%d: fp_ioctl unit %d=%d", __LINE__, sp->cbuf.index, r);
+       (void) fp_close(fp);
+       return (r);
+    }
+    if (di.devtype != DD_BUS || di.devsubtype != DS_SCSI) {
+       Trace2(0, "%d: not SCSI bus on unit %d", __LINE__,  sp->cbuf.index);
+       (void) fp_close(fp);
+       return (r);
+    }
+    sp->fp = fp;
+    sp->unstart = 1;
+    if (fp_ioctl(sp->fp, SCIOSTART, (caddr_t) IDLUN(sp->tgt, sp->lun), NULL)) {
+       sp->unstart = 0;
+    }
+    return (0);
+}
+
+/*
+ * Shut down a device
+ */
+static void
+gsclose(gsc_softc_t *sp, dev_t devno)
+{
+    int i;
+    if (sp->fp != NULL && sp->unstart) {
+       (void) fp_ioctl(sp->fp, SCIOSTOP, (caddr_t) IDLUN(sp->tgt, sp->lun), NULL);
+       sp->unstart = 0;
+    }
+    if (sp->fp) {
+       (void) fp_close(sp->fp);
+       sp->fp = NULL;
+    }
+    for (i = 0; i < MAX_UNITS; i++) {
+       if (softinfo[i].iscfg) {
+           Trace1(0, "gsclose: unit %d still confd", i);
+           break;
+       }
+    }
+    if (i == MAX_UNITS) {
+       Trace0(0, "gsclose: All unconfigured now");
+       (void) devswdel(devno);
+       unpincode((int (*) ()) gscdd_intr);
+    }
+}
+
+/*
+ * VFS entry points
+ */
+
+static int
+gsc_open(dev_t devno)
+{
+    gsc_softc_t *sp;
+    int unit = minor(devno);
+
+    Trace1(2, "gsc_open: open unit %d", unit);
+    if (unit < 0 || unit >= MAX_UNITS) {
+       return (ENODEV);
+    }
+    sp = &softinfo[unit];
+    if (sp->iscfg == 0 || sp->fp == NULL) {
+       Trace2(0, "%d: bad unit (%d)", __LINE__, unit);
+       return (ENODEV);
+    }
+    simple_lock(&sp->dd_lock);
+    if (sp->isopen) {
+       simple_unlock(&sp->dd_lock);
+       return (EBUSY);
+    }
+    sp->isopen = 1;
+    simple_unlock(&sp->dd_lock);
+    return (0);
+}
+
+static int
+gsc_close(dev_t dev)
+{
+    gsc_softc_t *sp;
+    int unit = minor(dev);
+
+    Trace1(2, "gsc_close: close unit %d", unit);
+    if (unit < 0 || unit >= MAX_UNITS) {
+       return (ENODEV);
+    }
+    sp = &softinfo[unit];
+    if (sp->iscfg == 0) {
+       return (ENODEV);
+    }
+    simple_lock(&sp->dd_lock);
+    sp->isopen = 0;
+    simple_unlock(&sp->dd_lock);
+    return (0);
+}
+
+static int
+gsc_ioctl(dev_t dev, int cmd, void *arg, ulong dflag)
+{
+    switch (cmd) {
+    case GSC_CMD:
+       return (gsccmd(dev, arg, dflag));
+
+    case GSC_SETDBG:
+    {
+       int i;
+       cmd = copyin(arg, (caddr_t) &i, sizeof (int));
+       if (cmd != 0) {
+           return (cmd);
+       }
+       cmd = scudebug;
+       scudebug = i;
+       return (copyout((caddr_t) &cmd, arg, sizeof (int)));
+    }
+    default:
+       return (ENOTTY);
+    }
+}
+
+
+/****************************************************************************/
+
+static int
+gsccmd(dev_t dev, scmd_t *argcmd, ulong dflag)
+{
+    gsc_softc_t *sp;
+    scmd_t local, *l;
+    char sbyte, albits;
+    struct sc_buf *usc;
+    struct buf *Ubp;
+    int r, r2, ival, upin, unit, rqvalid, once;
+
+    unit = minor(dev);
+    Trace2(1, "%d: cmd for unit %d", __LINE__, minor(dev));
+    if (unit < 0 || unit >= MAX_UNITS) {
+       setuerror(ENXIO);
+       return (ENXIO);
+    }
+    sp = &softinfo[unit];
+    if (sp->iscfg == 0 || sp->fp == NULL) {
+       Trace2(0, "gsccmd: bad unit %d (cfg=%d)", unit, sp->iscfg);
+       r = ENODEV;
+       setuerror(r);
+       return (r);
+    }
+    simple_lock(&sp->dd_lock);
+    l = &local;
+    if (dflag & DKERNEL) {
+       l = argcmd;
+    } else {
+       r = copyin((caddr_t) argcmd, (caddr_t) l, sizeof (scmd_t));
+       if (r != 0) {
+           Trace2(0, "%d: copyin=%d", __LINE__, r);
+           setuerror(r);
+           MJ_RTN (r);
+       }
+    }
+    Trace6(1, "%d: cdblen%d datalen%d snslen%d rw=%d tv=%d", __LINE__,
+          l->cdblen, l->datalen, l->senselen, l->rw, l->timeval);
+    sbyte = 0;
+    rqvalid = upin = r = r2 = 0;
+    usc = &sp->cmdbuf;
+    Ubp = &usc->bufstruct;
+    memset(usc, 0, sizeof (struct sc_buf));
+
+    /*
+     * Check some parameters...
+     */
+
+    if (l->cdblen > sizeof (struct sc_cmd)) {
+       r = EINVAL;
+       goto out;
+    }
+
+    /*
+     * Setup sc_buf structure
+     */
+    Ubp->b_iodone = gscdd_intr;
+    Ubp->b_dev = sp->dev;
+    Ubp->b_flags = B_BUSY | B_MPSAFE;
+    Ubp->b_resid = Ubp->b_bcount = l->datalen;
+    Ubp->b_xmemd.aspace_id = XMEM_INVAL;
+    Ubp->b_event = EVENT_NULL;
+
+    if (l->datalen) {
+       Ubp->b_un.b_addr = l->data_buf;
+       if (l->rw) {
+           Ubp->b_flags |= B_READ;
+       }
+       if (dflag & DKERNEL) {
+           r = pinu(l->data_buf, l->datalen, UIO_SYSSPACE);
+       } else {
+           r = pinu(l->data_buf, l->datalen, UIO_USERSPACE);
+       }
+       if (r) {
+           Trace2(0, "%d: pinu buf %d", __LINE__, r);
+           goto out;
+       }
+       upin++;
+       if (dflag & DKERNEL) {
+           r = xmattach(l->data_buf, l->datalen, &Ubp->b_xmemd, SYS_ADSPACE);
+       } else {
+           r = xmattach(l->data_buf, l->datalen, &Ubp->b_xmemd, USER_ADSPACE);
+       }
+       if (r != XMEM_SUCC) {
+           Trace2(0, "%d: xmattach %d", __LINE__, r);
+           r = EFAULT;
+           goto out;
+       }
+       upin++;
+       r = xmemdma(&Ubp->b_xmemd, l->data_buf, XMEM_UNHIDE);
+       if (r == XMEM_FAIL) {
+           Trace2(0, "%d: xmemdma %d", __LINE__, r);
+           r = EFAULT;
+           goto out;
+       }
+       r = 0;
+    }
+    usc->scsi_command.scsi_id = sp->tgt;
+    usc->scsi_command.scsi_length = l->cdblen;
+    if (dflag & DKERNEL) {
+       bcopy(l->cdb, (caddr_t)&usc->scsi_command.scsi_cmd, l->cdblen);
+    } else {
+       r = copyin(l->cdb, (caddr_t) & usc->scsi_command.scsi_cmd, l->cdblen);
+       if (r != 0) {
+           goto out;
+       }
+    }
+    /* Setting lun in SCSI CDB as well as sc_buf structure */
+    usc->lun = sp->lun;
+    usc->scsi_command.scsi_cmd.lun &= 0x1F;
+    usc->scsi_command.scsi_cmd.lun |= (sp->lun << 5) & 0xE0;
+    albits = usc->scsi_command.scsi_cmd.lun;
+    usc->timeout_value = l->timeval;
+    if (sp->needresume) {
+       usc->flags |= SC_RESUME;
+       sp->needresume = 0;
+    }
+
+    if (scudebug > 1) {
+       char *c = (char *) &usc->scsi_command.scsi_cmd;
+       char cdbuf[64];
+       (void) sprintf(cdbuf,
+                      "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "
+                      "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
+                      c[0], c[1], c[2], c[3], c[4], c[5],
+                      c[6], c[7], c[8], c[9], c[10], c[11]);
+       Trace2(0, "%d: cdb=%s", __LINE__, cdbuf);
+    }
+
+    once = 0;
+again:
+    Ubp->b_flags &= ~B_DONE;
+    r = devstrat(Ubp);
+    if (r == 0) {
+       ival = disable_lock(INTCLASS1, &sp->buf_lock);
+       while ((Ubp->b_flags & B_DONE) == 0) {
+           e_sleep_thread(&Ubp->b_event, &sp->buf_lock, LOCK_HANDLER);
+       }
+       unlock_enable(ival, &sp->buf_lock);
+    } else {
+       /*
+        * If ENXIO,  We never actually got started.
+        */
+       if (r == ENXIO && once == 0) {
+           once++;
+           usc->flags |= SC_RESUME|SC_DELAY_CMD;
+           goto again;
+       }
+       sp->needresume = 1;
+       Trace2(1, "%d: devstrat=%d", __LINE__, r);
+       goto out;
+    }
+
+    Trace4(1, "%d: b_flags %x b_error %d b_resid %d", __LINE__,
+          Ubp->b_flags, Ubp->b_error, Ubp->b_resid);
+    Trace5(1, "%d: sv %x st %x gc %x as %x", __LINE__,
+          usc->status_validity, usc->scsi_status,
+          usc->general_card_status, usc->adap_q_status);
+
+    if (Ubp->b_flags & B_ERROR) {
+       r = Ubp->b_error;
+       sp->needresume = 1;
+    }
+
+    if (usc->status_validity & SC_SCSI_ERROR) {
+       sbyte = (usc->scsi_status & SCSI_STATUS_MASK);
+       sp->needresume = 1;
+       if (sbyte == SC_CHECK_CONDITION && l->senselen) {
+           struct sc_buf *usl;
+           struct buf *Sbp;
+
+           r = make_rqs(sp, albits, l->sense_buf, l->senselen,
+                    (dflag & DKERNEL) != 0);
+           if (r) {
+               Trace2(0, "%d: make_rqs=%d", __LINE__, r);
+               goto out;
+           }
+           usl = &sp->rqsbuf;
+           Sbp = &usl->bufstruct;
+           r = devstrat(Sbp);
+           if (r == 0) {
+               ival = disable_lock(INTCLASS1, &sp->buf_lock);
+               while ((Sbp->b_flags & B_DONE) == 0) {
+                   e_sleep_thread(&Sbp->b_event, &sp->buf_lock, LOCK_HANDLER);
+               }
+               unlock_enable(ival, &sp->buf_lock);
+           } else {
+               Trace2(0, "%d:ds=%d for rqs", __LINE__, r);
+               goto out;
+           }
+           xmdetach(&Sbp->b_xmemd);
+           if (dflag & DKERNEL) {
+               (void) unpinu(l->sense_buf, l->senselen, UIO_SYSSPACE);
+           } else {
+               (void) unpinu(l->sense_buf, l->senselen, UIO_USERSPACE);
+           }
+           Trace4(1, "%d SENSE: b_flags %x b_error %d b_resid %d",
+                  __LINE__, Sbp->b_flags, Sbp->b_error,
+                  Sbp->b_resid);
+           Trace5(1, "%d: sv %x st %x gc %x as %x", __LINE__,
+                  usl->status_validity, usl->scsi_status,
+                  usl->general_card_status, usl->adap_q_status);
+           if (usl->scsi_status || usl->general_card_status) {
+               r = EIO;
+           } else {
+               rqvalid = 1;
+           }
+       }
+    }
+
+    if (usc->status_validity & SC_ADAPTER_ERROR) {
+       sp->needresume = 1;
+       Trace2(0, "%d: adapter error 0x%x", __LINE__,
+              usc->general_card_status);
+       Ubp->b_flags |= B_ERROR;
+       switch (usc->general_card_status) {
+       case SC_NO_DEVICE_RESPONSE:
+       case SC_HOST_IO_BUS_ERR:
+       case SC_SCSI_BUS_FAULT:
+       case SC_CMD_TIMEOUT:
+       case SC_ADAPTER_HDW_FAILURE:
+       case SC_ADAPTER_SFW_FAILURE:
+       case SC_FUSE_OR_TERMINAL_PWR:
+       case SC_SCSI_BUS_RESET:
+       default:
+           r = EIO;
+           break;
+       }
+    }
+
+    /*
+     * Log errors through errsave function
+     */
+    if (usc->status_validity & (SC_SCSI_ERROR|SC_ADAPTER_ERROR)) {
+       struct sc_error_log_df log;
+
+       memset(&log, 0, sizeof (log));
+       /*
+        * All errors are 'temporary unknown driver error'
+        */
+       log.error_id = ERRID_SCSI_ERR6;
+       (void) sprintf(log.resource_name, "gsc%d", unit);
+       memcpy(&log.scsi_command, &usc->scsi_command, sizeof (struct scsi));
+       log.status_validity = usc->status_validity;
+       log.scsi_status = usc->scsi_status;
+       log.general_card_status = usc->general_card_status;
+       if (rqvalid) {
+           int amt;
+           if (l->senselen > 128)
+               amt = 128;
+           else
+               amt = l->senselen;
+           (void) copyin(l->sense_buf, log.req_sense_data, amt);
+       }
+       errsave(&log, sizeof (struct sc_error_log_df));
+    }
+
+    if (dflag & DKERNEL) {
+       *l->statusp = sbyte;
+    } else {
+       r2 = copyout(&sbyte, l->statusp, 1);
+       if (r2 != 0) {
+           if (r == 0)
+               r = r2;
+           goto out;
+       }
+    }
+out:
+    if (l->datalen) {
+       if (upin > 1) {
+           xmdetach(&Ubp->b_xmemd);
+           upin--;
+       }
+       if (upin > 0) {
+           if (dflag & DKERNEL) {
+               (void) unpinu(l->data_buf, l->datalen, UIO_SYSSPACE);
+           } else {
+               (void) unpinu(l->data_buf, l->datalen, UIO_USERSPACE);
+           }
+           upin--;
+       }
+    }
+    Trace2(1, "%d: returning %d", __LINE__, r);
+    if (r)
+       setuerror(r);
+    MJ_RTN (r);
+}
+
+static int
+make_rqs(gsc_softc_t * sp, char albits, char *uaddr, int ulen, int isk)
+{
+    struct sc_buf *usl;
+    struct buf *Sbp;
+    int err, upin;
+
+    if (ulen > 255)
+       ulen = 255;
+    upin = err = 0;
+    usl = &sp->rqsbuf;
+    Sbp = &usl->bufstruct;
+    memset(usl, 0, sizeof (struct sc_buf));
+
+    Sbp->b_un.b_addr = uaddr;
+    Sbp->b_resid = Sbp->b_bcount = ulen;
+    Sbp->b_iodone = gscdd_intr;
+    Sbp->b_dev = sp->dev;
+    Sbp->b_flags = B_BUSY | B_READ | B_MPSAFE;
+    Sbp->b_event = EVENT_NULL;
+    Sbp->b_xmemd.aspace_id = XMEM_INVAL;
+
+    if (isk)
+       err = pinu(uaddr, ulen, UIO_SYSSPACE);
+    else
+       err = pinu(uaddr, ulen, UIO_USERSPACE);
+    if (err)
+       goto out;
+    upin++;
+    if (isk)
+       err = xmattach(uaddr, ulen, &Sbp->b_xmemd, SYS_ADSPACE);
+    else
+       err = xmattach(uaddr, ulen, &Sbp->b_xmemd, USER_ADSPACE);
+    if (err != XMEM_SUCC) {
+       err = EFAULT;
+       goto out;
+    }
+    upin++;
+    err = xmemdma(&Sbp->b_xmemd, Sbp->b_un.b_addr, XMEM_UNHIDE);
+    if (err == XMEM_FAIL) {
+       err = EFAULT;
+       (void) xmdetach(&Sbp->b_xmemd);
+       goto out;
+    }
+    err = 0;
+
+    usl->lun = sp->lun; /* Setting lun in sc_buf structure */
+    usl->scsi_command.scsi_id = sp->tgt;
+    usl->scsi_command.scsi_length = 6;
+    usl->scsi_command.scsi_cmd.scsi_op_code = 0x3;
+    usl->scsi_command.scsi_cmd.lun = albits & 0xE0; /*ONLY copy the lun bits*/
+    usl->scsi_command.scsi_cmd.scsi_bytes[2] = ulen;
+    usl->timeout_value = 2;
+    usl->flags = SC_RESUME;
+    sp->needresume = 0;
+
+ out:
+    if (err) {
+       if (upin > 1) {
+           xmdetach(&Sbp->b_xmemd);
+           upin--;
+       }
+       if (upin > 0) {
+           if (isk)
+               (void) unpinu(uaddr, ulen, UIO_SYSSPACE);
+           else
+               (void) unpinu(uaddr, ulen, UIO_USERSPACE);
+           upin--;
+       }
+    }
+    return (err);
+}
+
+void
+gscdd_intr(struct buf * bp)
+{
+    int lv;
+    gsc_softc_t *sp = &softinfo[((gsc_buf_t *)bp)->index];
+
+    lv = disable_lock(INTIODONE, &sp->buf_lock);
+    bp->b_flags |= B_DONE;
+    unlock_enable(lv, &sp->buf_lock);
+    e_wakeup(&bp->b_event);
+}
+/*
+ * mode: c
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff --git a/contrib/gsc/gscdds.h b/contrib/gsc/gscdds.h
new file mode 100644 (file)
index 0000000..11f8667
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * $Id: gscdds.h,v 1.1 2001/04/15 11:12:37 ant Exp $
+ * Copyright (c) 1996, 1997 by Matthew Jacob
+ *
+ *     This software is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Library General Public
+ *     License as published by the Free Software Foundation; version 2.
+ *
+ *     This software is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Library General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Library General Public
+ *     License along with this software; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *     The author may be reached via electronic communications at
+ *
+ *             mjacob@feral.com
+ *
+ *     or, via United States Postal Address
+ *
+ *             Matthew Jacob
+ *             1831 Castro Street
+ *             San Francisco, CA, 94131
+ */
+#ifndef        _gscdds_h
+#define        _gscdds_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        MAX_UNITS       64
+
+struct gsc_ddsinfo {
+    dev_t      busid;          /* dev_t for SCSI adapter */
+    char       target;         /* target */
+    char       lun;            /* logical unit */
+};
+
+/*
+ * Structure used to convey a scsi command to the driver
+ */
+
+typedef struct {
+    char *     cdb;            /* SCSI command block */
+    int        cdblen;         /* length of SCSI command block */
+    char *     data_buf;       /* pointer to data area */
+    int                datalen;        /* length of data area. Zero implies none */
+    char *     sense_buf;      /* pointer to SENSE DATA area */
+    int                senselen;       /* length of sense area. Zero implies none */
+    char *     statusp;        /* pointer to SCSI status byte */
+    int                rw;             /* direction of data transfer- 1 means read */
+    int                timeval;        /* secs to complete cmd- 0 means infinite */
+} scmd_t;
+
+
+#define        GSC_CMD         (('G' << 8) | 0)
+#define        GSC_SETDBG      (('G' << 8) | 1)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ! _gscdds_h */
+/*
+ * mode: c
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff --git a/contrib/gsc/makefile b/contrib/gsc/makefile
new file mode 100644 (file)
index 0000000..18e032c
--- /dev/null
@@ -0,0 +1,71 @@
+#
+# $Id: makefile,v 1.2 2001/08/10 17:12:22 ant Exp $
+# Copyright (c) 1997 by Matthew Jacob
+#
+#      This software is free software; you can redistribute it and/or
+#      modify it under the terms of the GNU Library General Public
+#      License as published by the Free Software Foundation; version 2.
+#
+#      This software is distributed in the hope that it will be useful,
+#      but WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#      Library General Public License for more details.
+#
+#      You should have received a copy of the GNU Library General Public
+#      License along with this software; if not, write to the Free
+#      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#      The author may be reached via electronic communications at
+#
+#              mjacob@feral.com
+#
+#      or, via United States Postal Address
+#
+#              Matthew Jacob
+#              1831 Castro Street
+#              San Francisco, CA, 94131
+
+#CC            = cc -qextchk -qlanglvl=ansi -qproto -qmaxmem=3000
+CC             = gcc
+RM             = rm -f
+DEBUG_FLAG     =
+KCFLAGS                = $(DEBUG_FLAG) -O
+CFLAGS         = $(DEBUG_FLAG) -O
+
+LDF1   =       -bI:/lib/kernex.exp -bI:/usr/lib/lowsys.exp
+#LDF2  =       -lsys -lcsys
+
+BINS   =       gscdd defgsc cfggsc ucfggsc tstinq
+DATA   =       gsc.cat
+
+
+all:   ${BINS} ${DATA}
+
+gscdd: gscdd.o
+       ${LD} -bl:$@.map -o $@ $@.o -e gsc_config ${LDF1} ${LDF2}
+
+gscdd.o:       gscdd.c gscdds.h
+       $(CC) $(KCFLAGS) -c gscdd.c -DKERNEL -D_KERNEL  -D_IBMR2
+
+cfggsc:        cfggsc.c
+       $(CC) $(CFLAGS) -o $@ -lodm -lcfg $@.c
+
+ucfggsc:       ucfggsc.c
+       $(CC) $(CFLAGS) -o $@ -lodm -lcfg $@.c
+
+defgsc:        defgsc.c
+       $(CC) $(CFLAGS) -o $@ -lodm -lcfg $@.c
+
+tstinq:        tstinq.c
+       $(CC) $(CFLAGS) -o $@ $@.c
+
+gsc.cat:       makefile
+       ${RM} /tmp/catalog_tmp
+       echo '$$set 1 Feral Software Generic SCSI Messages' > /tmp/catalog_tmp
+       echo "1 Feral Software Generic SCSI Release 1.0" >> /tmp/catalog_tmp
+       gencat $@ /tmp/catalog_tmp
+       ${RM} /tmp/catalog_tmp
+
+clean:
+       @${RM} ${BINS} ${DATA} *.map *.o
+
diff --git a/contrib/gsc/tstinq.c b/contrib/gsc/tstinq.c
new file mode 100644 (file)
index 0000000..bea4dde
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * %W% %G%
+ * $Id: tstinq.c,v 1.1 2001/04/15 11:12:37 ant Exp $
+ * Copyright (c) 1997 by Matthew Jacob
+ *
+ *     This software is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Library General Public
+ *     License as published by the Free Software Foundation; version 2.
+ *
+ *     This software is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Library General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Library General Public
+ *     License along with this software; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *     The author may be reached via electronic communications at
+ *
+ *             mjacob@feral.com
+ *
+ *     or, via United States Postal Address
+ *
+ *             Matthew Jacob
+ *             1831 Castro Street
+ *             San Francisco, CA, 94131
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "gscdds.h"
+
+static void process(char *, int);
+
+int
+main(int a, char **v)
+{
+    int fd;
+
+    while (*++v) {
+       fd = open(*v, 0);
+       if (fd < 0) {
+           perror(*v);
+           continue;
+       }
+       process(*v, fd);
+       (void) close(fd);
+    }
+    return (0);
+}
+
+static void
+process(char *name, int fd)
+{
+    scmd_t scmd;
+    char sb[32], iqd[256], sbyte, c, dt;
+    static char cdb[6] = { 0x12, 0, 0, 0, 255, 0 };
+
+    scmd.cdb = cdb;
+    scmd.cdblen = sizeof (cdb);
+    scmd.data_buf = iqd;
+    scmd.datalen = 255;
+    scmd.sense_buf = sb;
+    scmd.senselen = sizeof (sb);
+    scmd.statusp = &sbyte;
+    scmd.rw = 1;
+    scmd.timeval = 5;
+
+    if (ioctl(fd, GSC_CMD, (caddr_t) &scmd) < 0) {
+       perror("GSC_CMD");
+       return;
+    }
+    dt = iqd[0] & 0x1f;
+    c = iqd[8+28];
+    iqd[8+28] = 0;
+    (void) fprintf(stdout, "%s:%-28s|Device Type %d\n", name, &iqd[8], dt);
+}
+/*
+ * mode: c
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff --git a/contrib/gsc/ucfggsc.c b/contrib/gsc/ucfggsc.c
new file mode 100644 (file)
index 0000000..4bf7444
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * %W% %G%
+ * $Id: ucfggsc.c,v 1.1 2001/04/15 11:12:37 ant Exp $
+ * Copyright (c) 1997 by Matthew Jacob
+ *
+ *     This software is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Library General Public
+ *     License as published by the Free Software Foundation; version 2.
+ *
+ *     This software is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Library General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Library General Public
+ *     License along with this software; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *     The author may be reached via electronic communications at
+ *
+ *             mjacob@feral.com
+ *
+ *     or, via United States Postal Address
+ *
+ *             Matthew Jacob
+ *             1831 Castro Street
+ *             San Francisco, CA, 94131
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/cfgdb.h>
+#include <sys/cfgodm.h>
+#include <cf.h>
+#include <sys/sysconfig.h>
+#include <sys/sysmacros.h>
+#include <sys/device.h>
+
+#include "gscdds.h"
+
+#define        vprintf if (verbose) printf
+
+extern mid_t loadext(char *, int, int);
+
+static void
+err_exit(char exitcode)
+{
+    odm_close_class(CuDv_CLASS);
+    odm_close_class(PdDv_CLASS);
+    odm_terminate();
+    exit(exitcode);
+}
+
+int
+main(int argc, char **argv)
+{
+    char *logical_name, *ptr;
+    char sstring[256];
+    struct CuDv cudvobj;
+    struct PdDv pddvobj;
+    int rc, how_many, errflg, c, majorno, minorno, unit, verbose;
+    struct cfg_dd cfg;
+    struct cfg_load load;
+    int *minor_list;
+    extern int optind;
+    extern char *optarg;
+
+    verbose = errflg = 0;
+    logical_name = NULL;
+    while ((c = getopt(argc,argv,"vl:")) != EOF) {
+       switch (c) {
+       case 'v':
+           verbose++;
+           break;
+       case 'l':
+           if (logical_name != NULL)
+               errflg++;
+           logical_name = optarg;
+           break;
+       default:
+           errflg++;
+       }
+    }
+    if (errflg)
+       exit(E_ARGS);
+
+    if (logical_name == NULL)
+       exit(E_LNAME);
+
+    if (odm_initialize() == -1)
+       exit(E_ODMINIT);
+
+    /* Get Customized Device Object for this device */
+    sprintf(sstring,"name = '%s'",logical_name);
+    rc = (int) odm_get_first(CuDv_CLASS, sstring, &cudvobj);
+    if (rc ==  0) {
+       err_exit(E_NOCuDv);
+    } else if (rc == -1) {
+       err_exit(E_ODMGET);
+    }
+
+    if (cudvobj.status == DEFINED)
+       err_exit(E_OK);  /* already unconf'd */
+
+    /* get device's predefined object */
+    sprintf(sstring,"uniquetype = '%s'", cudvobj.PdDvLn_Lvalue);
+    rc = (int) odm_get_first(PdDv_CLASS, sstring, &pddvobj);
+    if (rc ==  0)
+       err_exit(E_NOPdDv);
+    else if (rc == -1)
+       err_exit(E_ODMGET);
+
+    /*
+     * Call sysconfig() to "terminate" the device.
+     * If fails with EBUSY, then device instance is "open",
+     * and device cannot be "unconfigured".  Any other errno
+     * returned will be ignored since we MUST unconfigure the
+     * device even if it reports some other error.
+     */
+
+    /* get major number of device */
+    majorno = genmajor(pddvobj.DvDr);
+    if (majorno == -1) {
+       return(E_MAJORNO);
+    }
+    /* get minor number */
+    minor_list = getminor(majorno, &how_many, pddvobj.DvDr);
+    if (minor_list == NULL || how_many == 0)
+       err_exit (E_MINORNO);
+    vprintf("how_many=%d\n", how_many);
+    ptr = logical_name;
+    ptr += strlen(pddvobj.prefix);
+    unit = atoi(ptr);
+    if (unit >= how_many) {
+       err_exit (E_MINORNO);
+    }
+    minorno = minor_list[unit];
+    vprintf("unit %d minorno %d\n", unit, minorno);
+
+    /* create devno for this device */
+    cfg.devno = makedev(majorno, minorno);
+    cfg.kmid = 0;
+    cfg.ddsptr = (caddr_t) NULL;
+    cfg.ddslen = (int) 0;
+    cfg.cmd = CFG_TERM;
+    if (sysconfig(SYS_CFGDD, &cfg, sizeof(struct cfg_dd)) == -1) {
+       if (errno == EBUSY)
+           err_exit(E_BUSY);
+    }
+    cfg.kmid = loadext(pddvobj.DvDr, FALSE, FALSE);
+    if (cfg.kmid == NULL)
+       err_exit(E_UNLOADEXT);
+
+    /* Change the status field of device to "DEFINED" */
+    cudvobj.status = DEFINED;
+    if (odm_change_obj(CuDv_CLASS, &cudvobj) == -1) 
+       err_exit(E_ODMUPDATE);
+
+    /*
+     * Terminate ODM
+     */
+    odm_terminate();
+    return (E_OK);
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * End:
+ */
index d299615fbf0bb664541d7b0e55fbb81869c1512b..9efbd5748b1bf5a52e36321e4369a36d282b8925 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/local/bin/perl
 # ========================================================================
-# @(#) $Id: set_prod_link.pl,v 1.1.2.1 1999/11/02 21:29:56 oliva Exp $
+# @(#) $Id: set_prod_link.pl,v 1.2 1999/11/02 21:30:10 oliva Exp $
 # ------------------------------------------------------------------------
 # $Source: /cvsroot/amanda/amanda/contrib/set_prod_link.pl,v $
 # ------------------------------------------------------------------------
@@ -23,7 +23,7 @@
 # History:
 #
 # $Log: set_prod_link.pl,v $
-# Revision 1.1.2.1  1999/11/02 21:29:56  oliva
+# Revision 1.2  1999/11/02 21:30:10  oliva
 # * contrib/set_prod_link.pl: Create the links for a configuration
 # with --with-suffix.
 #
index 53bf09e2485af982ff56302afb686b5936fa8670..b53a9551af1109ae0f2edb18a05688af49c99a70 100644 (file)
@@ -1,16 +1,31 @@
-all: sst sstest
 
-sst: sst.c
-       $(CC) -D_KERNEL -c sst.c
-       ld -r sst.o -o sst
+#
+# Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+# All Rights Reserved
+#
+#ident "@(#)Makefile   1.9     97/09/14 SMI"
+#
+
+TOP= ..
+
+include $(TOP)/Makefile.master
+
+.KEEP_STATE:
+
+MOD=sst
+
+OBJS=  sst.o
+
+MOD_CONF= $(MOD:%=%.conf)
+
+all: $(MOD)
+
+include ../Makefile.driver
+
+CFLAGS += -D$(INST) $(ENVCPPFLAGS1) $(ENVCPPFLAGS2) -DDEBUG
 
 sstest: sstest.c
-       $(CC) -o sstest sstest.c
+       $(CC) -o $(INST)/sstest $(ENVCPPFLAGS1) $(ENVCPPFLAGS2) sstest.c
 
-install: sst
-       cp sst /usr/kernel/drv
-       cp sst.conf /usr/kernel/drv
-#      echo "type=sample_driver;name=sst;minor=character\trsst\A1" >> /etc/devlink.tab
 
-clean:
-       rm sst sstest
+DDICTFLAGS += -D_USCSI
index 3c0efedd69e4ebb2a01c2d08baa59c77b1353367..e2b049398ccea6760f6852a2bab4985d2e9ae459 100644 (file)
@@ -1013,24 +1013,19 @@ sst_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
         * with extended sense data to tell us why) so do one sst_unit_ready
         * and ignore the result.
         */
-
-/* Makes no sense for chg-scsi, test unit ready is done by chg-scsi */
-/*
-
        (void) sst_unit_ready(dev);
 
        if (sst_unit_ready(dev) == 0) {
                SST_LOG(0, SST_CE_DEBUG1, "sst%d_open: not ready\n",
                    getminor(dev));
                targ->targ_state = SST_STATE_CLOSED;
-*/
+
                /*LINTED*/
-/*
                _NOTE(COMPETING_THREADS_NOW);
 
                return (EIO);
        }
-*/
+
        /*
         * Do any other initalization work here, e.g. send
         * Mode Sense/Select commands to get the target in the
index bd965a4811e87310f0200010907739aa81158cd5..6ffcd58741c7f1e844c224a686ed17a826e50c8c 100644 (file)
@@ -8,6 +8,5 @@ usr/lib/amanda/selfcheck
 usr/lib/amanda/sendbackup
 usr/lib/amanda/sendsize
 usr/lib/amanda/versionsuffix
-usr/lib/libamclient*
 usr/share/man/man8/amrecover.8.gz
 usr/sbin/amrecover
index a3caeb5971011d3022a1ff07c4e05a1e9204df86..fbf8a6c8c7307878950eec518f66cf8333e1d845 100644 (file)
@@ -5,4 +5,3 @@ amanda-client: setuid-binary usr/lib/amanda/rundump 4754 root/backup
 amanda-client: setuid-binary usr/lib/amanda/runtar 4754 root/backup
 amanda-client: maintainer-script-needs-depends-on-netbase postinst
 amanda-client: maintainer-script-needs-depends-on-netbase prerm
-amanda-client: package-name-doesnt-match-sonames libamclient-2.4.5p1
index e43c68006fc6d9762d749176954ce4762c48acb8..5b4d54afc764327b9e94d5e009e450d5d6b1d5ff 100644 (file)
@@ -1,2 +1,3 @@
 etc
 usr/lib
+usr/share/lintian/overrides
index fb5dc79d7d084939e2c240e0d402fd37dd90b573..46853e16c7dd5e890ae1612f76c75e369de41f84 100644 (file)
@@ -1 +1,2 @@
-amanda-common: package-name-doesnt-match-sonames libamtape-2.4.5p1 libamanda-2.4.5p1
+amanda-common: executable-not-elf-or-script ./usr/lib/amanda/dumper.d/generic-dumper
+amanda-common: package-name-doesnt-match-sonames librestore-2.5.0 libamanda-2.5.0 libamtape-2.5.0 libamserver-2.5.0 libamclient-2.5.0
index 2470da070645a464fec6f89c62ed9010f9c71be9..3f5ba4403cf4d188ecd0696d2ca5eef9172d1688 100644 (file)
@@ -1,4 +1,3 @@
-usr/lib/libamserver*
 usr/lib/amanda/amcat.awk
 usr/lib/amanda/amcleanupdisk
 usr/lib/amanda/amindexd
index 4f7a6b89bbe77570a8d5597196fd5f127ab14cf3..17614e9cf536d29287d398600d207c90dbc2b8f3 100644 (file)
@@ -13,4 +13,3 @@ amanda-server: non-standard-dir-perm var/log/amanda/ 0770 != 0755
 amanda-server: non-standard-dir-perm var/log/amanda/DailySet1/ 0770 != 0755
 amanda-server: maintainer-script-needs-depends-on-netbase postinst
 amanda-server: maintainer-script-needs-depends-on-netbase prerm
-amanda-server: package-name-doesnt-match-sonames libamserver-2.4.5p1
index 9f5066aa85c936b7548b040e4858c9089eca0764..36a6cac26f59be568791c9a0cf5c33fd245a942b 100644 (file)
@@ -1,3 +1,14 @@
+amanda (1:2.5.0-1) unstable; urgency=low
+
+  * new upstream version, closes: #360085
+  * add --with-maxtapeblocksize=256 to configure, to better support LTO-3
+    tapes like the HP Ultrium 960
+  * tweak packaging to handle changes in upstream makefiles, etc
+  * fix overlong line in amrestore man page synopsys
+  * move private shlibs to the amanda-common package to simplify deps
+
+ -- Bdale Garbee <bdale@gag.com>  Mon,  3 Apr 2006 00:28:17 -0700
+
 amanda (1:2.4.5p1-2) unstable; urgency=low
 
   * now that we're using it for debugging info, make sure /var/log/amanda
index 39985fa7d4c8c63be20da9b9edaef5c0a5e11c60..568080ffa27e1a1065b55f80881646497811f0ee 100644 (file)
@@ -3,7 +3,7 @@ Section: utils
 Priority: optional
 Maintainer: Bdale Garbee <bdale@gag.com>
 Build-Depends: debhelper (>= 5), dump, gnuplot, libncurses5-dev, libreadline5-dev | libreadline-dev, libtool, flex, perl, smbclient, mailx, lpr, mtx, xfsdump, po-debconf
-Standards-Version: 3.6.2.1
+Standards-Version: 3.6.2.2
 
 Package: amanda-common
 Architecture: any
index 1870dd0a38df8d31b41f26004f3d6d649cbe96f6..a25c049e57a93f16563e69dbe8729012dedc506f 100755 (executable)
@@ -11,6 +11,7 @@
 r=$(shell pwd)/debian/amanda-common
 server=$(shell pwd)/debian/amanda-server
 client=$(shell pwd)/debian/amanda-client
+common=$(shell pwd)/debian/amanda-common
 
 build: build-stamp 
 build-stamp: /sbin/dump /usr/bin/smbclient debian/po/templates.pot
@@ -27,7 +28,9 @@ build-stamp: /sbin/dump /usr/bin/smbclient debian/po/templates.pot
                --with-bsd-security --with-amandahosts \
                --with-smbclient=/usr/bin/smbclient \
                --with-debugging=/var/log/amanda \
-               --with-tcpportrange=50000,50100 --with-udpportrange=840,860
+               --with-dumperdir=/usr/lib/amanda/dumper.d \
+               --with-tcpportrange=50000,50100 --with-udpportrange=840,860 \
+               --with-maxtapeblocksize=256
        touch missing
        make CFLAGS="-O2 -g -Wall \
                -DAMANDATES_FILE='\"/var/lib/amanda/amandates\"' \
@@ -58,8 +61,7 @@ binary-arch: build
        dh_testroot
        dh_clean -k
        dh_installdirs -a
-       make install prefix=$(r)/usr bindir=$(r)/usr/sbin \
-               libexecdir=$(r)/usr/lib/amanda mandir=$(r)/usr/share/man
+       make install DESTDIR=$(r)
        install -m 644 debian/amanda.conf.in \
                $(server)/etc/amanda/DailySet1/amanda.conf
        install -m 644 debian/disklist $(server)/etc/amanda/DailySet1/disklist
@@ -104,6 +106,8 @@ binary-arch: build
                $(server)/usr/sbin/amcheck
        install -o root -g root -m 0644 debian/amanda-client.lintian \
                $(client)/usr/share/lintian/overrides/amanda-client
+       install -o root -g root -m 0644 debian/amanda-common.lintian \
+               $(common)/usr/share/lintian/overrides/amanda-common
        install -o root -g root -m 0644 debian/amanda-server.lintian \
                $(server)/usr/share/lintian/overrides/amanda-server
        dh_makeshlibs -a
index f85b1b22dabdd5b2716ab6fe178533cd8e9be1f9..7d7fcacab466bf968378eb4bdd2780b6d2915d64 100644 (file)
@@ -106,7 +106,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -118,9 +120,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -133,6 +138,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -195,10 +201,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
index 6859a2a506e3aa4a4602e61c07f0cae096d6c2a6..3b6b64b496897fff6f11f0e4d49996b2011fea6d 100644 (file)
@@ -1,10 +1,10 @@
 
- Chapter 26. Using Kerberos with AMANDA
+ Chapter 27. Using Kerberos with AMANDA
 Prev  Part V. Technical Background  Next
 
 -------------------------------------------------------------------------------
 
-Chapter 26. Using Kerberos with AMANDA
+Chapter 27. Using Kerberos with AMANDA
 
 
 AMANDA Core Team
@@ -249,5 +249,5 @@ have cross-realm authentication setup).
 -------------------------------------------------------------------------------
 
 Prev                           Up                        Next
-Chapter 25. Virtual Tape API  Home  Part VI. Historical files
+Chapter 26. Virtual Tape API  Home  Part VI. Historical files
 
index 4eb5ce610c3efceec8c3a36b4237261beac111d2..7731c94e118426415aa86f17d5c272a5ad0ea6d7 100644 (file)
@@ -1,10 +1,10 @@
 
-        Chapter 33. Y2K Compliancy
+        Chapter 33. Y2K Compliance
 Prev  Part VI. Historical files  Next
 
 -------------------------------------------------------------------------------
 
-Chapter 33. Y2K Compliancy
+Chapter 33. Y2K Compliance
 
 
 AMANDA Core Team
diff --git a/dumper-src/Makefile.am b/dumper-src/Makefile.am
new file mode 100644 (file)
index 0000000..0b4b739
--- /dev/null
@@ -0,0 +1,33 @@
+# Makefile for Amanda wrapper programs.
+
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src
+
+dumper_SCRIPTS =       gnutar generic-dumper
+dumperdir =            @DUMPER_DIR@
+
+SUFFIXES =             .sh .pl
+
+.pl:
+                       cat $< > $@
+                       chmod a+x $@
+                       -test -z "$(PERL)" || $(PERL) -c $@
+
+.sh:
+                       cat $< > $@
+                       chmod a+x $@
+
+DISTCLEANFILES = $(dumper_SCRIPTS)
+
+# these are used for testing only:
+
+install-data-hook:
+       @list="$(dumper_SCRIPTS)"; \
+       for p in $$list; do \
+               pa=$(DESTDIR)$(dumperdir)/`echo $$p|sed '$(transform)'`; \
+               echo chown $(BINARY_OWNER) $$pa; \
+               chown $(BINARY_OWNER) $$pa; \
+               echo chgrp $(SETUID_GROUP) $$pa; \
+               chgrp $(SETUID_GROUP) $$pa; \
+       done
+
diff --git a/dumper-src/Makefile.in b/dumper-src/Makefile.in
new file mode 100644 (file)
index 0000000..6379113
--- /dev/null
@@ -0,0 +1,479 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile for Amanda wrapper programs.
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = dumper-src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+       $(srcdir)/generic-dumper.pl.in $(srcdir)/gnutar.pl.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES = gnutar.pl generic-dumper.pl
+am__installdirs = "$(DESTDIR)$(dumperdir)"
+dumperSCRIPT_INSTALL = $(INSTALL_SCRIPT)
+SCRIPTS = $(dumper_SCRIPTS)
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMANDA_DBGDIR = @AMANDA_DBGDIR@
+AMANDA_DEBUG_DAYS = @AMANDA_DEBUG_DAYS@
+AMANDA_TMPDIR = @AMANDA_TMPDIR@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@
+AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@
+AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@
+AMPLOT_COMPRESS = @AMPLOT_COMPRESS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_VAR_ASSIGNMENT_OPT = @AWK_VAR_ASSIGNMENT_OPT@
+BINARY_OWNER = @BINARY_OWNER@
+CAT = @CAT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHIO = @CHIO@
+CHS = @CHS@
+CLIENT_LOGIN = @CLIENT_LOGIN@
+CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@
+COMPRESS = @COMPRESS@
+CONFIGURE_COMMAND = @CONFIGURE_COMMAND@
+CONFIG_DIR = @CONFIG_DIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DB_EXT = @DB_EXT@
+DD = @DD@
+DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@
+DEFAULT_CONFIG = @DEFAULT_CONFIG@
+DEFAULT_RAW_TAPE_DEVICE = @DEFAULT_RAW_TAPE_DEVICE@
+DEFAULT_SERVER = @DEFAULT_SERVER@
+DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
+DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
+DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GETCONF = @GETCONF@
+GNUPLOT = @GNUPLOT@
+GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
+GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
+GREP = @GREP@
+GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
+LN_S = @LN_S@
+LTALLOCA = @LTALLOCA@
+LTLIBOBJS = @LTLIBOBJS@
+MAILER = @MAILER@
+MAKEINFO = @MAKEINFO@
+MAXTAPEBLOCKSIZE = @MAXTAPEBLOCKSIZE@
+MCUTIL = @MCUTIL@
+MT = @MT@
+MTX = @MTX@
+MT_FILE_FLAG = @MT_FILE_FLAG@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCAT = @PCAT@
+PERL = @PERL@
+PRINT = @PRINT@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+RESTORE = @RESTORE@
+SAMBA_CLIENT = @SAMBA_CLIENT@
+SERVICE_SUFFIX = @SERVICE_SUFFIX@
+SETUID_GROUP = @SETUID_GROUP@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNAPSHOT_STAMP = @SNAPSHOT_STAMP@
+STRIP = @STRIP@
+USE_VERSION_SUFFIXES = @USE_VERSION_SUFFIXES@
+VDUMP = @VDUMP@
+VERSION = @VERSION@
+VERSION_COMMENT = @VERSION_COMMENT@
+VERSION_MAJOR = @VERSION_MAJOR@
+VERSION_MINOR = @VERSION_MINOR@
+VERSION_PATCH = @VERSION_PATCH@
+VERSION_SUFFIX = @VERSION_SUFFIX@
+VRESTORE = @VRESTORE@
+VXDUMP = @VXDUMP@
+VXRESTORE = @VXRESTORE@
+WANT_AMPLOT_FALSE = @WANT_AMPLOT_FALSE@
+WANT_AMPLOT_TRUE = @WANT_AMPLOT_TRUE@
+WANT_CHG_SCSI_FALSE = @WANT_CHG_SCSI_FALSE@
+WANT_CHG_SCSI_TRUE = @WANT_CHG_SCSI_TRUE@
+WANT_CHIO_SCSI_FALSE = @WANT_CHIO_SCSI_FALSE@
+WANT_CHIO_SCSI_TRUE = @WANT_CHIO_SCSI_TRUE@
+WANT_CLIENT_FALSE = @WANT_CLIENT_FALSE@
+WANT_CLIENT_TRUE = @WANT_CLIENT_TRUE@
+WANT_RECOVER_FALSE = @WANT_RECOVER_FALSE@
+WANT_RECOVER_TRUE = @WANT_RECOVER_TRUE@
+WANT_RESTORE_FALSE = @WANT_RESTORE_FALSE@
+WANT_RESTORE_TRUE = @WANT_RESTORE_TRUE@
+WANT_RUNTIME_PSEUDO_RELOC_FALSE = @WANT_RUNTIME_PSEUDO_RELOC_FALSE@
+WANT_RUNTIME_PSEUDO_RELOC_TRUE = @WANT_RUNTIME_PSEUDO_RELOC_TRUE@
+WANT_SAMBA_FALSE = @WANT_SAMBA_FALSE@
+WANT_SAMBA_TRUE = @WANT_SAMBA_TRUE@
+WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
+WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
+WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
+WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
+WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
+WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
+XFSDUMP = @XFSDUMP@
+XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
+YACC = @YACC@
+ac_c = @ac_c@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+ac_n = @ac_n@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src
+
+dumper_SCRIPTS = gnutar generic-dumper
+dumperdir = @DUMPER_DIR@
+SUFFIXES = .sh .pl
+DISTCLEANFILES = $(dumper_SCRIPTS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .sh .pl
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  dumper-src/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --gnu  dumper-src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+gnutar.pl: $(top_builddir)/config.status $(srcdir)/gnutar.pl.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+generic-dumper.pl: $(top_builddir)/config.status $(srcdir)/generic-dumper.pl.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-dumperSCRIPTS: $(dumper_SCRIPTS)
+       @$(NORMAL_INSTALL)
+       test -z "$(dumperdir)" || $(mkdir_p) "$(DESTDIR)$(dumperdir)"
+       @list='$(dumper_SCRIPTS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         if test -f $$d$$p; then \
+           f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+           echo " $(dumperSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(dumperdir)/$$f'"; \
+           $(dumperSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(dumperdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-dumperSCRIPTS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(dumper_SCRIPTS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+         echo " rm -f '$(DESTDIR)$(dumperdir)/$$f'"; \
+         rm -f "$(DESTDIR)$(dumperdir)/$$f"; \
+       done
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(SCRIPTS)
+installdirs:
+       for dir in "$(DESTDIR)$(dumperdir)"; do \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dumperSCRIPTS
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dumperSCRIPTS uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+       distclean distclean-generic distclean-libtool distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-data-hook \
+       install-dumperSCRIPTS install-exec install-exec-am \
+       install-info install-info-am install-man install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic \
+       mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+       uninstall-dumperSCRIPTS uninstall-info-am
+
+
+.pl:
+                       cat $< > $@
+                       chmod a+x $@
+                       -test -z "$(PERL)" || $(PERL) -c $@
+
+.sh:
+                       cat $< > $@
+                       chmod a+x $@
+
+# these are used for testing only:
+
+install-data-hook:
+       @list="$(dumper_SCRIPTS)"; \
+       for p in $$list; do \
+               pa=$(DESTDIR)$(dumperdir)/`echo $$p|sed '$(transform)'`; \
+               echo chown $(BINARY_OWNER) $$pa; \
+               chown $(BINARY_OWNER) $$pa; \
+               echo chgrp $(SETUID_GROUP) $$pa; \
+               chgrp $(SETUID_GROUP) $$pa; \
+       done
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/dumper-src/generic-dumper.pl.in b/dumper-src/generic-dumper.pl.in
new file mode 100644 (file)
index 0000000..ceb2235
--- /dev/null
@@ -0,0 +1,386 @@
+
+
+$command = $ARGV[0];
+if ($command eq "privilege") {
+   wrapper_privilege();
+}
+elsif ($command eq "support") {
+   wrapper_support();
+}
+elsif ($command eq "selfcheck") {
+   wrapper_selfcheck();
+}
+elsif ($command eq "estimate") {
+   wrapper_estimate();
+}
+elsif ($command eq "estimate-parse") {
+   wrapper_estimate_parse();
+}
+elsif ($command eq "backup") {
+   wrapper_backup();
+}
+elsif ($command eq "backup-parse") {
+   wrapper_backup_parse();
+}
+elsif ($command eq "index-from-output") {
+   wrapper_index_from_output();
+}
+elsif ($command eq "index-from-image") {
+   wrapper_index_from_image();
+}
+elsif ($command eq "restore") {
+   wrapper_restore();
+}
+elsif ($command eq "print-command") {
+   wrapper_print_command();
+}
+else {
+   printf STDERR "Unknown command `$command'.\n";
+   exit 1;
+}
+
+
+sub wrapper_privilege() {
+   if(defined(&command_support)) {
+      command_privilege();
+      exit 0;
+   }
+   my($subcommand) = $ARGV[1];
+   if ($subcommand eq "support") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "selfcheck") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "estimate") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "estimate-parse") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "backup") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "backup-parse") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "index-from-output") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "index-from-image") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "restore") {
+      wrapper_print_privilege($subcommand);
+   }
+   elsif ($subcommand eq "print-command") {
+      wrapper_print_privilege($subcommand);
+   }
+   else {
+      printf STDERR "Unknown command `$subcommand'.\n";
+      exit 1;
+   }
+   if(defined($user_default) && defined($group_default)) {
+      print "USER $user_default\n";
+      print "GROUP $group_default\n";
+      exit 0;
+   }
+   exit 0;
+}
+
+
+sub wrapper_print_privilege {
+   my($command) = @_;
+   $command =~ s/-/_/g;
+   my($var_user) = "user_$command";
+   my($var_group) = "group_$command";
+   if(defined($$var_user) && defined($$var_group)) {
+      print "USER $$var_user\n";
+      print "GROUP $$var_group\n";
+      exit 0;
+   }
+   elsif(defined($$var_user) && !defined($$var_group)) {
+      print STDERR "\$$var_user defined but \$$var_group not defined\n";
+      exit 1;
+   }
+   elsif(!defined($$var_user) && defined($$var_group)) {
+      print STDERR "\$$var_group defined but \$$var_user not defined\n";
+      exit 1;
+   }
+}
+
+sub wrapper_support() {
+   if(defined(&command_support)) {
+      command_support();
+      exit 0;
+   }
+   my($subcommand) = $ARGV[1];
+   if ($subcommand eq "level-incrementals") {
+      if (defined($level_incrementals)) {
+         print "$level_incrementals\n";
+      }
+      else {
+         print "1\n";
+      }
+      exit 0;
+   }
+   elsif ($subcommand eq "index") {
+      my($index_generation);
+      foreach $index_generation (@index_generation) {
+         if( $index_generation eq "direct" ||
+             $index_generation eq "parse"  ||
+             $index_generation eq "output" ||
+             $index_generation eq "image") {
+                print "$index_generation\n";
+         }
+         else {
+            print "unknow indexing method '$index_generation'\n";
+         }
+      }
+   exit 0;
+   }
+   elsif ($subcommand eq "parse-estimate") {
+      my($parse_estimate);
+      foreach $parse_estimate (@parse_estimate) {
+         if( $parse_estimate eq "direct" ||
+             $parse_estimate eq "parse" ) {
+            print "$parse_estimate\n";
+         }
+         else {
+            print "unknow parse-estimate method '$parse_estimate'\n";
+         }
+      }
+   exit 0;
+   }
+   elsif ($subcommand eq "parse-backup") {
+      print "direct\n" if (defined($parse_backup_direct));
+      print "parse\n"  if (defined($parse_backup_parse));
+      my($parse_backup);
+      foreach $parse_backup (@parse_backup) {
+         if( $parse_backup eq "direct" ||
+             $parse_backup eq "parse" ) {
+            print "$parse_backup\n";
+         }
+         else {
+            print "unknow parse-backup method '$parse_backup'\n";
+         }
+      }
+      exit 0;
+   }
+   else {
+      exit 1;
+   }
+}
+
+sub wrapper_selfcheck() {
+   if(defined(&command_selfcheck)) {
+      command_selfcheck();
+   }
+   else {
+      exit 1;
+   }
+}
+
+sub wrapper_estimate() {
+   my($estimate_type) = $ARGV[1];
+   my($option);
+   my($estimate_type_is_ok) = 0;
+   my($backups_type);
+   foreach $backups_type (@backup_type) {
+      $estimate_type_is_ok = 1 if($estimate_type eq $backups_type);
+   }
+   if($estimate_type_is_ok == 0) {
+      print "estimate type `$estimate_type' not supported.\n";
+      exit 3;
+   }
+   $option = 3 if ($estimate_type eq "full");
+   $option = 4 if ($estimate_type eq "level");
+   $option = 4 if ($estimate_type eq "diff");
+   parse_options($option);
+   if($option_estimate_direct + $option_estimate_parse > 1) {
+      print "Can't define both `estimate-direct' and `estimate-parse'.\n";
+      exit 5;
+   }
+   elsif($option_estimate_direct + $option_estimate_parse == 0) {
+      print "You must have the option `estimate-direct' or `estimate-parse'.\n";
+      exit 5;
+   }
+   if($estimate_type eq "full") {
+      command_estimate_full($ARGV[2]);
+   }
+    elsif($estimate_type eq "level") {
+      command_estimate_level($ARGV[2], $ARGV[3]);
+   }
+   elsif($estimate_type eq "diff") {
+      command_estimate_diff($ARGV[2], $ARGV[3]);
+   }
+}
+
+sub wrapper_estimate_parse() {
+   if(defined(&command_estimate_parse)) {
+      command_estimate_parse();
+   }
+   else {
+      printf STDERR "`estimate-parse' is not supported.\n";
+      exit 1;
+   }
+}
+
+sub wrapper_backup() {
+   my($backup_type) = $ARGV[1];
+   my($option);
+   my($backup_type_is_ok) = 0;
+   my($backups_type);
+   foreach $backups_type (@backup_type) {
+      $backup_type_is_ok = 1 if($backup_type eq $backups_type);
+   }
+   if($backup_type_is_ok == 0) {
+      print "backup type `$backup_type' not supported.\n";
+      exit 3;
+   }
+   $option = 3 if ($backup_type eq "full");
+   $option = 4 if ($backup_type eq "level");
+   $option = 4 if ($backup_type eq "diff");
+   parse_options($option);
+   if($option_backup_direct + $option_backup_parse > 1) {
+      print "Can't define both `backup-direct' and `backup-parse'.\n";
+      exit 5;
+   }
+   elsif($option_backup_direct + $option_backup_parse == 0) {
+      print "You must have the option `backup-direct' or `backup-parse'.\n";
+      exit 5;
+   }
+   if($backup_type eq "full") {
+      command_backup_full($ARGV[2]);
+   }
+   elsif($backup_type eq "level") {
+      command_backup_level($ARGV[2], $ARGV[3]);
+   }
+   elsif($backup_type eq "diff") {
+      command_backup_diff($ARGV[2], $ARGV[3]);
+   }
+}
+
+sub wrapper_backup_parse() {
+   if(defined(&command_backup_parse)) {
+      command_backup_parse();
+   }
+   else {
+      printf STDERR "`backup-parse' is not supported.\n";
+      exit 1;
+   }
+}
+
+sub wrapper_index_from_output() {
+   if(defined(&command_index_from_output)) {
+      command_index_from_output();
+   }
+   else {
+      printf STDERR "`index-from-output' is not supported.\n";
+      exit 1;
+   }
+}
+
+sub wrapper_index_from_image() {
+   if(defined(&command_index_from_image)) {
+      command_index_from_image();
+   }
+   else {
+      printf STDERR "command `index-from-image' is not supported.\n";
+      exit 1;
+   }
+}
+
+sub wrapper_restore() {
+   if(defined(&command_restore)) {
+      command_restore();
+   }
+   else {
+     printf STDERR "`restore' is not supported.\n";
+     exit 1;
+   }
+}
+
+sub wrapper_print_command() {
+   if(defined(&command_print_command)) {
+      command_print_command();
+   }
+   else {
+      printf STDERR "`print-command' is not supported.\n";
+      exit 1;
+   }
+}
+
+
+sub parse_options() {
+   my($no_option) = @_;
+   my($options, @options, $option, $name, $option_name, $value);
+
+   while($no_option <= $#ARGV) {
+      $options = $ARGV[${no_option}];
+      @options = split (/;/,$options);
+      foreach $option (@options) {
+         if( $option =~ /=/ ) {
+            ($name,$value) = split(/=/,$option);
+         }
+         else {
+            $name  = $option;
+            $value = 1;
+         }
+         $option_name = "option_$name";
+         $option_name =~ s/\-/\_/g;
+        $$option_name = $value;
+      }
+      $no_option++;
+   }
+}
+
+sub check_file {
+   my($filename, $mode) = @_;
+
+   stat($filename);
+
+   if($mode eq "e") {
+      if( -e _ ) {
+         print "OK $filename exists\n";
+      }
+      else {
+         print "ERROR [can not find $filename]\n";
+      }
+   }
+   elsif($mode eq "x") {
+      if( -x _ ) {
+         print "OK $filename executable\n";
+      }
+      else {
+         print "ERROR [can not execute $filename]\n";
+      }
+   }
+   elsif($mode eq "r") {
+      if( -r _ ) {
+         print "OK $filename readable\n";
+      }
+      else {
+         print "ERROR [can not read $filename]\n";
+      }
+   }
+   elsif($mode eq "w") {
+      if( -w _ ) {
+         print "OK $filename writable\n";
+      }
+      else {
+         print "ERROR [can not write $filename]\n";
+      }
+   }
+   else {
+      print "ERROR [check_file: unknow mode $mode]\n";
+   }
+}
+
+sub check_dir {
+}
+
+sub check_suid {
+}
+
+1;
diff --git a/dumper-src/gnutar.pl.in b/dumper-src/gnutar.pl.in
new file mode 100644 (file)
index 0000000..b5c7e6a
--- /dev/null
@@ -0,0 +1,318 @@
+#!@PERL@
+#
+
+# Run perl.
+eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}'
+       & eval 'exec @PERL@ -S $0 $argv:q'
+               if 0;
+
+$debug=1;
+push(@INC, "@DUMPER_DIR@");
+
+use File::Copy;
+use IPC::Open3;
+use Sys::Hostname;
+
+
+open(DEBUG,">>@AMANDA_DBGDIR@/gnutar.$$.debug") if ($debug==1);
+
+$prefix='@prefix@';
+$exec_prefix="@exec_prefix@";
+$libexecdir="@libexecdir@";
+$USE_VERSION_SUFFIXES='@USE_VERSION_SUFFIXES@';
+$suf = '';
+if ( $USE_VERSION_SUFFIXES =~ /^yes$/i ) {
+   $suf='-@VERSION@';
+}
+
+$host = hostname;
+$host =~ s/\..*$//;
+$runtar="${libexecdir}/runtar${suf}";
+$gnulist = '@GNUTAR_LISTED_INCREMENTAL_DIR@';
+$gnutar = $runtar;
+
+
+
+$level_incrementals = 9;
+
+@index_generation = ("direct","parse","output","image");
+@parse_estimate   = ("direct","parse");
+@parse_backup     = ("direct","parse");
+@backup_type      = ("full","level","diff");
+
+
+#$user_support  = "";
+#$group_support = "";
+
+#$user_selfcheck  = "";
+#$group_selfcheck = "";
+
+#$user_estimate  = "";
+#$group_estimate = "";
+
+#$user_estimate_parse  = "";
+#$group_estimate_parse = "";
+
+$user_backup  = "root";
+#$group_backup = "";
+
+#$user_backup_parse  = "";
+#$group_backup_parse = "";
+
+#$user_index_from_output  = "";
+#$group_index_from_output = "";
+
+#$user_index_from_image  = "";
+#$group_index_from_image = "";
+
+#$user_restore  = "";
+#$group_restore = "";
+
+#$user_print_command  = "";
+#$group_print_command = "";
+
+$user_default  = "amanda";
+$group_default = "amanda";
+
+
+sub command_selfcheck {
+print DEBUG "STDOUT: OK selfcheck\n" if ($debug == 1);
+   print "OK selfcheck\n";
+}
+
+sub command_estimate_full {
+   my($disk)    = @_;
+   command_estimate_level(0, $disk);
+}
+
+sub command_estimate_level {
+   my($level, $disk) = @_;
+   my($listdir) = "$host$disk";
+   $listdir     =~ s/\//_/g;
+   if($level == 0) {
+      open(GNULIST, ">${gnulist}/${listdir}_${level}.new") || die();
+      close(GNULIST) || die();
+   }
+   else {
+      my($prev_level) = $level - 1;
+      copy("${gnulist}/${listdir}_${prev_level}", "${gnulist}/${listdir}_${level}.new");
+   }
+   if($option_estimate_direct == 1) {
+      command_estimate_opt_direct($disk, $level, $listdir);
+   }
+   else {
+      command_estimate_opt_parse($disk, $level, $listdir);
+   }
+}
+
+#sub command_estimate_diff {
+#}
+
+sub command_estimate_opt_direct {
+   my($disk, $level, $listdir) = @_;
+   my($size) = -1;
+print DEBUG "$gnutar --create --directory $disk --listed-incremental ${gnulist}/${listdir}_${level}.new --sparse --one-file-system --ignore-failed-read --totals --file /dev/null .\n" if ($debug == 1);
+   open3(\*WTRFH, '>&STDOUT', \*ESTIMATE, "$gnutar --create --directory $disk --listed-incremental ${gnulist}/${listdir}_${level}.new --sparse --one-file-system --ignore-failed-read --totals --file /dev/null .") || die();
+
+   $size = parse_estimate(ESTIMATE);
+   close(ESTIMATE);
+   output_size($size);
+   unlink "${gnulist}/${listdir}_${level}.new";
+   exit 0;
+}
+
+sub command_estimate_opt_parse {
+   my($disk, $level, $listdir) = @_;
+
+   open3(\*WTRFH, '>&STDOUT',\*ESTIMATE,"$gnutar --create --directory $disk --listed-incremental ${gnulist}/${listdir}_${level}.new --sparse --one-file-system --ignore-failed-read --totals --file /dev/null .");
+
+   while (<ESTIMATE>) {
+print DEBUG "READ: $_" if ($debug == 1);
+print DEBUG "STDOUT: $_" if ($debug == 1);
+      print $_;
+   }
+   close(ESTIMATE);
+   close(WTRFH);
+
+   unlink "${gnulist}/${listdir}_${level}.new";
+}
+
+sub command_estimate_parse {
+   my($size) = parse_estimate(STDIN);
+   output_size($size);
+   exit 0;
+}
+
+sub parse_estimate {
+   my($fh) = @_;
+   my($size) = -1;
+   while(<$fh>) {
+print DEBUG "READ: $_" if ($debug == 1);
+      if ($_ =~ /^Total bytes written: (\d*)$/) {
+         $size = $1;
+         last;
+      }
+   }
+   return $size;
+}
+
+sub output_size {
+   my($size) = @_;
+   if($size == -1) {
+print DEBUG "STDOUT: -1 -1\n" if ($debug == 1);
+      print "-1 -1\n";
+      exit 2;
+   }
+   else {
+      my($ksize) = $size / 1024;
+print DEBUG "STDOUT: $ksize 1024\n" if ($debug == 1);
+      print "$ksize 1024\n";
+   }
+}
+
+sub command_backup_full {
+   my($disk)    = @_;
+   command_backup_level(0, $disk);
+}
+
+sub command_backup_level {
+   my($level, $disk) = @_;
+   my($listdir) = "$host$disk";
+   my($verbose) = "";
+   $listdir     =~ s/\//_/g;
+
+   if($level == 0) {
+      open(GNULIST, ">${gnulist}/${listdir}_${level}.new") || die();
+      close(GNULIST) || die();
+   }
+   else {
+      my($prev_level) = $level - 1;
+      copy("${gnulist}/${listdir}_${prev_level}", 
+           "${gnulist}/${listdir}_${level}.new");
+   }
+
+   if($option_index_direct == 1 || $option_index_parse == 1) {
+      $verbose = "--verbose";
+   }
+   my($cmd) = "$gnutar --create $verbose --directory $disk --listed-incremental ${gnulist}/${listdir}_${level}.new --sparse --one-file-system --ignore-failed-read --totals --file - .";
+
+   if($option_backup_parse == 1 && $option_index_direct == 0 &&
+                                   $option_index_parse  == 0) {
+      system($cmd);
+   }
+   else {
+      open3(\*WTRFH, '>&STDOUT', \*INDEX, $cmd) || die();
+
+      if($option_index_direct == 1 || $option_index_parse == 1) {
+         open(INDEXOUT, '>&=3') || die();
+         parse_backup(INDEX, STDERR, INDEXOUT);
+         close(INDEXOUT);
+      }
+      else {
+         parse_backup(INDEX, STDERR, undef);
+      }
+      close(INDEX);
+      close(WTRFH);
+   }
+
+   if(!defined($option_no_record)) {
+      rename "${gnulist}/${listdir}_${level}.new", 
+             "${gnulist}/${listdir}_${level}";
+   }
+   else {
+      unlink "${gnulist}/${listdir}_${level}.new";
+   }
+   exit 0;
+}
+
+#sub command_backup_diff {
+#}
+
+sub command_backup_parse {
+   $option_backup_direct = 1;
+   $option_backup_parse  = 0;
+   parse_backup(STDIN, STDOUT, undef);
+   exit 0;
+}
+
+sub parse_backup {
+   my($fhin, $fhout, $indexout) = @_;
+   my($size) = -1;
+   while(<$fhin>) {
+print DEBUG "READ: $_" if ($debug == 1);
+      if ( /^\.\//) {
+         if(defined($indexout)) {
+           if($option_index_direct == 1) {
+               s/^\.//;
+print DEBUG "INDEXOUT: $_" if ($debug == 1);
+               print $indexout $_;
+           }
+           elsif($option_index_parse == 1) {
+print DEBUG "INDEXOUT: $_" if ($debug == 1);
+               print $indexout $_;
+            }
+         }
+      }
+      else {
+         if (/^Total bytes written: (\d*)$/) {
+            $size = $1;
+           if(defined($fhout) && $option_backup_parse == 1) {
+print DEBUG "FHOUT: $_" if ($debug == 1);
+              print $fhout $_;
+           }
+         }
+         elsif(defined($fhout)) {
+            if($option_backup_direct == 1) {
+print DEBUG "FHOUT: $_" if ($debug == 1);
+               print $fhout $_;
+            }
+            elsif($option_backup_parse == 1) {
+print DEBUG "FHOUT: $_" if ($debug == 1);
+               print $fhout $_;
+            }
+         }
+      }
+   }
+   if(defined($fhout) && $option_backup_direct == 1) {
+      if ($size == -1) {
+print DEBUG "FHOUT: $command -1 -1\n" if ($debug == 1);
+         print $fhout "$command -1 -1\n";
+      }
+      else {
+         my($ksize) = $size/1024;
+print DEBUG "FHOUT: $ksize 1024\n" if ($debug == 1);
+         print $fhout "$ksize 1024\n";
+      }
+   }
+}
+
+sub command_index_from_output {
+   index_from_output(STDIN, STDOUT);
+   exit 0;
+}
+
+sub index_from_output {
+   my($fhin, $fhout) = @_;
+   my($size) = -1;
+   while(<$fhin>) {
+print DEBUG "READ: $_" if ($debug == 1);
+      next if /^Total bytes written:/;
+      next if !/^\.\//;
+      s/^\.//;
+print DEBUG "FHOUT: $_" if ($debug == 1);
+      print $fhout $_;
+   }
+}
+
+sub command_index_from_image {
+   open(INDEX, "$gnutar --list --file - |") || die();
+   index_from_output(INDEX, STDOUT);
+}
+
+#sub command_restore {
+#}
+
+sub command_print_command {
+}
+
+require "generic-dumper"
index 1d1cd56cc23457e271a225936d4cd119cd72bf1a..397e009ccf48db7f79591003fe76fbfa808a9d26 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for sample configuration files
 
-noinst_DATA = amanda.conf amanda.conf.chg-scsi
+noinst_DATA = amanda.conf
 
 EXTRA_DIST =   chg-multi.conf chg-scsi.conf config.site disklist \
                DLT.ps EXB-8500.ps HP-DAT.ps 8.5x11.ps 3hole.ps DIN-A4.ps \
index db659ba1fd7db64c59d67b8e731f6a38c8deb758..0c04058ea0fcf8c2e9ac80115c1501d2b7610972 100644 (file)
@@ -41,10 +41,7 @@ host_triplet = @host@
 target_triplet = @target@
 subdir = example
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
-       $(srcdir)/amanda.conf.chg-scsi.in $(srcdir)/amanda.conf.in \
-       $(srcdir)/chg-mcutil.conf.in $(srcdir)/chg-scsi-hpux.conf.in \
-       $(srcdir)/chg-scsi-linux.conf.in \
-       $(srcdir)/chg-scsi-solaris.conf.in
+       $(srcdir)/amanda.conf.in $(srcdir)/chg-mcutil.conf.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
        $(top_srcdir)/configure.in
@@ -52,9 +49,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/config/config.h
-CONFIG_CLEAN_FILES = amanda.conf amanda.conf.chg-scsi \
-       chg-scsi-linux.conf chg-scsi-solaris.conf chg-scsi-hpux.conf \
-       chg-mcutil.conf
+CONFIG_CLEAN_FILES = amanda.conf chg-mcutil.conf
 SOURCES =
 DIST_SOURCES =
 DATA = $(noinst_DATA)
@@ -106,7 +101,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -118,9 +115,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -133,6 +133,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -195,10 +196,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -249,7 +253,7 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-noinst_DATA = amanda.conf amanda.conf.chg-scsi
+noinst_DATA = amanda.conf
 EXTRA_DIST = chg-multi.conf chg-scsi.conf config.site disklist \
                DLT.ps EXB-8500.ps HP-DAT.ps 8.5x11.ps 3hole.ps DIN-A4.ps \
                chg-mcutil.conf
@@ -288,14 +292,6 @@ $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 amanda.conf: $(top_builddir)/config.status $(srcdir)/amanda.conf.in
        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-amanda.conf.chg-scsi: $(top_builddir)/config.status $(srcdir)/amanda.conf.chg-scsi.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-chg-scsi-linux.conf: $(top_builddir)/config.status $(srcdir)/chg-scsi-linux.conf.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-chg-scsi-solaris.conf: $(top_builddir)/config.status $(srcdir)/chg-scsi-solaris.conf.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-chg-scsi-hpux.conf: $(top_builddir)/config.status $(srcdir)/chg-scsi-hpux.conf.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 chg-mcutil.conf: $(top_builddir)/config.status $(srcdir)/chg-mcutil.conf.in
        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 
diff --git a/example/amanda.conf.chg-scsi.in b/example/amanda.conf.chg-scsi.in
deleted file mode 100644 (file)
index a4cefc0..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-###  !!! WARNING !!!  !!! WARNING !!!  !!! WARNING !!!  !!! WARNING !!!  ###
-###                                                                      ###
-###  This file is not meant to be installed "as is", and in fact, it     ###
-###  WILL NOT WORK!  You must go through it and make changes appropriate ###
-###  to your own situation.  See the documentation in this file, in the  ###
-###  "man amanda" man page, in the "docs" directory and at the Amanda    ###
-###  web page (www.amanda.org).                                          ###
-###                                                                      ###
-###  !!! WARNING !!!  !!! WARNING !!!  !!! WARNING !!!  !!! WARNING !!!  ###
-
-#
-# amanda.conf - sample Amanda configuration file.  This started off life as
-#               the actual config file in use at CS.UMD.EDU.
-#
-# If your configuration is called, say, "csd", then this file normally goes
-# in @CONFIG_DIR@/csd/amanda.conf.
-#
-
-org "@DEFAULT_CONFIG@"         # your organization name for reports
-mailto "@CLIENT_LOGIN@"                # space separated list of operators at your site
-dumpuser "@CLIENT_LOGIN@"      # the user to run dumps under
-
-inparallel 4           # maximum dumpers that will run in parallel (max 63)
-                       # this maximum can be increased at compile-time,
-                       # modifying MAX_DUMPERS in server-src/driverio.h
-netusage  600 Kbps     # maximum net bandwidth for Amanda, in KB per sec
-
-dumpcycle 4 weeks      # the number of days in the normal dump cycle
-runspercycle 20         # the number of amdump runs in dumpcycle days
-                       # (4 weeks * 5 amdump runs per week -- just weekdays)
-tapecycle 25 tapes     # the number of tapes in rotation
-                       # 4 weeks (dumpcycle) times 5 tapes per week (just
-                       # the weekdays) plus a few to handle errors that
-                       # need amflush and so we do not overwrite the full
-                       # backups performed at the beginning of the previous
-                       # cycle
-### ### ###
-# WARNING: don't use `inf' for tapecycle, it's broken!
-### ### ###
-
-bumpsize 20 Mb         # minimum savings (threshold) to bump level 1 -> 2
-bumpdays 1             # minimum days at each level
-bumpmult 4             # threshold = bumpsize * bumpmult^(level-1)
-
-etimeout 300           # number of seconds per filesystem for estimates.
-#etimeout -600         # total number of seconds for estimates.
-# a positive number will be multiplied by the number of filesystems on
-# each host; a negative number will be taken as an absolute total time-out.
-# The default is 5 minutes per filesystem.
-
-dtimeout 1800          # number of idle seconds before a dump is aborted.
-
-ctimeout 30            # maximum number of seconds that amcheck waits
-                       # for each client host
-tapebufs 20
-# A positive integer telling taper how many 32k buffers to allocate.
-# WARNING! If this is set too high, taper will not be able to allocate
-# the memory and will die.  The default is 20 (640k).
-
-
-# Specify tape device and/or tape changer.  If you don't have a tape
-# changer, and you don't want to use more than one tape per run of
-# amdump, just comment out the definition of tpchanger.
-
-# Some tape changers require tapedev to be defined; others will use
-# their own tape device selection mechanism.  Some use a separate tape
-# changer device (changerdev), others will simply ignore this
-# parameter.  Some rely on a configuration file (changerfile) to
-# obtain more information about tape devices, number of slots, etc;
-# others just need to store some data in files, whose names will start
-# with changerfile.  For more information about individual tape
-# changers, read docs/TAPE.CHANGERS.
-
-# At most one changerfile entry must be defined; select the most
-# appropriate one for your configuration.  If you select man-changer,
-# keep the first one; if you decide not to use a tape changer, you may
-# comment them all out.
-
-runtapes 1             # number of tapes to be used in a single run of amdump
-tpchanger "chg-scsi"   # the tape-changer glue script
-tapedev "0"    # the no-rewind tape device to be used
-changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/chg-scsi.conf"
-
-tapetype HP-DAT                # what kind of tape it is (see tapetypes below)
-labelstr "^@DEFAULT_CONFIG@[0-9][0-9]*$"       # label constraint regex: all tapes must match
-
-# Specify holding disks.  These are used as a temporary staging area for
-# dumps before they are written to tape and are recommended for most sites.
-# The advantages include: tape drive is more likely to operate in streaming
-# mode (which reduces tape and drive wear, reduces total dump time); multiple
-# dumps can be done in parallel (which can dramatically reduce total dump time.
-# The main disadvantage is that dumps on the holding disk need to be flushed
-# (with amflush) to tape after an operating system crash or a tape failure.
-# If no holding disks are specified then all dumps will be written directly
-# to tape.  If a dump is too big to fit on the holding disk than it will be
-# written directly to tape.  If more than one holding disk is specified then
-# they will all be used based on activity and available space.
-
-holdingdisk hd1 {
-    comment "main holding disk"
-    directory "/dumps/amanda"  # where the holding disk is
-    use 290 Mb         # how much space can we use on it
-                       # a non-positive value means:
-                       #        use all space but that value
-    chunksize 1Gb      # size of chunk if you want big dump to be
-                       # dumped on multiple files on holding disks
-                       #  N Kb/Mb/Gb split images in chunks of size N
-                       #             The maximum value should be
-                       #             (MAX_FILE_SIZE - 1Mb)
-                       #  0          same as INT_MAX bytes
-    }
-#holdingdisk hd2 {
-#    directory "/dumps2/amanda"
-#    use 1000 Mb
-#    }
-#holdingdisk hd3 {
-#    directory "/mnt/disk4"
-#    use 1000 Mb
-#    }
-
-
-# If amanda cannot find a tape on which to store backups, it will run
-# as many backups as it can to the holding disks.  In order to save
-# space for unattended backups, by default, amanda will only perform
-# incremental backups in this case, i.e., it will reserve 100% of the
-# holding disk space for the so-called degraded mode backups.
-# However, if you specify a different value for the `reserve'
-# parameter, amanda will not degrade backups if they will fit in the
-# non-reserved portion of the holding disk.
-
-# reserve 30 # percent
-# This means save at least 30% of the holding disk space for degraded
-# mode backups.  
-
-# The format for a ColumnSpec is a ',' seperated list of triples.
-# Each triple consists of
-#   + the name of the column (as in ColumnNameStrings)
-#   + prefix before the column
-#   + the width of the column, if set to -1 it will be recalculated
-#     to the maximum length of a line to print.
-# Example:
-#      "Disk=1:17,HostName=1:10,OutKB=1:7"
-# or
-#      "Disk=1:-1,HostName=1:10,OutKB=1:7"
-#        
-# You need only specify those colums that should be changed from
-# the default. If nothing is specified in the configfile, the
-# above compiled in values will be in effect, resulting in an
-# output as it was all the time.
-# The names of the colums are:
-# HostName, Disk, Level, OrigKB, OutKB, Compress, DumpTime, DumpRate,
-# TapeTime and TapeRate.
-#                                                      ElB, 1999-02-24.
-# columnspec "Disk=1:18,HostName=0:10,OutKB=1:7"
-
-
-# Amanda needs a few Mb of diskspace for the log and debug files,
-# as well as a database.  This stuff can grow large, so the conf directory
-# isn't usually appropriate.  Some sites use /usr/local/var and some /usr/adm.
-# Create an amanda directory under there.  You need a separate infofile and
-# logdir for each configuration, so create subdirectories for each conf and
-# put the files there.  Specify the locations below.
-
-# Note that, although the keyword below is infofile, it is only so for
-# historic reasons, since now it is supposed to be a directory (unless
-# you have selected some database format other than the `text' default)
-infofile "/usr/adm/amanda/@DEFAULT_CONFIG@/curinfo"    # database DIRECTORY
-logdir   "/usr/adm/amanda/@DEFAULT_CONFIG@"            # log directory
-indexdir "/usr/adm/amanda/@DEFAULT_CONFIG@/index"      # index directory
-#tapelist "/usr/adm/amanda/@DEFAULT_CONFIG@/tapelist"  # list of used tapes
-# tapelist is stored, by default, in the directory that contains amanda.conf
-
-
-# tapetypes
-
-# Define the type of tape you use here, and use it in "tapetype"
-# above.  Some typical types of tapes are included here.  The tapetype
-# tells amanda how many MB will fit on the tape, how big the filemarks
-# are, and how fast the tape device is.
-
-# A filemark is the amount of wasted space every time a tape section
-# ends.  If you run `make tapetype' in tape-src, you'll get a program
-# that generates tapetype entries, but it is slow as hell, use it only
-# if you really must and, if you do, make sure you post the data to
-# the amanda mailing list, so that others can use what you found out
-# by searching the archives.
-
-# For completeness Amanda should calculate the inter-record gaps too,
-# but it doesn't.  For EXABYTE and DAT tapes this is ok.  Anyone using
-# 9 tracks for amanda and need IRG calculations?  Drop me a note if
-# so.
-
-# If you want amanda to print postscript paper tape labels
-# add a line after the comment in the tapetype of the form
-#    lbl-templ "/path/to/postscript/template/label.ps"
-
-# if you want the label to go to a printer other than the default
-# for your system, you can also add a line above for a different
-# printer. (i usually add that line after the dumpuser specification)
-
-# dumpuser "operator"     # the user to run dumps under
-# printer "mypostscript"  # printer to print paper label on
-
-# here is an example of my definition for an EXB-8500
-
-# define tapetype EXB-8500 {
-# ...
-#     lbl-templ "/usr/local/amanda/config/lbl.exabyte.ps"
-# }
-
-
-define tapetype QIC-60 {
-    comment "Archive Viper"
-    length 60 mbytes
-    filemark 100 kbytes                # don't know a better value
-    speed 100 kbytes           # dito
-}
-
-define tapetype DEC-DLT2000 {
-    comment "DEC Differential Digital Linear Tape 2000"
-    length 15000 mbytes
-    filemark 8 kbytes
-    speed 1250 kbytes
-}
-
-# goluboff@butch.Colorado.EDU
-# in amanda-users (Thu Dec 26 01:55:38 MEZ 1996)
-define tapetype DLT {
-    comment "DLT tape drives"
-    length 20000 mbytes                # 20 Gig tapes
-    filemark 2000 kbytes       # I don't know what this means
-    speed 1536 kbytes          # 1.5 Mb/s
-}
-
-define tapetype SURESTORE-1200E {
-    comment "HP AutoLoader"
-    length 3900 mbytes
-    filemark 100 kbytes
-    speed 500 kbytes
-}
-
-define tapetype EXB-8500 {
-    comment "Exabyte EXB-8500 drive on decent machine"
-    length 4200 mbytes
-    filemark 48 kbytes
-    speed 474 kbytes                   
-}
-
-define tapetype EXB-8200 {
-    comment "Exabyte EXB-8200 drive on decent machine"
-    length 2200 mbytes
-    filemark 2130 kbytes
-    speed 240 kbytes                   
-}
-
-define tapetype HP-DAT {
-    comment "DAT tape drives"
-    # data provided by Rob Browning <rlb@cs.utexas.edu>
-    length 1930 mbytes
-    filemark 111 kbytes
-    speed 468 kbytes
-}
-
-define tapetype DAT {
-    comment "DAT tape drives"
-    length 1000 mbytes         # these numbers are not accurate
-    filemark 100 kbytes                # but you get the idea
-    speed 100 kbytes
-}
-
-define tapetype MIMSY-MEGATAPE {
-    comment "Megatape (Exabyte based) drive through Emulex on Vax 8600"
-    length 2200 mbytes
-    filemark 2130 kbytes
-    speed 170 kbytes           # limited by the Emulex bus interface, ugh
-}
-
-
-# dumptypes
-#
-# These are referred to by the disklist file.  The dumptype specifies
-# certain parameters for dumping including:
-#   auth       - authentication scheme to use between server and client.
-#                Valid values are "bsd" and "krb4".  Default: [auth bsd]
-#   comment    - just a comment string
-#   comprate   - set default compression rate.  Should be followed by one or
-#                two numbers, optionally separated by a comma.  The 1st is
-#                the full compression rate; the 2nd is the incremental rate.
-#                If the second is omitted, it is assumed equal to the first.
-#                The numbers represent the amount of the original file the
-#                compressed file is expected to take up.
-#                Default: [comprate 0.50, 0.50]
-#   compress   - specify compression of the backed up data.  Valid values are:
-#                "none"        - don't compress the dump output.
-#                "client best" - compress on the client using the best (and
-#                                probably slowest) algorithm.
-#                "client fast" - compress on the client using fast algorithm.
-#                "server best" - compress on the tape host using the best (and
-#                                probably slowest) algorithm.
-#                "server fast" - compress on the tape host using a fast
-#                                algorithm.  This may be useful when a fast
-#                                tape host is backing up slow clients.
-#                Default: [compress client fast]
-#   dumpcycle  - set the number of days in the dump cycle, ie, set how often a
-#                full dump should be performed.  Default: from DUMPCYCLE above
-#   exclude    - specify files and directories to be excluded from the dump.
-#                Useful with gnutar only; silently ignored by dump and samba.
-#                Valid values are:
-#                "pattern"       - a shell glob pattern defining which files
-#                                  to exclude.
-#                                  gnutar gets --exclude="pattern"
-#                list "filename" - a file (on the client!) containing patterns
-#                                  re's (1 per line) defining which files to
-#                                  exclude.
-#                                  gnutar gets --exclude-from="filename"
-#                Note that the `full pathname' of a file within its
-#                filesystem starts with `./', because of the way amanda runs
-#                gnutar: `tar -C $mountpoint -cf - --lots-of-options .' (note
-#                the final dot!)  Thus, if you're backing up `/usr' with a
-#                diskfile entry like ``host /usr gnutar-root', but you don't
-#                want to backup /usr/tmp, your exclude list should contain
-#                the pattern `./tmp', as this is relative to the `/usr' above.
-#                Please refer to the man-page of gnutar for more information.
-#                If a relative pathname is specified as the exclude list,
-#                it is searched from within the directory that is
-#                going to be backed up.
-#                Default: include all files
-#   holdingdisk        - should the holding disk be used for this dump.  Useful for
-#                dumping the holding disk itself.  Default: [holdingdisk yes]
-#   ignore     - do not back this filesystem up.  Useful for sharing a single
-#                disklist in several configurations.
-#   index      - keep an index of the files backed up.  Default: [index no]
-#   kencrypt   - encrypt the data stream between the client and server.
-#                Default: [kencrypt no]
-#   maxdumps   - max number of concurrent dumps to run on the client.
-#                Default: [maxdumps 1]
-#   priority   - priority level of the dump.  Valid levels are "low", "medium"
-#                or "high".  These are really only used when Amanda has no
-#                tape to write to because of some error.  In that "degraded
-#                mode", as many incrementals as will fit on the holding disk
-#                are done, higher priority first, to insure the important
-#                disks are at least dumped.  Default: [priority medium]
-#   program    - specify the dump system to use.  Valid values are "DUMP" and
-#                "GNUTAR".  Default: [program "DUMP"].
-#   record     - record the dump in /etc/dumpdates.  Default: [record yes]
-#   skip-full  - skip the disk when a level 0 is due, to allow full backups
-#                outside Amanda, eg when the machine is in single-user mode.
-#   skip-incr  - skip the disk when the level 0 is NOT due.  This is used in
-#                archive configurations, where only full dumps are done and
-#                the tapes saved.
-#   starttime  - delay the start of the dump?  Default: no delay
-#   strategy   - set the dump strategy.  Valid strategies are currently:
-#                "standard" - the standard one.
-#                "nofull"   - do level 1 dumps every time.  This can be used,
-#                             for example, for small root filesystems that
-#                             only change slightly relative to a site-wide
-#                             prototype.  Amanda then backs up just the
-#                             changes.
-#                "noinc"    - do level 0 dumps every time.
-#                             Unfortunately, this is not currently
-#                             implemented.  Use `dumpcycle 0'
-#                             instead.
-#                "skip"     - skip all dumps.  Useful for sharing a single
-#                             disklist in several configurations.
-#                "incronly" - do only incremental dumps. This is similar
-#                              to strategy 'nofull', but will increase
-#                              the dump level as usual. Full dumps will
-#                              only be performed when an 'amadmin force' 
-#                              has been issued 
-#                Default: [strategy standard]
-#
-# Note that you may specify previously defined dumptypes as a shorthand way
-# of defining parameters.
-
-define dumptype global {
-    comment "Global definitions"
-    # This is quite useful for setting global parameters, so you don't have
-    # to type them everywhere.  All dumptype definitions in this sample file
-    # do include these definitions, either directly or indirectly.
-    # There's nothing special about the name `global'; if you create any
-    # dumptype that does not contain the word `global' or the name of any
-    # other dumptype that contains it, these definitions won't apply.
-    # Note that these definitions may be overridden in other
-    # dumptypes, if the redefinitions appear *after* the `global'
-    # dumptype name.
-    # You may want to use this for globally enabling or disabling
-    # indexing, recording, etc.  Some examples:
-    # index yes
-    # record no
-}
-
-define dumptype always-full {
-    global
-    comment "Full dump of this filesystem always"
-    compress none
-    priority high
-    dumpcycle 0
-}
-
-define dumptype root-tar {
-    global
-    program "GNUTAR"
-    comment "root partitions dumped with tar"
-    compress none
-    index
-    exclude list "/usr/local/lib/amanda/exclude.gtar"
-    priority low
-}
-
-define dumptype user-tar {
-    root-tar
-    comment "user partitions dumped with tar"
-    priority medium
-}
-
-define dumptype high-tar {
-    root-tar
-    comment "partitions dumped with tar"
-    priority high
-}
-
-define dumptype comp-root-tar {
-    root-tar
-    comment "Root partitions with compression"
-    compress client fast
-}
-
-define dumptype comp-user-tar {
-    user-tar
-    compress client fast
-}
-
-define dumptype holding-disk {
-    global
-    comment "The master-host holding disk itself"
-    holdingdisk no # do not use the holding disk
-    priority medium
-}
-
-define dumptype comp-user {
-    global
-    comment "Non-root partitions on reasonably fast machines"
-    compress client fast
-    priority medium
-}
-
-define dumptype nocomp-user {
-    comp-user
-    comment "Non-root partitions on slow machines"
-    compress none
-}
-
-define dumptype comp-root {
-    global
-    comment "Root partitions with compression"
-    compress client fast
-    priority low
-}
-
-define dumptype nocomp-root {
-    comp-root
-    comment "Root partitions without compression"
-    compress none
-}
-
-define dumptype comp-high {
-    global
-    comment "very important partitions on fast machines"
-    compress client best
-    priority high
-}
-
-define dumptype nocomp-high {
-    comp-high
-    comment "very important partitions on slow machines"
-    compress none
-}
-
-define dumptype nocomp-test {
-    global
-    comment "test dump without compression, no /etc/dumpdates recording"
-    compress none
-    record no
-    priority medium
-}
-
-define dumptype comp-test {
-    nocomp-test
-    comment "test dump with compression, no /etc/dumpdates recording"
-    compress client fast
-}
-
-# network interfaces
-#
-# These are referred to by the disklist file.  They define the attributes
-# of the network interface that the remote machine is accessed through.
-# Notes: - netusage above defines the attributes that are used when the
-#          disklist entry doesn't specify otherwise.
-#        - the values below are only samples.
-#        - specifying an interface does not force the traffic to pass
-#          through that interface.  Your OS routing tables do that.  This
-#          is just a mechanism to stop Amanda trashing your network.
-# Attributes are:
-#      use             - bandwidth above which amanda won't start
-#                        backups using this interface.  Note that if
-#                        a single backup will take more than that,
-#                        amanda won't try to make it run slower!
-
-define interface local {
-    comment "a local disk"
-    use 1000 kbps
-}
-
-define interface le0 {
-    comment "10 Mbps ethernet"
-    use 400 kbps
-}
-
-# You may include other amanda configuration files, so you can share
-# dumptypes, tapetypes and interface definitions among several
-# configurations.
-
-#includefile "/usr/local/amanda.conf.main"
index b8b68e155613d73831ed54ce53b1b5eda1ec9997..1baa5095eeb9cb6e8ca4fc756d80a194ac61a94c 100644 (file)
@@ -107,15 +107,21 @@ runtapes 1                # number of tapes to be used in a single run of amdump
 tpchanger "chg-manual" # the tape-changer glue script
 tapedev "@DEFAULT_TAPE_DEVICE@"        # the no-rewind tape device to be used
 rawtapedev "@DEFAULT_RAW_TAPE_DEVICE@" # the raw device to be used (ftape only)
-changerfile "/usr/adm/amanda/@DEFAULT_CONFIG@/changer"
-changerfile "/usr/adm/amanda/@DEFAULT_CONFIG@/changer-status"
+#changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/changer"
+#changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/changer-status"
 changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/changer.conf"
 changerdev "@DEFAULT_CHANGER_DEVICE@"
 
+# If you want Amanda to automatically label any non-Amanda tapes it
+# encounters, uncomment the line below. Note that this will ERASE any
+# non-Amanda tapes you may have, and may also ERASE any near-failing tapes.
+# Use with caution.
+## label_new_tapes "@DEFAULT_CONFIG@-%%%"
+
 maxdumpsize -1         # Maximum number of bytes the planner will schedule
                        # for a run (default: runtapes * tape_length).
 tapetype HP-DAT                # what kind of tape it is (see tapetypes below)
-labelstr "^@DEFAULT_CONFIG@[0-9][0-9]*$"       # label constraint regex: all tapes must match
+labelstr "^@DEFAULT_CONFIG@-[0-9][0-9]*$"      # label constraint regex: all tapes must match
 
 amrecover_do_fsf yes           # amrecover will call amrestore with the
                                # -f flag for faster positioning of the tape.
@@ -211,13 +217,12 @@ autoflush no #
 # Note that, although the keyword below is infofile, it is only so for
 # historic reasons, since now it is supposed to be a directory (unless
 # you have selected some database format other than the `text' default)
-infofile "/usr/adm/amanda/@DEFAULT_CONFIG@/curinfo"    # database DIRECTORY
-logdir   "/usr/adm/amanda/@DEFAULT_CONFIG@"            # log directory
-indexdir "/usr/adm/amanda/@DEFAULT_CONFIG@/index"      # index directory
-#tapelist "/usr/adm/amanda/@DEFAULT_CONFIG@/tapelist"  # list of used tapes
+infofile "@CONFIG_DIR@/@DEFAULT_CONFIG@/curinfo"       # database DIRECTORY
+logdir   "@CONFIG_DIR@/@DEFAULT_CONFIG@"               # log directory
+indexdir "@CONFIG_DIR@/@DEFAULT_CONFIG@/index" # index directory
+#tapelist "@CONFIG_DIR/@DEFAULT_CONFIG@/tapelist"      # list of used tapes
 # tapelist is stored, by default, in the directory that contains amanda.conf
 
-
 # tapetypes
 
 # Define the type of tape you use here, and use it in "tapetype"
@@ -252,7 +257,7 @@ indexdir "/usr/adm/amanda/@DEFAULT_CONFIG@/index"   # index directory
 
 # define tapetype EXB-8500 {
 # ...
-#     lbl-templ "/usr/local/amanda/config/lbl.exabyte.ps"
+#     lbl-templ "@CONFIG_DIR@/config/lbl.exabyte.ps"
 # }
 
 
@@ -328,7 +333,8 @@ define tapetype MIMSY-MEGATAPE {
 # These are referred to by the disklist file.  The dumptype specifies
 # certain parameters for dumping including:
 #   auth       - authentication scheme to use between server and client.
-#                Valid values are "bsd" and "krb4".  Default: [auth bsd]
+#                Valid values are "bsd", "krb4", "krb5" and "ssh".  
+#                Default: [auth bsd]
 #   comment    - just a comment string
 #   comprate   - set default compression rate.  Should be followed by one or
 #                two numbers, optionally separated by a comma.  The 1st is
@@ -342,11 +348,19 @@ define tapetype MIMSY-MEGATAPE {
 #                "client best" - compress on the client using the best (and
 #                                probably slowest) algorithm.
 #                "client fast" - compress on the client using fast algorithm.
+#                "client custom" - compress using your custom client compression program.
+#                                  use client_custom_compress "PROG" to specify
+#                                  the custom compression program.
+#                                  PROG must not contain white space.
 #                "server best" - compress on the tape host using the best (and
 #                                probably slowest) algorithm.
 #                "server fast" - compress on the tape host using a fast
 #                                algorithm.  This may be useful when a fast
 #                                tape host is backing up slow clients.
+#                "server custom" - compress using your server custom compression program.
+#                                  use server_custom_compress "PROG" to specify
+#                                  the custom compression program.
+#                                  PROG must not contain white space.
 #                Default: [compress client fast]
 #   dumpcycle  - set the number of days in the dump cycle, ie, set how often a
 #                full dump should be performed.  Default: from DUMPCYCLE above
@@ -361,6 +375,19 @@ define tapetype MIMSY-MEGATAPE {
 #                              it takes only a few seconds but the result is not 
 #                              accurate if your disk usage changes from day to day.
 #                Default: [client]
+#   encrypt     - specify encryption of the backed up data. Valid values are:
+#                "none"   - don't encrypt the dump output.
+#                "client" - encrypt on the client using the program specified by 
+#                            client_encrypt "PROG".
+#                           Use client_decrypt_option to specify the decrypt- 
+#                            parameter, default is "-d".
+#                            PROG and decrypt-parameter must not contain white space.     
+#                "server" - encrypt on the server using the program specified by 
+#                            server_encrypt "PROG".
+#                            Use server_decrypt_option to specify the decrypt- 
+#                            parameter, default is "-d".
+#                            PROG and decrypt-parameter must not contain white space.
+#                 Default: [none]
 #   exclude    - specify files and directories to be excluded from the dump.
 #                Useful with gnutar only; silently ignored by dump and samba.
 #                Valid values are:
@@ -422,9 +449,6 @@ define tapetype MIMSY-MEGATAPE {
 #                             prototype.  Amanda then backs up just the
 #                             changes.
 #                "noinc"    - do level 0 dumps every time.
-#                             Unfortunately, this is not currently
-#                             implemented.  Use `dumpcycle 0'
-#                             instead.
 #                "skip"     - skip all dumps.  Useful for sharing a single
 #                             disklist in several configurations.
 #                "incronly" - do only incremental dumps. This is similar
@@ -433,9 +457,28 @@ define tapetype MIMSY-MEGATAPE {
 #                              only be performed when an 'amadmin force' 
 #                              has been issued 
 #                Default: [strategy standard]
+# tape_splitsize - (optional) split dump file into pieces of a specified size.
+#                This allows dumps to be spread across multiple tapes, and can
+#                potentially make more efficient use of tape space.  Note that
+#                if this value is too large (more than half the size of the
+#                average dump being split), substantial tape space can be
+#                wasted.  If too small, large dumps will be split into
+#                innumerable tiny dumpfiles, adding to restoration complexity.
+#                A good rule of thumb, usually, is 1/10 of the size of your
+#                tape.  Default: [disabled]
+# split_diskbuffer - (optional) When dumping a split dump  in  PORT-WRITE
+#                 mode (usually meaning "no holding disk"), buffer the split
+#                chunks to a file in the directory specified by this option.
+#                Default: [none]
+# fallback_splitsize - (optional) When dumping a split dump  in  PORT-WRITE
+#                 mode, if no split_diskbuffer is specified (or if we somehow
+#                 fail to use our split_diskbuffer), we must buffer split
+#                 chunks in memory.  This specifies the maximum size split
+#                 chunks can be in this scenario, and thus the maximum amount
+#                 of memory consumed for in-memory splitting.  Default: [10m]
 #
-# Note that you may specify previously defined dumptypes as a shorthand way
-# of defining parameters.
+# Note that you may specify previously defined dumptypes as a shorthand way of
+# defining parameters.
 
 define dumptype global {
     comment "Global definitions"
@@ -452,6 +495,8 @@ define dumptype global {
     # indexing, recording, etc.  Some examples:
     # index yes
     # record no
+    # split_diskbuffer "/raid/amanda"
+    # fallback_splitsize 64m
 }
 
 define dumptype always-full {
@@ -468,7 +513,7 @@ define dumptype root-tar {
     comment "root partitions dumped with tar"
     compress none
     index
-    exclude list "/usr/local/lib/amanda/exclude.gtar"
+#   exclude list "@CONFIG_DIR@/exclude.gtar"
     priority low
 }
 
@@ -478,6 +523,13 @@ define dumptype user-tar {
     priority medium
 }
 
+define dumptype user-tar-span {
+    root-tar
+    tape_splitsize 3 Gb
+    comment "tape-spanning user partitions dumped with tar"
+    priority medium
+}
+
 define dumptype high-tar {
     root-tar
     comment "partitions dumped with tar"
@@ -495,6 +547,11 @@ define dumptype comp-user-tar {
     compress client fast
 }
 
+define dumptype comp-user-tar-span {
+    user-tar-span
+    compress client fast
+}
+
 define dumptype holding-disk {
     global
     comment "The master-host holding disk itself"
@@ -509,12 +566,26 @@ define dumptype comp-user {
     priority medium
 }
 
+define dumptype comp-user-span {
+    global
+    tape_splitsize 5 Gb
+    comment "Tape-spanning non-root partitions on reasonably fast machines"
+    compress client fast
+    priority medium
+}
+
 define dumptype nocomp-user {
     comp-user
     comment "Non-root partitions on slow machines"
     compress none
 }
 
+define dumptype nocomp-user-span {
+    comp-user-span
+    comment "Tape-spanning non-root partitions on slow machines"
+    compress none
+}
+
 define dumptype comp-root {
     global
     comment "Root partitions with compression"
@@ -555,6 +626,24 @@ define dumptype comp-test {
     compress client fast
 }
 
+define dumptype custom-compress {
+   global
+   program "GNUTAR"
+   comment "test dump with custom client compression"
+   compress client custom
+   client_custom_compress "/usr/bin/bzip2"
+}
+
+define dumptype encrypt-fast {
+   global
+   program "GNUTAR"
+   comment "test dump with fast client compression and server symmetric encryption"
+   compress client fast
+   encrypt server
+   server_encrypt "/usr/local/sbin/amcrypt"
+   server_decrypt_option "-d"
+}
+
 # network interfaces
 #
 # These are referred to by the disklist file.  They define the attributes
@@ -585,4 +674,4 @@ define interface le0 {
 # dumptypes, tapetypes and interface definitions among several
 # configurations.
 
-#includefile "/usr/local/amanda.conf.main"
+#includefile "@CONFIG_DIR@/amanda.conf.main"
index 95df670dae7bd23e35d91e0ce52da4f5f15678eb..3009077a3eaadb95503a787782d7e84eac80b17c 100644 (file)
@@ -26,7 +26,7 @@
 #
 
 mcutil mcutil          #location of the mcutil program
-tape /dev/null # use ntape for norewind
+tape null:     # use ntape for norewind
                        # {a|m|h|c} suffixes should NOT 
                        # be tape device since they all
                        # implement hardware compression
diff --git a/example/chg-scsi-hpux.conf.in b/example/chg-scsi-hpux.conf.in
deleted file mode 100644 (file)
index 42d7a4d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-number_configs 1
-eject          0       # Tapedrives need an eject command
-sleep          90      # Seconds to wait until the tape gets ready
-cleanmax       100     # How many times could a cleaning tape get used
-changerdev     /dev/scsi/4:1
-#
-# Next comes the data for drive 0
-#
-config         0
-drivenum       0
-dev            /dev/rmt/0mnb
-startuse       0       # The slots associated with the drive 0
-enduse         4       # 
-statfile       @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-slot  # The file where the actual slot is stored
-cleancart      5       # the slot where the cleaningcartridge for drive 0 is located
-cleanfile      @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-clean # The file where the cleanings are recorded
-usagecount     @CONFIG_DIR@/@DEFAULT_CONFIG@/totaltime
-tapestatus     @CONFIG_DIR@/@DEFAULT_CONFIG@/tapestatus
-#labelfile     @CONFIG_DIR@/@DEFAULT_CONFIG@/labelfile # Use this if you have an barcode reader
diff --git a/example/chg-scsi-linux.conf.in b/example/chg-scsi-linux.conf.in
deleted file mode 100644 (file)
index 8fbd388..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-number_configs 1
-eject          0       # Tapedrives need an eject command
-sleep          90      # Seconds to wait until the tape gets ready
-cleanmax       100     # How many times could a cleaning tape get used
-changerdev     /dev/sg2
-#
-# Next comes the data for drive 0
-#
-config         0
-drivenum       0
-dev            /dev/nst0
-scsitapedev    /dev/sg1
-startuse       0       # The slots associated with the drive 0
-enduse         4       # 
-statfile       @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-slot  # The file where the actual slot is stored
-cleancart      5       # the slot where the cleaningcartridge for drive 0 is located
-cleanfile      @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-clean # The file where the cleanings are recorded
-usagecount     @CONFIG_DIR@/@DEFAULT_CONFIG@/totaltime
-tapestatus     @CONFIG_DIR@/@DEFAULT_CONFIG@/tapestatus # here will some status infos be stored
-#labelfile     @CONFIG_DIR@/@DEFAULT_CONFIG@/labelfile # Use this if you have an barcode reader
diff --git a/example/chg-scsi-solaris.conf.in b/example/chg-scsi-solaris.conf.in
deleted file mode 100644 (file)
index d74e68b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-number_configs 1
-eject          0       # Tapedrives need an eject command
-sleep          60      # Seconds to wait until the tape gets ready
-cleanmax       10      # How many times could a cleaning tape get used
-changerdev     /dev/rsst4
-#
-# Next comes the data for drive 0
-#
-config         0
-drivenum       0
-dev            /dev/rmt/0bn    # the device that is used for the tapedrive 0 (BSD type, no rewind, no compression)
-startuse       0       # The slots associated with the drive 0
-enduse         4       # 
-statfile       @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-slot  # The file where the actual slot is stored
-cleancart      5       # the slot where the cleaningcartridge for drive 0 is located
-cleanfile      @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-clean # The file where the cleanings are recorded
-usagecount     @CONFIG_DIR@/@DEFAULT_CONFIG@/totaltime
-tapestatus      @CONFIG_DIR@/@DEFAULT_CONFIG@/tape0-status
-#labelfile     @CONFIG_DIR@/@DEFAULT_CONFIG@/labelfile # Use this if you have an barcode reader
index 8ad8e77127cc774f506758ad50e28c4ff8ff9b87..1eea354f27a3ddb7bfccddf0b9be8072a7b7783d 100644 (file)
 
 transform =    s,x,x,;
 
-if WANT_AMPLOT
-AMPLOT_MAN_PAGES = amplot.8
+AMPLOT_MAN8_PAGES = amplot.8
+
+COMMON_MAN8_PAGES = amanda.8
+
+COMMON_MAN5_PAGES = amanda.conf.5
+
+SERVER_MAN8_PAGES = amadmin.8 \
+                   amcheck.8 \
+                   amcheckdb.8 \
+                   amcleanup.8 \
+                   amdd.8 \
+                   amdump.8 \
+                   amflush.8 \
+                   amgetconf.8 \
+                   amlabel.8 \
+                   ammt.8 \
+                   amoverview.8 \
+                   amreport.8 \
+                   amrmtape.8 \
+                   amstatus.8 \
+                   amtape.8 \
+                   amtapetype.8 \
+                   amtoc.8 \
+                   amverify.8 \
+                   amverifyrun.8 \
+                   amfetchdump.8 \
+                   amcrypt.8 \
+                   amaespipe.8
+
+if WANT_RECOVER
+RECOVER_MAN8_PAGES = amrecover.8
+endif
+
+if WANT_RESTORE
+RESTORE_MAN8_PAGES = amrestore.8
 endif
 
-COMMON_MAN_PAGES = amanda.8 amanda.conf.5
+man8_MANS = $(COMMON_MAN8_PAGES)
+
+man5_MANS = $(COMMON_MAN5_PAGES)
+
+if WANT_AMPLOT
+man8_MANS += $(AMPLOT_MAN8_PAGES)
+endif
 
 if WANT_SERVER
-SERVER_MAN_PAGES = amadmin.8 \
-                  amcheck.8 \
-                  amcheckdb.8 \
-                  amcleanup.8 \
-                  amdd.8 \
-                  amdump.8 \
-                  amflush.8 \
-                  amgetconf.8 \
-                  amlabel.8 \
-                  ammt.8 \
-                  amoverview.8 \
-                  amreport.8 \
-                  amrmtape.8 \
-                  amstatus.8 \
-                  amtape.8 \
-                  amtapetype.8 \
-                  amtoc.8 \
-                  amverify.8 \
-                  amverifyrun.8
+man8_MANS += $(SERVER_MAN8_PAGES)
 endif
 
 if WANT_RECOVER
-RECOVER_MAN_PAGES = amrecover.8
+man8_MANS += $(RECOVER_MAN8_PAGES)
 endif
 
 if WANT_RESTORE
-RESTORE_MAN_PAGES = amrestore.8
+man8_MANS += $(RESTORE_MAN8_PAGES)
 endif
 
-# not autoconf-generated:
-EXTRA_DIST = amadmin.8 amanda.8 amanda.conf.5 amcheck.8 amcheckdb.8 amcleanup.8 amdd.8 amdump.8 amflush.8 amgetconf.8 amlabel.8 ammt.8 amoverview.8 amplot.8 amreport.8 amrecover.8 amrestore.8 amrmtape.8 amstatus.8 amtape.8 amtapetype.8 amtoc.8 amverify.8 amverifyrun.8
+ALL_MAN_PAGES = $(AMPLOT_MAN8_PAGES) \
+          $(COMMON_MAN5_PAGES) \
+          $(COMMON_MAN8_PAGES) \
+          $(SERVER_MAN8_PAGES) \
+          $(RECOVER_MAN8_PAGES) \
+          $(RESTORE_MAN8_PAGES)
+
+man_MANS = $(man5_MANS) $(man8_MANS)
+
+SRCMANPAGEDIR  = $(srcdir)/xml-source
+
+MAN_XML = $(ALL_MAN_PAGES:%=xml-source/%.xml)
 
-man_MANS = $(AMPLOT_MAN_PAGES) \
-          $(COMMON_MAN_PAGES) \
-          $(SERVER_MAN_PAGES) \
-          $(RECOVER_MAN_PAGES) \
-          $(RESTORE_MAN_PAGES)
+EXTRA_XML = xslt/expand-sambadoc.xsl \
+            xslt/man.xsl \
+            xslt/settings.xsl \
+           entities/global.entities \
+           entities/xinclude.dtd
+           
+
+EXTRA_DIST = $(ALL_MAN_PAGES) $(MAN_XML) $(EXTRA_XML)
+
+if HAVE_XSLTPROC
+
+GEN_XML = $(ALL_MAN_PAGES:%=xml-source/%.proc.xml)
+
+MOSTLYCLEANFILES = $(GEN_XML)
+MAINTAINERCLEANFILES = $(ALL_MAN_PAGES)
+
+xml-source/%.proc.xml: $(SRCMANPAGEDIR)/%.xml $(srcdir)/xslt/expand-sambadoc.xsl
+       $(XSLTPROC) --path $(srcdir)/xslt/ --xinclude --stringparam latex.imagebasedir "$*/" --stringparam noreference 1 --output $@ $(srcdir)/xslt/expand-sambadoc.xsl $<
+
+%: xml-source/%.proc.xml $(srcdir)/xslt/man.xsl
+       $(XSLTPROC) --path $(srcdir)/xslt/ --output $@ man.xsl $<
+
+endif
+# ^- HAVE_XSLTPROC
 
 install-data-hook:
-       @list="$(man_MANS)"; \
+       @list="$(man8_MANS)"; \
        for p in $$list; do \
-               pa=$(DESTDIR)$(mandir)/man8/`echo $$p|sed '$(transform)'`; \
+               pa=$(DESTDIR)$(man8dir)/`echo $$p|sed '$(transform)'`; \
                echo chown $(BINARY_OWNER) $$pa; \
                chown $(BINARY_OWNER) $$pa; \
                echo chgrp $(SETUID_GROUP) $$pa; \
                chgrp $(SETUID_GROUP) $$pa; \
        done
+       @list="$(man5_MANS)"; \
+       for p in $$list; do \
+               pa=$(DESTDIR)$(man5dir)/`echo $$p|sed '$(transform)'`; \
+               echo chown $(BINARY_OWNER) $$pa; \
+               chown $(BINARY_OWNER) $$pa; \
+               echo chgrp $(SETUID_GROUP) $$pa; \
+               chgrp $(SETUID_GROUP) $$pa; \
+       done
+
index 906df072cb205fb597c7b8e802e2e58a233f5c12..df2afad64b42b4a91f171a433bd6e446d010ef0d 100644 (file)
@@ -37,6 +37,10 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
+@WANT_AMPLOT_TRUE@am__append_1 = $(AMPLOT_MAN8_PAGES)
+@WANT_SERVER_TRUE@am__append_2 = $(SERVER_MAN8_PAGES)
+@WANT_RECOVER_TRUE@am__append_3 = $(RECOVER_MAN8_PAGES)
+@WANT_RESTORE_TRUE@am__append_4 = $(RESTORE_MAN8_PAGES)
 subdir = man
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -53,7 +57,7 @@ man5dir = $(mandir)/man5
 am__installdirs = "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"
 man8dir = $(mandir)/man8
 NROFF = nroff
-MANS = $(man_MANS)
+MANS = $(man5_MANS) $(man8_MANS) $(man_MANS)
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 transform = s,x,x,;
 ACLOCAL = @ACLOCAL@
@@ -103,7 +107,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -115,9 +121,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -130,6 +139,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -192,10 +202,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -246,39 +259,57 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-@WANT_AMPLOT_TRUE@AMPLOT_MAN_PAGES = amplot.8
-COMMON_MAN_PAGES = amanda.8 amanda.conf.5
-@WANT_SERVER_TRUE@SERVER_MAN_PAGES = amadmin.8 \
-@WANT_SERVER_TRUE@                amcheck.8 \
-@WANT_SERVER_TRUE@                amcheckdb.8 \
-@WANT_SERVER_TRUE@                amcleanup.8 \
-@WANT_SERVER_TRUE@                amdd.8 \
-@WANT_SERVER_TRUE@                amdump.8 \
-@WANT_SERVER_TRUE@                amflush.8 \
-@WANT_SERVER_TRUE@                amgetconf.8 \
-@WANT_SERVER_TRUE@                amlabel.8 \
-@WANT_SERVER_TRUE@                ammt.8 \
-@WANT_SERVER_TRUE@                amoverview.8 \
-@WANT_SERVER_TRUE@                amreport.8 \
-@WANT_SERVER_TRUE@                amrmtape.8 \
-@WANT_SERVER_TRUE@                amstatus.8 \
-@WANT_SERVER_TRUE@                amtape.8 \
-@WANT_SERVER_TRUE@                amtapetype.8 \
-@WANT_SERVER_TRUE@                amtoc.8 \
-@WANT_SERVER_TRUE@                amverify.8 \
-@WANT_SERVER_TRUE@                amverifyrun.8
-
-@WANT_RECOVER_TRUE@RECOVER_MAN_PAGES = amrecover.8
-@WANT_RESTORE_TRUE@RESTORE_MAN_PAGES = amrestore.8
-
-# not autoconf-generated:
-EXTRA_DIST = amadmin.8 amanda.8 amanda.conf.5 amcheck.8 amcheckdb.8 amcleanup.8 amdd.8 amdump.8 amflush.8 amgetconf.8 amlabel.8 ammt.8 amoverview.8 amplot.8 amreport.8 amrecover.8 amrestore.8 amrmtape.8 amstatus.8 amtape.8 amtapetype.8 amtoc.8 amverify.8 amverifyrun.8
-man_MANS = $(AMPLOT_MAN_PAGES) \
-          $(COMMON_MAN_PAGES) \
-          $(SERVER_MAN_PAGES) \
-          $(RECOVER_MAN_PAGES) \
-          $(RESTORE_MAN_PAGES)
-
+AMPLOT_MAN8_PAGES = amplot.8
+COMMON_MAN8_PAGES = amanda.8
+COMMON_MAN5_PAGES = amanda.conf.5
+SERVER_MAN8_PAGES = amadmin.8 \
+                   amcheck.8 \
+                   amcheckdb.8 \
+                   amcleanup.8 \
+                   amdd.8 \
+                   amdump.8 \
+                   amflush.8 \
+                   amgetconf.8 \
+                   amlabel.8 \
+                   ammt.8 \
+                   amoverview.8 \
+                   amreport.8 \
+                   amrmtape.8 \
+                   amstatus.8 \
+                   amtape.8 \
+                   amtapetype.8 \
+                   amtoc.8 \
+                   amverify.8 \
+                   amverifyrun.8 \
+                   amfetchdump.8 \
+                   amcrypt.8 \
+                   amaespipe.8
+
+@WANT_RECOVER_TRUE@RECOVER_MAN8_PAGES = amrecover.8
+@WANT_RESTORE_TRUE@RESTORE_MAN8_PAGES = amrestore.8
+man8_MANS = $(COMMON_MAN8_PAGES) $(am__append_1) $(am__append_2) \
+       $(am__append_3) $(am__append_4)
+man5_MANS = $(COMMON_MAN5_PAGES)
+ALL_MAN_PAGES = $(AMPLOT_MAN8_PAGES) \
+          $(COMMON_MAN5_PAGES) \
+          $(COMMON_MAN8_PAGES) \
+          $(SERVER_MAN8_PAGES) \
+          $(RECOVER_MAN8_PAGES) \
+          $(RESTORE_MAN8_PAGES)
+
+man_MANS = $(man5_MANS) $(man8_MANS)
+SRCMANPAGEDIR = $(srcdir)/xml-source
+MAN_XML = $(ALL_MAN_PAGES:%=xml-source/%.xml)
+EXTRA_XML = xslt/expand-sambadoc.xsl \
+            xslt/man.xsl \
+            xslt/settings.xsl \
+           entities/global.entities \
+           entities/xinclude.dtd
+
+EXTRA_DIST = $(ALL_MAN_PAGES) $(MAN_XML) $(EXTRA_XML)
+@HAVE_XSLTPROC_TRUE@GEN_XML = $(ALL_MAN_PAGES:%=xml-source/%.proc.xml)
+@HAVE_XSLTPROC_TRUE@MOSTLYCLEANFILES = $(GEN_XML)
+@HAVE_XSLTPROC_TRUE@MAINTAINERCLEANFILES = $(ALL_MAN_PAGES)
 all: all-am
 
 .SUFFIXES:
@@ -419,6 +450,7 @@ CTAGS:
 
 
 distdir: $(DISTFILES)
+       $(mkdir_p) $(distdir)/entities $(distdir)/xslt
        @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
        topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
        list='$(DISTFILES)'; for file in $$list; do \
@@ -467,6 +499,7 @@ install-strip:
          `test -z '$(STRIP)' || \
            echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
 mostlyclean-generic:
+       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
 
 clean-generic:
 
@@ -476,6 +509,7 @@ distclean-generic:
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
 clean: clean-am
 
 clean-am: clean-generic clean-libtool mostlyclean-am
@@ -538,10 +572,26 @@ uninstall-man: uninstall-man5 uninstall-man8
        uninstall-info-am uninstall-man uninstall-man5 uninstall-man8
 
 
+@HAVE_XSLTPROC_TRUE@xml-source/%.proc.xml: $(SRCMANPAGEDIR)/%.xml $(srcdir)/xslt/expand-sambadoc.xsl
+@HAVE_XSLTPROC_TRUE@   $(XSLTPROC) --path $(srcdir)/xslt/ --xinclude --stringparam latex.imagebasedir "$*/" --stringparam noreference 1 --output $@ $(srcdir)/xslt/expand-sambadoc.xsl $<
+
+@HAVE_XSLTPROC_TRUE@%: xml-source/%.proc.xml $(srcdir)/xslt/man.xsl
+@HAVE_XSLTPROC_TRUE@   $(XSLTPROC) --path $(srcdir)/xslt/ --output $@ man.xsl $<
+
+# ^- HAVE_XSLTPROC
+
 install-data-hook:
-       @list="$(man_MANS)"; \
+       @list="$(man8_MANS)"; \
+       for p in $$list; do \
+               pa=$(DESTDIR)$(man8dir)/`echo $$p|sed '$(transform)'`; \
+               echo chown $(BINARY_OWNER) $$pa; \
+               chown $(BINARY_OWNER) $$pa; \
+               echo chgrp $(SETUID_GROUP) $$pa; \
+               chgrp $(SETUID_GROUP) $$pa; \
+       done
+       @list="$(man5_MANS)"; \
        for p in $$list; do \
-               pa=$(DESTDIR)$(mandir)/man8/`echo $$p|sed '$(transform)'`; \
+               pa=$(DESTDIR)$(man5dir)/`echo $$p|sed '$(transform)'`; \
                echo chown $(BINARY_OWNER) $$pa; \
                chown $(BINARY_OWNER) $$pa; \
                echo chgrp $(SETUID_GROUP) $$pa; \
index 66359824f69e75e30cd2e8b44257e20d1e6791ac..ba4e500be1882f426d2510a6dd3892ddcd018e22 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMADMIN" 8 "" "" ""
 .SH NAME
-amadmin \- administrative interface to control AMANDA backups
+amadmin \- administrative interface to control Amanda backups
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,10 +31,10 @@ amadmin \- administrative interface to control AMANDA backups
 .SH "DESCRIPTION"
 
 .PP
-\fBAmadmin\fR performs various administrative tasks on the \fBconfig\fR  \fBAMANDA\fR configuration\&.
+\fBAmadmin\fR performs various administrative tasks on the \fBconfig\fR  \fBAmanda\fR configuration\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "COMMANDS"
 
@@ -47,11 +47,11 @@ Show the current version and some compile time and runtime parameters\&. The \fB
 
 .TP
 \fBforce\-bump\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]+
-Force the \fBdisks\fR on \fBhostname\fR to bump to a new incremental level during the next \fBAMANDA\fR run\&.
+Force the \fBdisks\fR on \fBhostname\fR to bump to a new incremental level during the next \fBAmanda\fR run\&.
 
 .TP
 \fBforce\-no\-bump\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]+
-Force the \fBdisks\fR on \fBhostname\fR to not bump to a new incremental level during the next \fBAMANDA\fR run\&.
+Force the \fBdisks\fR on \fBhostname\fR to not bump to a new incremental level during the next \fBAmanda\fR run\&.
 
 .TP
 \fBunforce\-bump\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]+
@@ -59,7 +59,7 @@ Undo a previous \fBforce\-bump\fR or \fBforce\-no\-bump\fR command\&.
 
 .TP
 \fBforce\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]+
-Force the \fBdisks\fR on \fBhostname\fR to do a full (level 0) backup during the next \fBAMANDA\fR run\&.
+Force the \fBdisks\fR on \fBhostname\fR to do a full (level 0) backup during the next \fBAmanda\fR run\&.
 
 .TP
 \fBunforce\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]+
@@ -71,36 +71,36 @@ The tapes listed will be available for reuse at their point in the tape cycle\&.
 
 .TP
 \fBno\-reuse\fR \fBtapelabel\fR [ \&.\&.\&. ]
-The tapes listed will not be reused when their turn comes up again in the tape cycle\&. Note that if this causes the number of reusable tapes to drop below the \fBamanda\&.conf\fR  \fBtapecycle\fR value, \fBAMANDA\fR will request new tapes until the count is satisfied again\&.
+The tapes listed will not be reused when their turn comes up again in the tape cycle\&. Note that if this causes the number of reusable tapes to drop below the \fBamanda\&.conf\fR  \fBtapecycle\fR value, \fBAmanda\fR will request new tapes until the count is satisfied again\&.
 
 .TP
 \fBdue\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]*
 Show when the next full dump is due\&.
 
 .TP
-\fBfind\fR [ \fB\-\-sort\fR \fIhkdlb\fR ]\fB\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]*
+\fBfind\fR [ \fB\-\-sort\fR \fIhkdlpb\fR ]\fB\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]*
 Display all backups currently on tape or in the holding disk\&. The tape label or holding disk filename, file number, and status are displayed\&.
 
 The \fB\-\-sort\fR option changes the sort order using the following flags:
 
-\fBh\fRhost name \fBk\fRdisk name \fBd\fRdump date \fBl\fRbackup level \fBb\fRtape label
+\fBh\fRhost name \fBk\fRdisk name \fBd\fRdump date \fBl\fRbackup level \fBp\fR dump part \fBb\fRtape label
 
-An uppercase letter reverses the sort order for that key\&. The default sort order is \fBhkdlb\fR\&.
+An uppercase letter reverses the sort order for that key\&. The default sort order is \fBhkdlpb\fR\&.
 
 .TP
 \fBdelete\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]+
-Delete the specified \fBdisks\fR on \fBhostname\fR from the \fBAMANDA\fR database\&.
+Delete the specified \fBdisks\fR on \fBhostname\fR from the \fBAmanda\fR database\&.
 
 .RS
 .Sh "Note"
 If you do not also remove the disk from the
 \fBdisklist\fR
-file, \fBAMANDA\fR will treat it as a new disk during the next run\&.
+file, \fBAmanda\fR will treat it as a new disk during the next run\&.
 .RE
 
 .TP
 \fBtape\fR
-Display the tape(s) \fBAMANDA\fR expects to write to during the next run\&. See also \fBamcheck\fR(8)\&.
+Display the tape(s) \fBAmanda\fR expects to write to during the next run\&. See also \fBamcheck\fR(8)\&.
 
 .TP
 \fBbumpsize\fR
@@ -112,11 +112,11 @@ Display the distribution of full backups throughout the dump schedule\&.
 
 .TP
 \fBexport\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]*
-Convert records from the \fBAMANDA\fR database to a text format that may be transmitted to another \fBAMANDA\fR machine and \fBimport\fRed\&.
+Convert records from the \fBAmanda\fR database to a text format that may be transmitted to another \fBAmanda\fR machine and \fBimport\fRed\&.
 
 .TP
 \fBimport\fR
-Convert \fBexport\fRed records read from standard input to a form \fBAMANDA\fR uses and insert them into the database on this machine\&.
+Convert \fBexport\fRed records read from standard input to a form \fBAmanda\fR uses and insert them into the database on this machine\&.
 
 .TP
 \fBdisklist\fR [ \fBhostname\fR [ \fBdisks\fR ]* ]*
@@ -129,7 +129,7 @@ Display the database record for each of the \fBdisks\fR on \fBhostname\fR (or al
 .SH "EXAMPLES"
 
 .PP
-Request three specific file systems on \fBmachine\-a\fR get a full level 0 backup during the next \fBAMANDA\fR run\&.
+Request three specific file systems on \fBmachine\-a\fR get a full level 0 backup during the next \fBAmanda\fR run\&.
 .nf
 
 $ amadmin daily force machine\-a / /var /usr
@@ -139,7 +139,7 @@ amadmin: machine\-a:/usr is set to a forced level 0 tonight\&.
 .fi
 
 .PP
-Request all file systems on \fBmachine\-b\fR get a full level 0 backup during the next \fBAMANDA\fR run\&.
+Request all file systems on \fBmachine\-b\fR get a full level 0 backup during the next \fBAmanda\fR run\&.
 .nf
 
 $ amadmin daily force machine\-b
@@ -162,21 +162,21 @@ Locate backup images of \fI/var\fR from \fBmachine\-c\fR\&. The \fBtape or file\
 .nf
 
 $ amadmin daily find machine\-c /var
-date        host      disk lv tape or file                    file status
-2000\-11\-09  machine\-c /var  0 000110                             9 OK
-2000\-11\-08  machine\-c /var  2 000109                             2 OK
-2000\-11\-07  machine\-c /var  2 /amanda/20001107/machine\-c\&._var\&.2  0 OK
-2000\-11\-06  machine\-c /var  2 000107                             2 OK
-2000\-11\-05  machine\-c /var  2 000106                             3 OK
-2000\-11\-04  machine\-c /var  2 000105                             2 OK
-2000\-11\-03  machine\-c /var  2 000104                             2 OK
-2000\-11\-02  machine\-c /var  2 000103                             2 OK
-2000\-11\-01  machine\-c /var  1 000102                             5 OK
-2000\-10\-31  machine\-c /var  1 000101                             3 OK
+date        host      disk lv tape or file                 file part  status
+2000\\\-11\\\-09  machine\\\-c /var  0 000110                       9   \-\-  OK
+2000\\\-11\\\-08  machine\\\-c /var  2 000109                       2   \-\-  OK
+2000\\\-11\\\-07  machine\\\-c /var  2 /amanda/20001107/machine\-c\&._var\&.2  0 OK
+2000\\\-11\\\-06  machine\\\-c /var  2 000107                       2   \-\-  OK
+2000\\\-11\\\-05  machine\\\-c /var  2 000106                       3   \-\-  OK
+2000\\\-11\\\-04  machine\\\-c /var  2 000105                       2   \-\-  OK
+2000\\\-11\\\-03  machine\\\-c /var  2 000104                       2   \-\-  OK
+2000\\\-11\\\-02  machine\\\-c /var  2 000103                       2   \-\-  OK
+2000\\\-11\\\-01  machine\\\-c /var  1 000102                       5   \-\-  OK
+2000\\\-10\\\-31  machine\\\-c /var  1 000101                       3   \-\-  OK
 .fi
 
 .PP
-Forget about the \fI/workspace\fR disk on \fBmachine\-d\fR\&. If you do not also remove the disk from the \fBdisklist\fR file, \fBAMANDA\fR will treat it as a new disk during the next run\&.
+Forget about the \fI/workspace\fR disk on \fBmachine\-d\fR\&. If you do not also remove the disk from the \fBdisklist\fR file, \fBAmanda\fR will treat it as a new disk during the next run\&.
 .nf
 
 $ amadmin daily delete machine\-d /workspace
@@ -185,21 +185,21 @@ amadmin: NOTE: you'll have to remove these from the disklist yourself\&.
 .fi
 
 .PP
-Find the next tape \fBAMANDA\fR will use (in this case, 123456)\&.
+Find the next tape \fBAmanda\fR will use (in this case, 123456)\&.
 .nf
 
 $ amadmin daily tape
-The next \fBAMANDA\fR run should go onto tape 123456 or a new tape\&.
+The next \fBAmanda\fR run should go onto tape 123456 or a new tape\&.
 .fi
 
 .PP
 Show how well full backups are balanced across the dump cycle\&. The \fBdue\-date\fR column is the day the backups are due for a full backup\&. \fB#fs\fR shows the number of filesystems doing full backups that night, and \fBorig KB\fR and \fBout KB\fR show the estimated total size of the backups before and after any compression, respectively\&.
 
 .PP
-The \fBbalance\fR column shows how far off that night's backups are from the average size (shown at the bottom of the balance column)\&. \fBAMANDA\fR tries to keep the backups within +/\- 5%, but since the amount of data on each filesystem is always changing, and \fBAMANDA\fR will never delay backups just to rebalance the schedule, it is common for the schedule to fluctuate by larger percentages\&. In particular, in the case of a tape or backup failure, a bump will occur the following night, which will not be smoothed out until the next pass through the schedule\&.
+The \fBbalance\fR column shows how far off that night's backups are from the average size (shown at the bottom of the balance column)\&. \fBAmanda\fR tries to keep the backups within +/\- 5%, but since the amount of data on each filesystem is always changing, and \fBAmanda\fR will never delay backups just to rebalance the schedule, it is common for the schedule to fluctuate by larger percentages\&. In particular, in the case of a tape or backup failure, a bump will occur the following night, which will not be smoothed out until the next pass through the schedule\&.
 
 .PP
-The last line also shows an estimate of how many \fBAMANDA\fR runs will be made between full backups for a file system\&. In the example, a file system will probably have a full backup done every eight times \fBAMANDA\fR is run (e\&.g\&. every eight days)\&.
+The last line also shows an estimate of how many \fBAmanda\fR runs will be made between full backups for a file system\&. In the example, a file system will probably have a full backup done every eight times \fBAmanda\fR is run (e\&.g\&. every eight days)\&.
 .nf
 
 $ amadmin daily balance
@@ -230,10 +230,10 @@ TOTAL      241  12412187   7316312   731631  (estimated 8 runs per dumpcycle)
 James da Silva, <jds@amanda\&.org> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
 .PP
-\fBamanda\fR(8), \fBamcheck\fR(8), \fBamdump\fR(8), \fBamrestore\fR(8)
+\fBamanda\fR(8), \fBamcheck\fR(8), \fBamdump\fR(8), \fBamrestore\fR(8), \fBamfetchdump\fR(8)
 
diff --git a/man/amaespipe.8 b/man/amaespipe.8
new file mode 100644 (file)
index 0000000..09ac0c3
--- /dev/null
@@ -0,0 +1,47 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "AMAESPIPE" 8 "" "" ""
+.SH NAME
+amaespipe \- wrapper program for aespipe
+.SH "SYNOPSIS"
+.ad l
+.hy 0
+.HP 10
+\fBamaespipe\fR
+.ad
+.hy
+
+.SH "DESCRIPTION"
+
+.PP
+ \fBamaespipe\fR requires \fBaespipe\fR and \fBgpg\fR to work\&. Aespipe is available from : http://loop-aes.sourceforge.net
+
+.PP
+ \fBamaespipe\fR will search for the aespipe program in the following directories: /usr/bin:/usr/local/bin:/sbin:/usr/sbin\&.
+\fBamaespipe\fR is called by  \fBamcrypt\fR for \fBAmanda\fR data encryption\&.
+
+.PP
+ \fBamaespipe\fR is based on aespipe's bzaespipe program\&. It calls aespipe to encrypt data using AES256 as the encryption and SHA256 as the hash function\&. GPG key should be stored in $AMANDA_HOME/\&.gnupg/am_key\&.gpg\&. \fBamaespipe\fR reads passphrase from file descriptor 3\&. During decryption, \fBamaespipe\fR autodects encryption type and hash function from the encrypted image\&.
+
+.SH "SEE ALSO"
+
+.PP
+\fBamanda\fR(8), \fBamanda\&.conf\fR(5), \fBaespipe\fR(1), \fBamcrypt\fR(8), \fBgpg\fR(1) 
+
index e907b81b1677f9c1ff22c304884178228cb9bad2..186199248d69d296a47170d46e76c0b207b1aa24 100644 (file)
@@ -25,24 +25,40 @@ amanda \- Advanced Maryland Automatic Network Disk Archiver
 .hy 0
 .HP 8
 \fBamadmin\fR \fIconfig\fR \fIcommand\fR [\fIoptions\fR]
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 8
 \fBamcheck\fR [\fIoptions\fR] \fIconfig\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 10
 \fBamcheckdb\fR \fIconfig\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 10
 \fBamcleanup\fR \fIconfig\fR
+.br
+
+.ad
+.hy
+.ad l
+.hy 0
+.HP 8
+\fBamcrypt\fR
+.br
+
 .ad
 .hy
 .ad l
@@ -55,24 +71,40 @@ amanda \- Advanced Maryland Automatic Network Disk Archiver
 .hy 0
 .HP 7
 \fBamdump\fR \fIconfig\fR
+.br
+
+.ad
+.hy
+.ad l
+.hy 0
+.HP 10
+\fBamaespipe\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 8
 \fBamflush\fR [\-f] \fIconfig\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 10
 \fBamgetconf\fR [\fIconfig\fR] \fIparameter\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 8
 \fBamlabel\fR \fIconfig\fR \fIlabel\fR [\fIslot\fR\ \fIslot\fR]
+.br
+
 .ad
 .hy
 .ad l
@@ -85,48 +117,70 @@ amanda \- Advanced Maryland Automatic Network Disk Archiver
 .hy 0
 .HP 11
 \fBamoverview\fR \fIconfig\fR [\fIoptions\fR]
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 7
 \fBamplot\fR [\fIoptions\fR] \fIamdump\-files\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 10
 \fBamrecover\fR [\fIconfig\fR] [\fIoptions\fR]
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 9
 \fBamreport\fR [\fIconfig\fR] [\fIoptions\fR]
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 10
 \fBamrestore\fR [\fIoptions\fR] \fItapedevice\fR [\fIhostname\fR\ [\fIdiskname\fR]]
+.br
+
+.ad
+.hy
+.ad l
+.hy 0
+.HP 12
+\fBamfetchdump\fR [\fIoptions\fR] \fIconfig\fR [\fIhostname\fR\ [\fIdiskname\fR\ [\fIdate\fR\ [level]]]]
 .ad
 .hy
 .ad l
 .hy 0
 .HP 9
 \fBamrmtape\fR [\fIoptions\fR] \fIconfig\fR \fIlabel\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 9
 \fBamstatus\fR \fIconfig\fR [\fIoptions\fR]
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 7
 \fBamtape\fR \fIconfig\fR \fIcommand\fR [\fIoptions\fR]
+.br
+
 .ad
 .hy
 .ad l
@@ -139,12 +193,16 @@ amanda \- Advanced Maryland Automatic Network Disk Archiver
 .hy 0
 .HP 6
 \fBamtoc\fR [\fIoptions\fR] \fIlogfile\fR
+.br
+
 .ad
 .hy
 .ad l
 .hy 0
 .HP 9
 \fBamverify\fR \fIconfig\fR
+.br
+
 .ad
 .hy
 .ad l
@@ -157,14 +215,14 @@ amanda \- Advanced Maryland Automatic Network Disk Archiver
 .SH "DESCRIPTION"
 
 .PP
-\fBAMANDA\fR is the "Advanced Maryland Automatic Network Disk Archiver"\&. This manual page gives an overview of the \fBAMANDA\fR commands and configuration files for quick reference\&.
+\fBAmanda\fR is the "Advanced Maryland Automatic Network Disk Archiver"\&. This manual page gives an overview of the \fBAmanda\fR commands and configuration files for quick reference\&.
 
 .PP
-Here are all the \fBAMANDA\fR commands\&. Each one has its own manual page\&. See them for all the gory details\&.
+Here are all the \fBAmanda\fR commands\&. Each one has its own manual page\&. See them for all the gory details\&.
 
 .TP
 \fBamdump\fR
-Take care of automatic \fBAMANDA\fR backups\&. This is normally executed by \fBcron\fR on a computer called the \fBtape server host\fR and requests backups of file systems located on \fBbackup\fR  \fBclients\fR\&. \fBAmdump\fR backs up all disks in the \fBdisklist\fR file (discussed below) to tape or, if there is a problem, to a special \fBholding\fR  \fBdisk\fR\&. After all backups are done, \fBamdump\fR sends mail reporting failures and successes\&.
+Take care of automatic \fBAmanda\fR backups\&. This is normally executed by \fBcron\fR on a computer called the \fBtape server host\fR and requests backups of file systems located on \fBbackup\fR  \fBclients\fR\&. \fBAmdump\fR backs up all disks in the \fBdisklist\fR file (discussed below) to tape or, if there is a problem, to a special \fBholding\fR  \fBdisk\fR\&. After all backups are done, \fBamdump\fR sends mail reporting failures and successes\&.
 
 .TP
 \fBamflush\fR
@@ -176,15 +234,19 @@ Clean up after an interrupted \fBamdump\fR\&. This command is only needed if \fB
 
 .TP
 \fBamrecover\fR
-Provides an interactive interface to browse the \fBAMANDA\fR index files (backup image catalogues) and select which tapes to recover files from\&. It can also run \fBamrestore\fR and a restore program (e\&.g\&. \fBtar\fR) to actually recover the files\&.
+Provides an interactive interface to browse the \fBAmanda\fR index files (backup image catalogues) and select which tapes to recover files from\&. It can also run \fBamrestore\fR and a restore program (e\&.g\&. \fBtar\fR) to actually recover the files\&.
 
 .TP
 \fBamrestore\fR
-Read an \fBAMANDA\fR tape, searching for requested backups\&. \fBAmrestore\fR is suitable for everything from interactive restores of single files to a full restore of all partitions on a failed disk\&.
+Read an \fBAmanda\fR tape, searching for requested backups\&. \fBAmrestore\fR is suitable for everything from interactive restores of single files to a full restore of all partitions on a failed disk\&.
+
+.TP
+\fBamfetchdump\fR
+Performs \fBAmanda\fR tape restoration, similar to \fBamrestore\fR\&. Additional capabilities include "hands\-off" searching of multiple tapes, automatic retrieval of specific dump files based on dump logs, and assembly of tape\-spanning split dump files\&.
 
 .TP
 \fBamlabel\fR
-Write an \fBAMANDA\fR format label onto a tape\&. All \fBAMANDA\fR tapes must be labeled with \fBamlabel\fR\&. \fBAmdump\fR and \fBamflush\fR will not write to an unlabeled tape (see TAPE MANAGEMENT below)\&.
+Write an \fBAmanda\fR format label onto a tape\&. All \fBAmanda\fR tapes must be labeled with \fBamlabel\fR\&. \fBAmdump\fR and \fBamflush\fR will not write to an unlabeled tape (see TAPE MANAGEMENT below)\&.
 
 .TP
 \fBamcheck\fR
@@ -200,11 +262,11 @@ Take care of tape changer control operations like loading particular tapes, ejec
 
 .TP
 \fBamverify\fR
-Check \fBAMANDA\fR backup tapes for errors\&.
+Check \fBAmanda\fR backup tapes for errors\&.
 
 .TP
 \fBamrmtape\fR
-Delete a tape from the \fBAMANDA\fR databases\&.
+Delete a tape from the \fBAmanda\fR databases\&.
 
 .TP
 \fBamstatus\fR
@@ -216,35 +278,43 @@ Display a chart of hosts and file systems backed up every run\&.
 
 .TP
 \fBamplot\fR
-Generate utilization plots of \fBAMANDA\fR runs for performance tuning\&.
+Generate utilization plots of \fBAmanda\fR runs for performance tuning\&.
 
 .TP
 \fBamreport\fR
-Generate an \fBAMANDA\fR summary E\-mail report\&.
+Generate an \fBAmanda\fR summary E\-mail report\&.
 
 .TP
 \fBamtoc\fR
-Generate table of content files for \fBAMANDA\fR tapes\&.
+Generate table of content files for \fBAmanda\fR tapes\&.
 
 .TP
 \fBamcheckdb\fR
-Verify every tape \fBAMANDA\fR knows about is consistent in the database\&.
+Verify every tape \fBAmanda\fR knows about is consistent in the database\&.
 
 .TP
 \fBamgetconf\fR
-Look up parameters in the \fBAMANDA\fR configuration file\&.
+Look up parameters in the \fBAmanda\fR configuration file\&.
 
 .TP
 \fBamtapetype\fR
 Generate a tapetype definition\&.
 
+.TP
+\fBamaespipe\fR
+Wrapper program from aespipe (data encryption utility)
+
+.TP
+\fBamcrypt\fR
+Reference encryption program for Amanda symmetric data encryption
+
 .SH "CONFIGURATION"
 
 .PP
-There are three user\-editable files that control the behavior of \fBAMANDA\fR\&.
+There are three user\-editable files that control the behavior of \fBAmanda\fR\&.
 
 .PP
-The first is \fBamanda\&.conf\fR, the main configuration file\&. It contains parameters to customize \fBAMANDA\fR for the site\&. Refer to the \fBamanda\&.conf\fR(5), manpage for details on \fBAMANDA\fR configuration parameters\&.
+The first is \fBamanda\&.conf\fR, the main configuration file\&. It contains parameters to customize \fBAmanda\fR for the site\&. Refer to the \fBamanda\&.conf\fR(5), manpage for details on \fBAmanda\fR configuration parameters\&.
 
 .PP
 Second is the \fBdisklist\fR file, which lists hosts and disk partitions to back up\&.
@@ -253,19 +323,19 @@ Second is the \fBdisklist\fR file, which lists hosts and disk partitions to back
 Third is the \fBtapelist\fR file, which lists tapes that are currently active\&. These files are described in more detail in the following sections\&.
 
 .PP
-All files are stored in individual configuration directories under \fI/usr/local/etc/amanda/\fR\&. A site will often have more than one configuration\&. For example, it might have a \fBnormal\fR configuration for everyday backups and an \fBarchive\fR configuration for infrequent full archival backups\&. The configuration files would be stored under directories \fI/usr/local/etc/amanda/normal/\fR and \fI/usr/local/etc/amanda/archive/\fR, respectively\&. Part of the job of an \fBAMANDA\fR administrator is to create, populate and maintain these directories\&.
+All files are stored in individual configuration directories under \fI/usr/local/etc/amanda/\fR\&. A site will often have more than one configuration\&. For example, it might have a \fBnormal\fR configuration for everyday backups and an \fBarchive\fR configuration for infrequent full archival backups\&. The configuration files would be stored under directories \fI/usr/local/etc/amanda/normal/\fR and \fI/usr/local/etc/amanda/archive/\fR, respectively\&. Part of the job of an \fBAmanda\fR administrator is to create, populate and maintain these directories\&.
 
 .PP
-All log and database files generated by \fBAMANDA\fR go in corresponding directories somewhere\&. The exact location is controlled by entries in \fBamanda\&.conf\fR\&. A typical location would be under \fI/var/adm/amanda\fR\&. For the above example, the files might go in \fI/var/adm/amanda/normal/\fR and \fI/var/adm/amanda/archive/\fR\&.
+All log and database files generated by \fBAmanda\fR go in corresponding directories somewhere\&. The exact location is controlled by entries in \fBamanda\&.conf\fR\&. A typical location would be under \fI/var/adm/amanda\fR\&. For the above example, the files might go in \fI/var/adm/amanda/normal/\fR and \fI/var/adm/amanda/archive/\fR\&.
 
 .PP
-As log files are no longer needed (no longer contain relevant information), \fBAMANDA\fR cycles them out in various ways, depending on the type of file\&.
+As log files are no longer needed (no longer contain relevant information), \fBAmanda\fR cycles them out in various ways, depending on the type of file\&.
 
 .PP
 Detailed information about \fBamdump\fR runs are stored in files named \fBamdump\&.\fR\fBNN\fR where \fBNN\fR is a sequence number, with 1 being the most recent file\&. \fBAmdump\fR rotates these files each run, keeping roughly the last \fBtapecycle\fR (see below) worth of them\&.
 
 .PP
-The file used by \fBamreport\fR to generate the mail summary is named \fBlog\&.\fR\fBYYYYMMDD\&.NN\fR where \fBYYYYMMDD\fR is the datestamp of the start of the \fBamdump\fR run and \fBNN\fR is a sequence number started at 0\&. At the end of each \fBamdump\fR run, log files for runs whose tapes have been reused are renamed into a subdirectory of the main log directory (see the \fBlogdir\fR parameter below) named \fBoldlog\fR\&. It is up to the \fBAMANDA\fR administrator to remove them from this directory when desired\&.
+The file used by \fBamreport\fR to generate the mail summary is named \fBlog\&.\fR\fBYYYYMMDD\&.NN\fR where \fBYYYYMMDD\fR is the datestamp of the start of the \fBamdump\fR run and \fBNN\fR is a sequence number started at 0\&. At the end of each \fBamdump\fR run, log files for runs whose tapes have been reused are renamed into a subdirectory of the main log directory (see the \fBlogdir\fR parameter below) named \fBoldlog\fR\&. It is up to the \fBAmanda\fR administrator to remove them from this directory when desired\&.
 
 .PP
 Index (backup image catalogue) files older than the full dump matching the oldest backup image for a given client and disk are removed by \fBamdump\fR at the end of each run\&.
@@ -273,7 +343,7 @@ Index (backup image catalogue) files older than the full dump matching the oldes
 .SH "DISKLIST FILE"
 
 .PP
-The \fBdisklist\fR file determines which disks will be backed up by \fBAMANDA\fR\&. The file usually contains one line per disk:
+The \fBdisklist\fR file determines which disks will be backed up by \fBAmanda\fR\&. The file usually contains one line per disk:
 .nf
 
 \fBhostname diskname\fR [\fBdiskdevice\fR] \fBdumptype\fR [\fBspindle\fR [\fBinterface\fR] ]
@@ -287,11 +357,11 @@ Lines starting with # are ignored, as are blank lines\&. The fields have the fol
 
 .TP
 \fBhostname\fR
-The name of the host to be backed up\&. If \fBdiskdevice\fR refers to a PC share, this is the host \fBAMANDA\fR will run the Samba \fBsmbclient\fR program on to back up the share\&.
+The name of the host to be backed up\&. If \fBdiskdevice\fR refers to a PC share, this is the host \fBAmanda\fR will run the Samba \fBsmbclient\fR program on to back up the share\&.
 
 .TP
 \fBdiskname\fR
-The name of the disk (a label)\&. In most case, you set your \fBdiskname\fR to the \fBdiskdevice\fR and you don't set the \fBdiskdevice\&.\fR If you want multiple entries with the same \fBdiskdevice\fR, you must set a different \fBdiskname\fR for each entry\&. It's the \fBdiskname\fR that you use on the commandline for any \fBAMANDA\fR command\&. Look at the example/disklist file for example\&.
+The name of the disk (a label)\&. In most case, you set your \fBdiskname\fR to the \fBdiskdevice\fR and you don't set the \fBdiskdevice\&.\fR If you want multiple entries with the same \fBdiskdevice\fR, you must set a different \fBdiskname\fR for each entry\&. It's the \fBdiskname\fR that you use on the commandline for any \fBAmanda\fR command\&. Look at the example/disklist file for example\&.
 
 .TP
 \fBdiskdevice\fR
@@ -305,7 +375,7 @@ Refers to a \fBdumptype\fR defined in the \fBamanda\&.conf\fR file\&. \fBDumptyp
 
 .TP
 \fBspindle\fR
-Default: \fB\-1\fR\&. A number used to balance backup load on a host\&. \fBAMANDA\fR will not run multiple backups at the same time on the same spindle, unless the spindle number is \-1, which means there is no spindle restriction\&.
+Default: \fB\-1\fR\&. A number used to balance backup load on a host\&. \fBAmanda\fR will not run multiple backups at the same time on the same spindle, unless the spindle number is \-1, which means there is no spindle restriction\&.
 
 .TP
 \fBinterface\fR
@@ -330,7 +400,7 @@ For instance, if a \fBdumptype\fR named \fBnormal\fR is used for most disks, but
 .SH "TAPE MANAGEMENT"
 
 .PP
-The \fBtapelist\fR file contains the list of tapes in active use\&. This file is maintained entirely by \fBAMANDA\fR and should not be created or edited during normal operation\&. It contains lines of the form:
+The \fBtapelist\fR file contains the list of tapes in active use\&. This file is maintained entirely by \fBAmanda\fR and should not be created or edited during normal operation\&. It contains lines of the form:
 
 .PP
 
@@ -340,7 +410,7 @@ YYYYMMDD label flags
 
 
 .PP
-Where \fBYYYYMMDD\fR is the date the tape was written, \fBlabel\fR is a label for the tape as written by \fBamlabel\fR and \fBflags\fR tell \fBAMANDA\fR whether the tape may be reused, etc (see the \fBreuse\fR options of \fBamadmin\fR)\&.
+Where \fBYYYYMMDD\fR is the date the tape was written, \fBlabel\fR is a label for the tape as written by \fBamlabel\fR and \fBflags\fR tell \fBAmanda\fR whether the tape may be reused, etc (see the \fBreuse\fR options of \fBamadmin\fR)\&.
 
 .PP
 \fBAmdump\fR and \fBamflush\fR will refuse to write to an unlabeled tape, or to a labeled tape that is considered active\&. There must be more tapes in active rotation (see the \fBtapecycle\fR option) than there are runs in the backup cycle (see the \fBdumpcycle\fR option) to prevent overwriting a backup image that would be needed to do a full recovery\&.
@@ -348,7 +418,7 @@ Where \fBYYYYMMDD\fR is the date the tape was written, \fBlabel\fR is a label fo
 .SH "OUTPUT DRIVERS"
 
 .PP
-The normal value for the \fBtapedev\fR parameter, or for what a tape changer returns, is a full path name to a non\-rewinding tape device, such as \fI/dev/nst0\fR or \fI/dev/rmt/0mn\fR or \fI/dev/nst0\&.1\fR or whatever conventions the operating system uses\&. \fBAMANDA\fR provides additional application level drivers that support non\-traditional tape\-simulations or features\&. To access a specific output driver, set \fBtapedev\fR (or configure your changer to return) a string of the form \fBdriver\fR:\fBdriver\-info\fR where \fBdriver\fR is one of the supported drivers and \fBdriver\-info\fR is optional additional information needed by the driver\&.
+The normal value for the \fBtapedev\fR parameter, or for what a tape changer returns, is a full path name to a non\-rewinding tape device, such as \fI/dev/nst0\fR or \fI/dev/rmt/0mn\fR or \fI/dev/nst0\&.1\fR or whatever conventions the operating system uses\&. \fBAmanda\fR provides additional application level drivers that support non\-traditional tape\-simulations or features\&. To access a specific output driver, set \fBtapedev\fR (or configure your changer to return) a string of the form \fBdriver\fR:\fBdriver\-info\fR where \fBdriver\fR is one of the supported drivers and \fBdriver\-info\fR is optional additional information needed by the driver\&.
 
 .PP
 The supported drivers are:
@@ -367,7 +437,7 @@ tapedev tape:/dev/rmt/0mn
 
 .TP
 \fBnull\fR
-This driver throws away anything written to it and returns EOF for any reads except a special case is made for reading a label, in which case a "fake" value is returned that \fBAMANDA\fR checks for and allows through regardless of what you have set in \fBlabelstr\fR\&. The \fBdriver\-info\fR field is not used and may be left blank:
+This driver throws away anything written to it and returns EOF for any reads except a special case is made for reading a label, in which case a "fake" value is returned that \fBAmanda\fR checks for and allows through regardless of what you have set in \fBlabelstr\fR\&. The \fBdriver\-info\fR field is not used and may be left blank:
 
 
 .nf
@@ -412,25 +482,25 @@ The \fBlength\fR value from the associated \fBtapetype\fR is used to limit the a
 
 One way to use this driver with a real device such as a CD\-writer is to create a directory for the \fBfile\fR device and one or more other directories for the actual data\&. Create a symlink named \fBdata\fR in the \fBfile\fR directory to one of the data directories\&. Set the \fBtapetype\fR length to whatever the medium will hold\&.
 
-When \fBAMANDA\fR fills the \fBfile\fR device, remove the symlink and (optionally) create a new symlink to another data area\&. Use a CD writer software package to burn the image from the first data area\&.
+When \fBAmanda\fR fills the \fBfile\fR device, remove the symlink and (optionally) create a new symlink to another data area\&. Use a CD writer software package to burn the image from the first data area\&.
 
 To read the CD, mount it and create the \fBdata\fR symlink in the \fBfile\fR device directory\&.
 
 .SH "AUTHORIZATION"
 
 .PP
-\fBAMANDA\fR processes on the tape server host run as the \fBdumpuser\fR user listed in \fBamanda\&.conf\fR\&. When they connect to a backup client, they do so with an \fBAMANDA\fR\-specific protocol\&. They do not, for instance, use \fBrsh\fR or \fBssh\fR directly\&.
+\fBAmanda\fR processes on the tape server host run as the \fBdumpuser\fR user listed in \fBamanda\&.conf\fR\&. When they connect to a backup client, they do so with an \fBAmanda\fR\-specific protocol\&. They do not, for instance, use \fBrsh\fR or \fBssh\fR directly\&.
 
 .PP
 On the client side, the \fBamandad\fR daemon validates the connection using one of several methods, depending on how it was compiled and on options it is passed:
 
 .TP
 \&.rhosts
-Even though \fBAMANDA\fR does not use \fBrsh\fR, it can use \&.rhosts\-style authentication and a \&.rhosts file\&.
+Even though \fBAmanda\fR does not use \fBrsh\fR, it can use \&.rhosts\-style authentication and a \&.rhosts file\&.
 
 .TP
 \&.amandahosts
-This is essentially the same as \&.rhosts authentication except a different file, with almost the same format, is used\&. This is the default mechanism built into \fBAMANDA\fR\&.
+This is essentially the same as \&.rhosts authentication except a different file, with almost the same format, is used\&. This is the default mechanism built into \fBAmanda\fR\&.
 
 The format of the \fI\&.amandahosts\fR file is:
 
@@ -440,17 +510,17 @@ If \fBusername\fR is ommitted, it defaults to the user running \fBamandad\fR, i\
 
 .TP
 Kerberos
-\fBAMANDA\fR may use the Kerberos authentication system\&. Further information is in the \fBdocs/KERBEROS\fR   file that comes with an \fBAMANDA\fR distribution\&.
+\fBAmanda\fR may use the Kerberos authentication system\&. Further information is in the \fBdocs/KERBEROS\fR   file that comes with an \fBAmanda\fR distribution\&.
 
-For Samba access, \fBAMANDA\fR needs a file on the Samba server (which may or may not also be the tape server) named \fI/etc/amandapass\fR with share names, (clear text) passwords and (optional) domain names, in that order, one per line, whitespace separated\&. By default, the user used to connect to the PC is the same for all PC's and is compiled into \fBAMANDA\fR\&. It may be changed on a host by host basis by listing it first in the password field followed by a percent sign and then the password\&. For instance:
+For Samba access, \fBAmanda\fR needs a file on the Samba server (which may or may not also be the tape server) named \fI/etc/amandapass\fR with share names, (clear text) passwords and (optional) domain names, in that order, one per line, whitespace separated\&. By default, the user used to connect to the PC is the same for all PC's and is compiled into \fBAmanda\fR\&. It may be changed on a host by host basis by listing it first in the password field followed by a percent sign and then the password\&. For instance:
 
 .nf
 
   //some\-pc/home normalpw
   //another\-pc/disk otheruser%otherpw.fi
-With clear text passwords, this file should obviously be tightly protected\&. It only needs to be readable by the \fBAMANDA\fR\-user on the Samba server\&.
+With clear text passwords, this file should obviously be tightly protected\&. It only needs to be readable by the \fBAmanda\fR\-user on the Samba server\&.
 
-You can find further information in the \fBdocs/SAMBA\fR   file that comes with an \fBAMANDA\fR distribution\&.
+You can find further information in the \fBdocs/SAMBA\fR   file that comes with an \fBAmanda\fR distribution\&.
 
 .SH "HOST & DISK EXPRESSION"
 
@@ -459,8 +529,45 @@ All host and disk arguments to programs are special expressions\&. The command a
 
 .PP
 The matcher matches by word, each word is a glob expression, words are separated by the separator '\&.' for host and '/' for disk\&. You can anchor the expression at left with a '^'\&. You can anchor the expression at right with a '$'\&. The matcher is case insensitive for host but is case sensitive for disk\&. A match succeeds if all words in your expression match contiguous words in the host or disk\&.
-\&. word separator for a host/ word separator for a disk^ anchor at left$ anchor at right? match exactly one character except the separator* match zero or more characters except the separator**match zero or more characters including the separator
+
+.nf
+
+\&.    word separator for a host
+/      word separator for a disk
+^      anchor at left
+$      anchor at right
+?      match exactly one character except the separator
+*      match zero or more characters except the separator
+**     match zero or more characters including the separator
+
+.fi
+
 .PP
+Some examples:
+
+.nf
+
+EXPRESSION     WILL MATCH           WILL NOT MATCH
+hosta          hosta                hostb
+               hoSTA\&.dOMAIna\&.ORG 
+               foo\&.hosta\&.org 
+host           host                 hosta
+host?          hosta                host
+               hostb 
+ho*na          hoina                ho\&.aina\&.org
+ho**na         hoina 
+               ho\&.aina\&.org 
+^hosta         hosta                foo\&.hosta\&.org
+sda*           /dev/sda1 
+               /dev/sda12 
+/opt/          opt (disk)           opt (host)
+\&.opt\&.          opt (host)           opt (disk)
+/              /                    any other disk
+/usr           /usr 
+               /usr/opt 
+/usr$          /usr                 /usr/opt
+
+.fi
 
 .SH "DATESTAMP EXPRESSION"
 
@@ -476,10 +583,10 @@ A \fBdatestamp\fR expression is a range expression where we only match the prefi
 James da Silva, <jds@amanda\&.org> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion, major update
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion, major update
 
 .SH "SEE ALSO"
 
 .PP
- \fBamadmin\fR(8), \fBamanda\&.conf\fR(5), \fBamcheck\fR(8), \fBamcheckdb\fR(8), \fBamcleanup\fR(8), \fBamdd\fR(8), \fBamdump\fR(8), \fBamflush\fR(8), \fBamgetconf\fR(8), \fBamlabel\fR(8), \fBammt\fR(8), \fBamoverview\fR(8), \fBamplot\fR(8), \fBamrecover\fR(8), \fBamreport\fR(8), \fBamrestore\fR(8), \fBamrmtape\fR(8), \fBamstatus\fR(8), \fBamtape\fR(8), \fBamtapetype\fR(8), \fBamtoc\fR(8), \fBamverify\fR(8), \fBamverifyrun\fR(8)
+ \fBamadmin\fR(8), \fBamanda\&.conf\fR(5), \fBamcheck\fR(8), \fBamcheckdb\fR(8), \fBamcleanup\fR(8), \fBamdd\fR(8), \fBamdump\fR(8), \fBamfetchdump\fR(8)  \fBamflush\fR(8), \fBamgetconf\fR(8), \fBamlabel\fR(8), \fBammt\fR(8), \fBamoverview\fR(8), \fBamplot\fR(8), \fBamrecover\fR(8), \fBamreport\fR(8), \fBamrestore\fR(8), \fBamrmtape\fR(8), \fBamstatus\fR(8), \fBamtape\fR(8), \fBamtapetype\fR(8), \fBamtoc\fR(8), \fBamverify\fR(8), \fBamverifyrun\fR(8)
 
index df18a5c6567d893987903674b9ee27611b927414..2165cfadd35c788daa4d1f5a51bfe11ba55447f7 100644 (file)
 ..
 .TH "AMANDA.CONF" 5 "" "" ""
 .SH NAME
-amanda.conf \- Main configuration file for AMANDA, the Advanced Maryland Automatic Network Disk Archiver
+amanda.conf \- Main configuration file for Amanda, the Advanced Maryland Automatic Network Disk Archiver
 .SH "DESCRIPTION"
 
 .PP
-\fIamanda\&.conf\fR is the main configuration file for \fBAMANDA\fR\&. This manpage lists the relevant sections and parameters of this file for quick reference\&.
+\fIamanda\&.conf\fR is the main configuration file for \fBAmanda\fR\&. This manpage lists the relevant sections and parameters of this file for quick reference\&.
 
 .SH "PARAMETERS"
 
 .PP
-There are a number of configuration parameters that control the behavior of the \fBAMANDA\fR programs\&. All have default values, so you need not specify the parameter in \fBamanda\&.conf\fR if the default is suitable\&.
+There are a number of configuration parameters that control the behavior of the \fBAmanda\fR programs\&. All have default values, so you need not specify the parameter in \fBamanda\&.conf\fR if the default is suitable\&.
 
 .PP
 Lines starting with # are ignored, as are blank lines\&. Comments may be placed on a line with a directive by starting the comment with a #\&. The remainder of the line is ignored\&.
@@ -81,13 +81,22 @@ Some number of days\&.
 \fBweek weeks\fR
 Some number of weeks (days*7)\&.
 
- .RS .Sh "Note" The value \fBinf\fR may be used in most places where an integer is expected to mean an infinite amount\&. Boolean arguments may have any of the values \fBy\fR, \fByes\fR, \fBt\fR, \fBtrue\fR or \fBon\fR to indicate a true state, or \fBn\fR, \fBno\fR, \fBf\fR, \fBfalse\fR or \fBoff\fR to indicate a false state\&. If no argument is given, \fBtrue\fR is assumed\&. .RE 
+.RS
+.Sh "Note"
+The value
+\fBinf\fR
+may be used in most places where an integer is expected
+to mean an infinite amount\&.
+
+Boolean arguments may have any of the values \fBy\fR, \fByes\fR, \fBt\fR, \fBtrue\fR or \fBon\fR to indicate a true state, or \fBn\fR, \fBno\fR, \fBf\fR, \fBfalse\fR or \fBoff\fR to indicate a false state\&. If no argument is given, \fBtrue\fR is assumed\&.
+
+.RE
 
 .SS "PARAMETERS"
 
 .TP
 \fBorg\fR \fB string\fR
-Default: \fBdaily\fR\&. A descriptive name for the configuration\&. This string appears in the Subject line of mail reports\&. Each \fBAMANDA\fR configuration should have a different string to keep mail reports distinct\&.
+Default: \fBdaily\fR\&. A descriptive name for the configuration\&. This string appears in the Subject line of mail reports\&. Each \fBAmanda\fR configuration should have a different string to keep mail reports distinct\&.
 
 .TP
 \fBmailto\fR \fB string\fR
@@ -97,7 +106,19 @@ Default: \fBoperators\fR\&. A space separated list of recipients for mail report
 \fBdumpcycle\fR \fB int\fR
 Default: \fB10 days\fR\&. The number of days in the backup cycle\&. Each disk will get a full backup at least this often\&. Setting this to zero tries to do a full backup each run\&.
 
- .RS .Sh "Note" This parameter may also be set in a specific \fBdumptype\fR (see below)\&. This value sets the default for all \fBdumptype\fRs so must appear in \fBamanda\&.conf\fR before any \fBdumptype\fRs are defined\&. .RE 
+.RS
+.Sh "Note"
+This parameter may also be set in a specific
+\fBdumptype\fR
+(see below)\&.
+This value sets the default for all
+\fBdumptype\fRs
+so must appear in
+\fBamanda\&.conf\fR
+before any
+\fBdumptype\fRs
+are defined\&.
+.RE
 
 .TP
 \fBrunspercycle\fR \fB int\fR
@@ -105,15 +126,29 @@ Default: \fBsame as dumpcycle\fR\&. The number of amdump runs in \fBdumpcycle\fR
 
 .TP
 \fBtapecycle\fR \fB int\fR
-Default: \fB15 tapes\fR\&. Typically tapes are used by \fBAMANDA\fR in an ordered rotation\&. The \fBtapecycle\fR parameter defines the size of that rotation\&. The number of tapes in rotation must be larger than the number of tapes required for a complete dump cycle (see the \fBdumpcycle\fR parameter)\&.
+Default: \fB15 tapes\fR\&. Typically tapes are used by \fBAmanda\fR in an ordered rotation\&. The \fBtapecycle\fR parameter defines the size of that rotation\&. The number of tapes in rotation must be larger than the number of tapes required for a complete dump cycle (see the \fBdumpcycle\fR parameter)\&.
 
-This is calculated by multiplying the number of \fBamdump\fR runs per dump cycle (\fBrunspercycle\fR parameter) times the number of tapes used per run (\fBruntapes\fR parameter)\&. Typically two to four times this calculated number of tapes are in rotation\&. While \fBAMANDA\fR is always willing to use a new tape in its rotation, it refuses to reuse a tape until at least '\fBtapecycle\fR \-1' number of other tapes have been used\&.
+This is calculated by multiplying the number of \fBamdump\fR runs per dump cycle (\fBrunspercycle\fR parameter) times the number of tapes used per run (\fBruntapes\fR parameter)\&. Typically two to four times this calculated number of tapes are in rotation\&. While \fBAmanda\fR is always willing to use a new tape in its rotation, it refuses to reuse a tape until at least '\fBtapecycle\fR \-1' number of other tapes have been used\&.
 
 It is considered good administrative practice to set the \fBtapecycle\fR parameter slightly lower than the actual number of tapes in rotation\&. This allows the administrator to more easily cope with damaged or misplaced tapes or schedule adjustments that call for slight adjustments in the rotation order\&.
 
+.TP
+\fBlabel_new_tapes\fR \fB string\fR
+Default: not set\&. When set, this directive will cause \fBAmanda\fR to automatically write an \fBAmanda\fR tape label to any blank tape she encounters\&. This option is DANGEROUS because when set, \fBAmanda\fR will ERASE any non\-\fBAmanda\fR tapes you may have, and may also ERASE any near\-failing tapes\&. Use with caution\&.
+
+When using this directive, specify the template for new tape labels\&. The template should contain some number of contiguous '%' characters, which will be replaced with a generated number\&. Be sure to specify enough '%' characters that you do not run out of tape labels\&. Example: label_new_tapes "DailySet1\-%%%" 
+
+.TP
+
+=======
+  \fBlabel_new_tapes\fR \fB string\fR
+Default: not set\&. When set, this directive will cause \fBAmanda\fR to automatically write an Amanda tape label to any black tape she encounters\&. This option is DANGEROUS because when set, \fBAmanda\fR will ERASE any non\-\fBAmanda\fR tapes you may have, and may also ERASE any near\-failing tapes\&. Use with caution\&.
+
+When using this directive, specify the template for new tape labels\&. The template should contain some number of contiguous '%' characters, which will be replaced with a generated number\&. Be sure to specify enough '%' characters that you do not run out of tape labels\&. Example: label_new_tapes "DailySet1\-%%%" 
+
 .TP
 \fBdumpuser\fR \fB string\fR
-Default: \fBamanda\fR\&. The login name \fBAMANDA\fR uses to run the backups\&. The backup client hosts must allow access from the tape server host as this user via \&.rhosts or \&.amandahosts, depending on how the \fBAMANDA\fR software was built\&.
+Default: \fBamanda\fR\&. The login name \fBAmanda\fR uses to run the backups\&. The backup client hosts must allow access from the tape server host as this user via \&.rhosts or \&.amandahosts, depending on how the \fBAmanda\fR software was built\&.
 
 .TP
 \fBprinter\fR string
@@ -121,7 +156,7 @@ Printer to use when doing tape labels\&. See the \fBlbl\-templ\fR  \fBtapetype\f
 
 .TP
 \fBtapedev\fR string
-Default: \fI/dev/nst0\fR\&. The path name of the non\-rewinding tape device\&. Non\-rewinding tape device names often have an 'n' in the name, e\&.g\&. \fI/dev/rmt/0mn\fR, however this is operating system specific and you should consult that documentation for detailed naming information\&.
+Default: \fInull:\fR\&. The path name of the non\-rewinding tape device\&. Non\-rewinding tape device names often have an 'n' in the name, e\&.g\&. \fI/dev/rmt/0mn\fR, however this is operating system specific and you should consult that documentation for detailed naming information\&.
 
 If a tape changer is configured (see the \fBtpchanger\fR option), this option might not be used\&.
 
@@ -129,7 +164,7 @@ If the \fBnull\fR output driver is selected (see the section OUTPUT DRIVERS in t
 
 .TP
 \fBrawtapedev\fR string
-Default: \fI/dev/null\fR\&. The path name of the raw tape device\&. This is only used if \fBAMANDA\fR is compiled for Linux machines with floppy tapes and is needed for QIC volume table operations\&.
+Default: \fInull:\fR\&. The path name of the raw tape device\&. This is only used if \fBAmanda\fR is compiled for Linux machines with floppy tapes and is needed for QIC volume table operations\&.
 
 .TP
 \fBtpchanger\fR string
@@ -149,11 +184,11 @@ Default: \fI/usr/adm/amanda/log/changer\-status\fR\&. A tape changer configurati
 \fBruntapes\fR int
 Default: 1\&. The maximum number of tapes used in a single run\&. If a tape changer is not configured, this option is not used and should be commented out of the configuration file\&.
 
-If a tape changer is configured, this may be set larger than one to let \fBAMANDA\fR write to more than one tape\&.
+If a tape changer is configured, this may be set larger than one to let \fBAmanda\fR write to more than one tape\&.
 
-Note that this is an upper bound on the number of tapes, and \fBAMANDA\fR may use less\&.
+Note that this is an upper bound on the number of tapes, and \fBAmanda\fR may use less\&.
 
-Also note that as of this release, \fBAMANDA\fR does not support true tape overflow\&. When it reaches the end of one tape, the backup image \fBAMANDA\fR was processing starts over again on the next tape\&.
+Also note that as of this release, \fBAmanda\fR does not support true tape overflow\&. When it reaches the end of one tape, the backup image \fBAmanda\fR was processing starts over again on the next tape\&.
 
 .TP
 \fBmaxdumpsize\fR int
@@ -200,6 +235,8 @@ Default: \fB\&.*\fR\&. The tape label constraint regular expression\&. All tape
 \fBtapetype\fR \fB string\fR
 Default: \fBEXABYTE\fR\&. The type of tape drive associated with \fBtapedev\fR or \fBtpchanger\fR\&. This refers to one of the defined \fBtapetype\fRs in the config file (see below), which specify various tape parameters, like the \fBlength\fR, \fBfilemark\fR size, and \fBspeed\fR of the tape media and device\&.
 
+First character of a \fBtapetype\fR string must be an alphabetic character
+
 .TP
 \fBctimeout\fR int
 Default: \fB30 seconds\fR\&. Maximum amount of time that \fBamcheck\fR will wait for each client host\&.
@@ -214,11 +251,11 @@ Default: \fB300 seconds\fR\&. Amount of time per disk on a given client that the
 
 .TP
 \fBnetusage\fR int
-Default: \fB300 Kbps\fR\&. The maximum network bandwidth allocated to \fBAMANDA\fR, in Kbytes per second\&. See also the \fBinterface\fR section\&.
+Default: \fB300 Kbps\fR\&. The maximum network bandwidth allocated to \fBAmanda\fR, in Kbytes per second\&. See also the \fBinterface\fR section\&.
 
 .TP
 \fBinparallel\fR int
-Default: 10\&. The maximum number of backups that \fBAMANDA\fR will attempt to run in parallel\&. \fBAMANDA\fR will stay within the constraints of network bandwidth and holding disk space available, so it doesn't hurt to set this number a bit high\&. Some contention can occur with larger numbers of backups, but this effect is relatively small on most systems\&.
+Default: 10\&. The maximum number of backups that \fBAmanda\fR will attempt to run in parallel\&. \fBAmanda\fR will stay within the constraints of network bandwidth and holding disk space available, so it doesn't hurt to set this number a bit high\&. Some contention can occur with larger numbers of backups, but this effect is relatively small on most systems\&.
 
 .TP
 \fBdisplayunit\fR "k|m|g|t"
@@ -253,13 +290,13 @@ B: largest bandwidth
 
 .TP
 \fBmaxdumps\fR int
-Default: 1\&. The maximum number of backups from a single host that \fBAMANDA\fR will attempt to run in parallel\&. See also the \fBinparallel\fR option\&.
+Default: 1\&. The maximum number of backups from a single host that \fBAmanda\fR will attempt to run in parallel\&. See also the \fBinparallel\fR option\&.
 
 Note that this parameter may also be set in a specific \fBdumptype\fR (see below)\&. This value sets the default for all \fBdumptype\fRs so must appear in \fBamanda\&.conf\fR before any \fBdumptype\fRs are defined\&.
 
 .TP
 \fBbumpsize\fR int
-Default: \fB10 Mbytes\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as size\&. If \fBAMANDA\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&. The value of this parameter is used only if the parameter \fBbumppercent\fR is set to 0\&.
+Default: \fB10 Mbytes\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as size\&. If \fBAmanda\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&. The value of this parameter is used only if the parameter \fBbumppercent\fR is set to 0\&.
 
 The global setting of this parameter can be overwritten inside of a dumptype\-definition\&.
 
@@ -267,7 +304,7 @@ See also the options \fBbumppercent\fR, \fBbumpmult\fR and \fBbumpdays\fR\&.
 
 .TP
 \fBbumppercent\fR int
-Default: \fB0 percent\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as percentage of the current size of the DLE (size of current level 0)\&. If \fBAMANDA\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&.
+Default: \fB0 percent\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as percentage of the current size of the DLE (size of current level 0)\&. If \fBAmanda\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&.
 
 If this parameter is set to 0, the value of the parameter \fBbumpsize\fR is used to trigger bumping\&.
 
@@ -277,13 +314,13 @@ See also the options \fBbumpsize\fR, \fBbumpmult\fR and \fBbumpdays\fR\&.
 
 .TP
 \fBbumpmult\fR \fB float\fR
-Default: 1\&.5\&. The bump size multiplier\&. \fBAMANDA\fR multiplies \fBbumpsize\fR by this factor for each level\&. This prevents active filesystems from bumping too much by making it harder to bump to the next level\&. For example, with the default \fBbumpsize\fR and \fBbumpmult\fR set to 2\&.0, the bump threshold will be 10 Mbytes for level one, 20 Mbytes for level two, 40 Mbytes for level three, and so on\&.
+Default: 1\&.5\&. The bump size multiplier\&. \fBAmanda\fR multiplies \fBbumpsize\fR by this factor for each level\&. This prevents active filesystems from bumping too much by making it harder to bump to the next level\&. For example, with the default \fBbumpsize\fR and \fBbumpmult\fR set to 2\&.0, the bump threshold will be 10 Mbytes for level one, 20 Mbytes for level two, 40 Mbytes for level three, and so on\&.
 
 The global setting of this parameter can be overwritten inside of a dumptype\-definition\&.
 
 .TP
 \fBbumpdays\fR \fB int\fR
-Default: \fB2 days\fR\&. To insure redundancy in the dumps, \fBAMANDA\fR keeps filesystems at the same incremental level for at least \fBbumpdays\fR days, even if the other bump threshold criteria are met\&.
+Default: \fB2 days\fR\&. To insure redundancy in the dumps, \fBAmanda\fR keeps filesystems at the same incremental level for at least \fBbumpdays\fR days, even if the other bump threshold criteria are met\&.
 
 The global setting of this parameter can be overwritten inside of a dumptype\-definition\&.
 
@@ -293,7 +330,7 @@ Default: \fBdisklist\fR\&. The file name for the \fBdisklist\fR file holding cli
 
 .TP
 \fBinfofile\fR \fB string\fR
-Default: \fI/usr/adm/amanda/curinfo\fR\&. The file or directory name for the historical information database\&. If \fBAMANDA\fR was configured to use DBM databases, this is the base file name for them\&. If it was configured to use text formated databases (the default), this is the base directory and within here will be a directory per client, then a directory per disk, then a text file of data\&.
+Default: \fI/usr/adm/amanda/curinfo\fR\&. The file or directory name for the historical information database\&. If \fBAmanda\fR was configured to use DBM databases, this is the base file name for them\&. If it was configured to use text formated databases (the default), this is the base directory and within here will be a directory per client, then a directory per disk, then a text file of data\&.
 
 .TP
 \fBlogdir\fR \fB string\fR
@@ -305,7 +342,7 @@ Default \fI/usr/adm/amanda/index\fR\&. The directory where index files (backup i
 
 .TP
 \fBtapelist\fR \fB string\fR
-Default: \fBtapelist\fR\&. The file name for the active \fBtapelist\fR file\&. \fBAMANDA\fR maintains this file with information about the active set of tapes\&.
+Default: \fBtapelist\fR\&. The file name for the active \fBtapelist\fR file\&. \fBAmanda\fR maintains this file with information about the active set of tapes\&.
 
 .TP
 \fBtapebufs\fR \fB int\fR
@@ -317,7 +354,7 @@ Default: 100\&. The part of holding\-disk space that should be reserved for incr
 
 .TP
 \fBautoflush\fR \fB bool\fR
-Default: \fBoff\fR\&. Whether an amdump run will flush the dump already on holding disk to tape\&.
+Default: \fBoff\fR\&. Whether an amdump run will flush the dumps from holding disk to tape\&.
 
 .TP
 \fBamrecover_do_fsf\fR \fB bool\fR
@@ -385,15 +422,20 @@ the width of the column itself\&. If set to a negative value, the width will be
 .RE
 .IP
 Here is an example:
-
 .nf
 
-columnspec "Disk=1:18,HostName=0:10,OutKB=1:7".fi
-The above will display the disk information in 18 characters and put one space before it\&. The hostname column will be 10 characters wide with no space to the left\&. The output KBytes column is seven characters wide with one space before it\&.
+columnspec "Disk=1:18,HostName=0:10,OutKB=1:7"
+
+.fi
 
+The above will display the disk information in 18 characters
+and put one space before it\&. The hostname column will be 10 characters wide with
+no space to the left\&. The output KBytes column is seven characters wide
+with one space before it\&.
+  
 .TP
 \fBincludefile\fR \fB string\fR
-Default: \fBnone\fR\&. The name of an \fBAMANDA\fR configuration file to include within the current file\&. Useful for sharing dumptypes, tapetypes and interface definitions among several configurations\&.
+Default: \fBnone\fR\&. The name of an \fBAmanda\fR configuration file to include within the current file\&. Useful for sharing dumptypes, tapetypes and interface definitions among several configurations\&.
 
 .SH "HOLDINGDISK SECTION"
 
@@ -422,22 +464,42 @@ Default: \fI/dumps/amanda\fR\&. The path to this holding area\&.
 
 .TP
 \fBuse\fR \fB int\fR
-Default: \fB0 Gb\fR\&. Amount of space that can be used in this holding disk area\&. If the value is zero, all available space on the file system is used\&. If the value is negative, \fBAMANDA\fR will use all available space minus that value\&.
 
+Default:
+\fB0 Gb\fR\&.
+Amount of space that can be used in this holding disk area\&.
+If the value is zero, all available space on the file system is used\&.
+If the value is negative, \fBAmanda\fR will use all available space minus that value\&.
+  
 .TP
 \fBchunksize\fR \fB int\fR
-Default: \fB1 Gb\fR\&. Holding disk chunk size\&. Dumps larger than the specified size will be stored in multiple holding disk files\&. The size of each chunk will not exceed the specified value\&. However, even though dump images are split in the holding disk, they are concatenated as they are written to tape, so each dump image still corresponds to a single continuous tape section\&.
-
-If 0 is specified, \fBAMANDA\fR will create holding disk chunks as large as ((INT_MAX/1024)\-64) Kbytes\&.
-
-Each holding disk chunk includes a 32 Kbyte header, so the minimum chunk size is 64 Kbytes (but that would be really silly)\&.
-
-Operating systems that are limited to a maximum file size of 2 Gbytes actually cannot handle files that large\&. They must be at least one byte less than 2 Gbytes\&. Since \fBAMANDA\fR works with 32 Kbyte blocks, and to handle the final read at the end of the chunk, the chunk size should be at least 64 Kbytes (2 * 32 Kbytes) smaller than the maximum file size, e\&.g\&. 2047 Mbytes\&.
 
+Default:
+\fB1 Gb\fR\&.
+Holding disk chunk size\&. Dumps larger than the specified size will be stored in multiple
+holding disk files\&. The size of each chunk will not exceed the specified value\&.
+However, even though dump images are split in the holding disk, they are concatenated as 
+they are written to tape, so each dump image still corresponds to a single continuous 
+tape section\&.
+
+If 0 is specified, \fBAmanda\fR will create holding disk chunks as large as
+((INT_MAX/1024)\-64) Kbytes\&.
+
+Each holding disk chunk includes a 32 Kbyte header, so the minimum
+chunk size is 64 Kbytes (but that would be really silly)\&.
+
+Operating systems that are limited to a maximum file size of 2 Gbytes
+actually cannot handle files that large\&.
+They must be at least one byte less than 2 Gbytes\&.
+Since \fBAmanda\fR works with 32 Kbyte blocks, and
+to handle the final read at the end of the chunk, the chunk size
+should be at least 64 Kbytes (2 * 32 Kbytes) smaller than the maximum
+file size, e\&.g\&. 2047 Mbytes\&.
+  
 .SH "DUMPTYPE SECTION"
 
 .PP
-The \fBamanda\&.conf\fR file may define multiple sets of backup options and refer to them by name from the \fBdisklist\fR file\&. For instance, one set of options might be defined for file systems that can benefit from high compression, another set that does not compress well, another set for file systems that should always get a full backup and so on\&.
+The \fIamanda\&.conf\fR file may define multiple sets of backup options and refer to them by name from the \fIdisklist\fR file\&. For instance, one set of options might be defined for file systems that can benefit from high compression, another set that does not compress well, another set for file systems that should always get a full backup and so on\&.
 
 .PP
 A set of backup options are entered in a \fBdumptype\fR section, which looks like this:
@@ -450,27 +512,33 @@ define dumptype \fBname\fR {
 .fi
 
 .PP
-\fBName\fR is the name of this set of backup options\&. It is referenced from the \fBdisklist\fR file\&.
+\fBName\fR is the name of this set of backup options\&. It is referenced from the \fIdisklist\fR file\&.
 
 .PP
-Some of the options in a \fBdumptype\fR section are the same as those in the main part of \fBamanda\&.conf\fR\&. The main option value is used to set the default for all \fBdumptype\fR sections\&. For instance, setting \fBdumpcycle\fR to 50 in the main part of the config file causes all following \fBdumptype\fR sections to start with that value, but the value may be changed on a section by section basis\&. Changes to variables in the main part of the config file must be done before (earlier in the file) any \fBdumptype\fRs are defined\&.
+Some of the options in a \fBdumptype\fR section are the same as those in the main part of \fIamanda\&.conf\fR\&. The main option value is used to set the default for all \fBdumptype\fR sections\&. For instance, setting \fBdumpcycle\fR to 50 in the main part of the config file causes all following \fBdumptype\fR sections to start with that value, but the value may be changed on a section by section basis\&. Changes to variables in the main part of the config file must be done before (earlier in the file) any \fBdumptype\fRs are defined\&.
 
 .PP
 The dumptype options and values are:
 
 .TP
 \fBauth\fR \fB string\fR
-Default: \fBbsd\fR\&. Type of authorization to perform between tape server and backup client hosts\&. May be \fBkrb4\fR to use Kerberos\-IV authorization\&.
+Default: \fBbsd\fR\&. Type of authorization to perform between tape server and backup client hosts\&.
+
+\fBkrb4\fR to use Kerberos\-IV authorization\&.
+
+\fBkrb5\fR to use Kerberos\-V authorization\&.
+
+\fBssh\fR to use OpenSSH authorization\&.
 
 .TP
 \fBbumpsize\fR int
-Default: \fB10 Mbytes\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as size\&. If \fBAMANDA\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&. The value of this parameter is used only if the parameter \fBbumppercent\fR is set to 0\&.
+Default: \fB10 Mbytes\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as size\&. If \fBAmanda\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&. The value of this parameter is used only if the parameter \fBbumppercent\fR is set to 0\&.
 
 See also the options \fBbumppercent\fR, \fBbumpmult\fR and \fBbumpdays\fR\&.
 
 .TP
 \fBbumppercent\fR int
-Default: \fB0 percent\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as percentage of the current size of the DLE (size of current level 0)\&. If \fBAMANDA\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&.
+Default: \fB0 percent\fR\&. The minimum savings required to trigger an automatic bump from one incremental level to the next, expressed as percentage of the current size of the DLE (size of current level 0)\&. If \fBAmanda\fR determines that the next higher backup level will be this much smaller than the current level, it will do the next level\&.
 
 If this parameter is set to 0, the value of the parameter \fBbumpsize\fR is used to trigger bumping\&.
 
@@ -478,11 +546,11 @@ See also the options \fBbumpsize\fR, \fBbumpmult\fR and \fBbumpdays\fR\&.
 
 .TP
 \fBbumpmult\fR \fB float\fR
-Default: 1\&.5\&. The bump size multiplier\&. \fBAMANDA\fR multiplies \fBbumpsize\fR by this factor for each level\&. This prevents active filesystems from bumping too much by making it harder to bump to the next level\&. For example, with the default \fBbumpsize\fR and \fBbumpmult\fR set to 2\&.0, the bump threshold will be 10 Mbytes for level one, 20 Mbytes for level two, 40 Mbytes for level three, and so on\&.
+Default: 1\&.5\&. The bump size multiplier\&. \fBAmanda\fR multiplies \fBbumpsize\fR by this factor for each level\&. This prevents active filesystems from bumping too much by making it harder to bump to the next level\&. For example, with the default \fBbumpsize\fR and \fBbumpmult\fR set to 2\&.0, the bump threshold will be 10 Mbytes for level one, 20 Mbytes for level two, 40 Mbytes for level three, and so on\&.
 
 .TP
 \fBbumpdays\fR \fB int\fR
-Default: \fB2 days\fR\&. To insure redundancy in the dumps, \fBAMANDA\fR keeps filesystems at the same incremental level for at least \fBbumpdays\fR days, even if the other bump threshold criteria are met\&.
+Default: \fB2 days\fR\&. To insure redundancy in the dumps, \fBAmanda\fR keeps filesystems at the same incremental level for at least \fBbumpdays\fR days, even if the other bump threshold criteria are met\&.
 
 .TP
 \fBcomment\fR \fB string\fR
@@ -490,13 +558,13 @@ Default: \fBnone\fR\&. A comment string describing this set of backup options\&.
 
 .TP
 \fBcomprate\fR \fBfloat\fR [, \fBfloat\fR ]
-Default: 0\&.50, 0\&.50\&. The expected full and incremental compression factor for dumps\&. It is only used if \fBAMANDA\fR does not have any history information on compression rates for a filesystem, so should not usually need to be set\&. However, it may be useful for the first time a very large filesystem that compresses very little is backed up\&.
+Default: 0\&.50, 0\&.50\&. The expected full and incremental compression factor for dumps\&. It is only used if \fBAmanda\fR does not have any history information on compression rates for a filesystem, so should not usually need to be set\&. However, it may be useful for the first time a very large filesystem that compresses very little is backed up\&.
 
 .TP
 \fBcompress [client|server]\fR \fB string\fR
-Default: \fBclient fast\fR\&. If \fBAMANDA\fR does compression of the backup images, it can do so either on the backup client host before it crosses the network or on the tape server host as it goes from the network into the holding disk or to tape\&. Which place to do compression (if at all) depends on how well the dump image usually compresses, the speed and load on the client or server, network capacity, holding disk capacity, availability of tape hardware compression, etc\&.
+Default: \fBclient fast\fR\&. If \fBAmanda\fR does compression of the backup images, it can do so either on the backup client host before it crosses the network or on the tape server host as it goes from the network into the holding disk or to tape\&. Which place to do compression (if at all) depends on how well the dump image usually compresses, the speed and load on the client or server, network capacity, holding disk capacity, availability of tape hardware compression, etc\&.
 
-For either type of compression, \fBAMANDA\fR also allows the selection of two styles of compression\&. \fBBest\fR is the best compression available, often at the expense of CPU overhead\&. \fBFast\fR is often not as good a compression as \fBbest\fR, but usually less CPU overhead\&.
+For either type of compression, \fBAmanda\fR also allows the selection of three styles of compression\&. \fBBest\fR is the best compression available, often at the expense of CPU overhead\&. \fBFast\fR is often not as good a compression as \fBbest\fR, but usually less CPU overhead\&. Or to specify \fBCustom\fR to use your own compression method\&. (See dumptype custom\-compress in example/amanda\&.conf for reference)
 
 So the \fBcompress\fR options line may be one of:
 
@@ -513,22 +581,77 @@ compress [client] fast
 compress [client] best
 .TP
 \(bu
+compress client custom
+
+Specify client_custom_compress "PROG"
+
+PROG must not contain white space and it must accept \-d for uncompress\&.
+.TP
+\(bu
 compress server fast
 .TP
 \(bu
 compress server best
+.TP
+\(bu
+compress server custom
+
+Specify server_custom_compress "PROG"
+
+PROG must not contain white space and it must accept \-d for uncompress\&.
 .LP
 .RE
 .IP
-Note that some tape devices do compression and this option has nothing to do with whether that is used\&. If hardware compression is used (usually via a particular tape device name or \fBmt\fR option), \fBAMANDA\fR (software) compression should be disabled\&.
+Note that some tape devices do compression and this option has nothing to do with whether that is used\&. If hardware compression is used (usually via a particular tape device name or \fBmt\fR option), \fBAmanda\fR (software) compression should be disabled\&.
 
 .TP
 \fBdumpcycle\fR \fB int\fR
-Default: \fB10 days\fR\&. The number of days in the backup cycle\&. Each disk using this set of options will get a full backup at least this often\&. Setting this to zero tries to do a full backup each run\&.
+Default: \fB10 days\fR\&. The number of days in the backup cycle\&. Each disk using this set of options will get a full backup at least this of ten\&. Setting this to zero tries to do a full backup each run\&.
+
+.TP
+\fBencrypt [none|client|server]\fR
+Default: \fBnone\fR\&. To encrypt backup images, it can do so either on the backup client host before it crosses the network or on the tape server host as it goes from the network into the holding disk or to tape\&.
+
+So the \fBencrypt\fR options line may be one of:
+
+.RS
+.TP 3
+\(bu
+encrypt none
+.TP
+\(bu
+encrypt client
+
+Specify client_encrypt "PROG"
+
+PROG must not contain white space\&.
+
+Specify client_decrypt_option "decryption\-parameter" Default: "\-d"
+
+decryption\-parameter must not contain white space\&.
+
+(See dumptype encrypt\-fast in example/amanda\&.conf for reference)
+.TP
+\(bu
+encrypt server
+
+Specify server_encrypt "PROG"
+
+PROG must not contain white space\&.
+
+Specify server_decrypt_option "decryption\-parameter" Default: "\-d"
+
+decryption\-parameter must not contain white space\&.
+.LP
+.RE
+.IP
+
+.PP
+Note that current logic assumes compression then encryption during backup(thus decrypt then uncompress during restore)\&. So specifying client\-encryption AND server\-compression is not supported\&. \fBamcrypt\fR which is a wrapper of \fBaespipe\fR is provided as a reference encryption program\&.
 
 .TP
 \fBestimate\fR \fBclient|calcsize|server\fR
-Default: \fBclient\fR\&. Determine the way \fBAMANDA\fR does it's estimate\&.
+Default: \fBclient\fR\&. Determine the way \fBAmanda\fR does it's estimate\&.
 
 .RS
 .TP 3
@@ -552,10 +675,12 @@ Use only statistics from the previous run to give an estimate, it takes only a f
 
 .TP
 \fBexclude\fR [ \fBlist|file\fR ][[optional][ \fBappend\fR ][ \fB string\fR ]+]
-Default: \fBfile\fR\&. There are two exclude lists, \fBexclude file\fR and \fBexclude list\&.\fR With \fBexclude file\fR , the \fBstring\fR is a \fBGNU\-tar\fR exclude expression\&. With \fBexclude list\fR , the \fBstring\fR is a file name on the client containing \fBGNU\-tar\fR exclude expressions\&.
+Default: \fBfile\fR\&. There are two exclude lists, \fBexclude file\fR and \fBexclude list\&.\fR With \fBexclude file\fR , the \fBstring\fR is a \fBGNU\-tar\fR exclude expression\&. With \fBexclude list\fR , the \fBstring\fR is a file name on the client containing \fBGNU\-tar\fR exclude expressions\&. The path to the specified exclude list file, if present (see description of 'optional' below), must be readable by the \fBAmanda\fR user\&.
 
 All exclude expressions are concatenated in one file and passed to \fBGNU\-tar\fR as an \fB\-\-exclude\-from\fR argument\&.
 
+Exclude expressions must always be specified as relative to the head directory of the DLE\&.
+
 With the \fBappend\fR keyword, the \fBstring\fR is appended to the current list, without it, the \fBstring\fR overwrites the list\&.
 
 If \fBoptional\fR is specified for \fBexclude list\fR, then amcheck will not complain if the file doesn't exist or is not readable\&.
@@ -570,7 +695,7 @@ the actual file used would be \fI/var/\&.amanda\&.excludes\fR for a backup of \f
 
 .TP
 \fBholdingdisk\fR \fB boolean\fR
-Default: \fByes\fR\&. Whether a holding disk should be used for these backups or whether they should go directly to tape\&. If the holding disk is a portion of another file system that \fBAMANDA\fR is backing up, that file system should refer to a dumptype with \fBholdingdisk\fR set to \fBno\fR to avoid backing up the holding disk into itself\&.
+Default: \fByes\fR\&. Whether a holding disk should be used for these backups or whether they should go directly to tape\&. If the holding disk is a portion of another file system that \fBAmanda\fR is backing up, that file system should refer to a dumptype with \fBholdingdisk\fR set to \fBno\fR to avoid backing up the holding disk into itself\&.
 
 .TP
 \fBignore\fR \fB boolean\fR
@@ -580,8 +705,16 @@ Default: \fBno\fR\&. Whether disks associated with this backup type should be ba
 \fBinclude\fR [ \fBlist|file\fR ][[optional][ \fBappend\fR ][ \fB string\fR ]+]
 Default: \fBfile\fR "\&."\&. There are two include lists, \fBinclude file\fR and \fBinclude list\&.\fR With \fBinclude file\fR , the \fBstring\fR is a glob expression\&. With \fBinclude list\fR , the \fBstring\fR is a file name on the client containing glob expressions\&.
 
-All include expressions are expanded by \fBAMANDA\fR, concatenated in one file and passed to \fBGNU\-tar\fR as a \fB\-\-files\-from\fR argument\&. They must start with "\&./" and contain no other "/"\&.
+All include expressions are expanded by \fBAmanda\fR, concatenated in one file and passed to \fBGNU\-tar\fR as a \fB\-\-files\-from\fR argument\&. They must start with "\&./" and contain no other "/"\&.
+
+Include expressions must always be specified as relative to the head directory of the DLE\&.
+
 
+.RS
+.Sh "Note"
+For globbing to work at all, even the limited single level, 
+the top level directory of the DLE must be readable by the \fBAmanda\fR user\&.
+.RE
 With the \fBappend\fR keyword, the \fBstring\fR is appended to the current list, without it, the \fBstring\fR overwrites the list\&.
 
 If \fBoptional\fR is specified for \fBinclude list,\fR then amcheck will not complain if the file doesn't exist or is not readable\&.
@@ -598,7 +731,7 @@ Default: \fBno\fR\&. Whether the backup image should be encrypted by Kerberos as
 
 .TP
 \fBmaxdumps\fR \fB int\fR
-Default: 1\&. The maximum number of backups from a single host that \fBAMANDA\fR will attempt to run in parallel\&. See also the main section parameter \fBinparallel\fR\&.
+Default: 1\&. The maximum number of backups from a single host that \fBAmanda\fR will attempt to run in parallel\&. See also the main section parameter \fBinparallel\fR\&.
 
 .TP
 \fBmaxpromoteday\fR \fB int\fR
@@ -606,7 +739,7 @@ Default: 10000\&. The maximum number of day for a promotion, set it 0 if you don
 
 .TP
 \fBpriority\fR \fB string\fR
-Default: \fBmedium\fR\&. When there is no tape to write to, \fBAMANDA\fR will do incremental backups in priority order to the holding disk\&. The priority may be high (2), medium (1), low (0) or a number of your choice\&.
+Default: \fBmedium\fR\&. When there is no tape to write to, \fBAmanda\fR will do incremental backups in priority order to the holding disk\&. The priority may be high (2), medium (1), low (0) or a number of your choice\&.
 
 .TP
 \fBprogram\fR \fB string\fR
@@ -618,7 +751,7 @@ Default: \fByes\fR\&. Whether to ask the backup program to update its database (
 
 .TP
 \fBskip\-full\fR \fB boolean\fR
-Default: \fBno\fR\&. If \fBtrue\fR and \fBplanner\fR has scheduled a full backup, these disks will be skipped, and full backups should be run off\-line on these days\&. It was reported that \fBAMANDA\fR only schedules level 1 incrementals in this configuration; this is probably a bug\&.
+Default: \fBno\fR\&. If \fBtrue\fR and \fBplanner\fR has scheduled a full backup, these disks will be skipped, and full backups should be run off\-line on these days\&. It was reported that \fBAmanda\fR only schedules level 1 incrementals in this configuration; this is probably a bug\&.
 
 .TP
 \fBskip\-incr\fR \fB boolean\fR
@@ -636,7 +769,7 @@ Default: \fBstandard\fR\&. Strategy to use when planning what level of backup to
 
 .TP
 \fBstandard\fR
-The standard \fBAMANDA\fR schedule\&.
+The standard \fBAmanda\fR schedule\&.
 
 .TP
 \fBnofull\fR
@@ -652,13 +785,25 @@ Never do backups (useful when sharing the \fBdisklist\fR file)\&.
 
 .TP
 \fBincronly\fR
-Only do incremental dumps\&. \fBamadmin force\fR should be used to tell \fBAMANDA\fR that a full dump has been performed off\-line, so that it resets to level 1\&. It is similar to skip\-full, but with incronly full dumps may be scheduled manually\&. Unfortunately, it appears that \fBAMANDA\fR will perform full backups with this configuration, which is probably a bug\&.
+Only do incremental dumps\&. \fBamadmin force\fR should be used to tell \fBAmanda\fR that a full dump has been performed off\-line, so that it resets to level 1\&. It is similar to skip\-full, but with incronly full dumps may be scheduled manually\&. Unfortunately, it appears that \fBAmanda\fR will perform full backups with this configuration, which is probably a bug\&.
 
 .RE
 .IP
 
+.TP
+\fBtape_splitsize\fR \fB int\fR
+Default: \fBnone\fR\&. Split dump file on tape into pieces of a specified size\&. This allows dumps to be spread across multiple tapes, and can potentially make more efficient use of tape space\&. Note that if this value is too large (more than half the size of the average dump being split), substantial tape space can be wasted\&. If too small, large dumps will be split into innumerable tiny dumpfiles, adding to restoration complexity\&. A good rule of thumb, usually, is 1/10 of the size of your tape\&.
+
+.TP
+\fBsplit_diskbuffer\fR \fB string\fR
+Default: \fBnone\fR\&. When dumping a split dump in PORT\-WRITE mode (usually meaning "no holding disk"), buffer the split chunks to a file in the directory specified by this option\&.
+
+.TP
+\fBfallback_splitsize\fR \fB int\fR
+Default: \fB10M\fR\&. When dumping a split dump in PORT\-WRITE mode, if no split_diskbuffer is specified (or if we somehow fail to use our split_diskbuffer), we must buffer split chunks in memory\&. This specifies the maximum size split chunks can be in this scenario, and thus the maximum amount of memory consumed for in\-memory splitting\&. The size of this buffer can be changed from its (very conservative) default to a value reflecting the amount of memory that each taper process on the dump server may reasonably consume\&.
+
 .PP
-The following \fBdumptype\fR entries are predefined by \fBAMANDA\fR:
+The following \fBdumptype\fR entries are predefined by \fBAmanda\fR:
 .nf
 
 define dumptype no\-compress {
@@ -708,7 +853,7 @@ define dumptype testing {
 .fi
 
 .PP
-\fBAMANDA\fR provides a \fBdumptype\fR named \fBglobal\fR in the sample \fBamanda\&.conf\fR file that all \fBdumptype\fRs should reference\&. This provides an easy place to make changes that will affect every \fBdumptype\fR\&.
+\fBAmanda\fR provides a \fBdumptype\fR named \fBglobal\fR in the sample \fBamanda\&.conf\fR file that all \fBdumptype\fRs should reference\&. This provides an easy place to make changes that will affect every \fBdumptype\fR\&.
 
 .SH "TAPETYPE SECTION"
 
@@ -740,15 +885,15 @@ Default: \fB1000 bytes\fR\&. How large a file mark (tape mark) is, measured in b
 \fBlength\fR \fB int\fR
 Default: \fB2000 kbytes\fR\&. How much data will fit on a tape\&.
 
-Note that this value is only used by \fBAMANDA\fR to schedule which backups will be run\&. Once the backups start, \fBAMANDA\fR will continue to write to a tape until it gets an error, regardless of what value is entered for \fBlength\fR (but see the section OUTPUT DRIVERS in the \fBamanda\fR(8) manpage for exceptions)\&.
+Note that this value is only used by \fBAmanda\fR to schedule which backups will be run\&. Once the backups start, \fBAmanda\fR will continue to write to a tape until it gets an error, regardless of what value is entered for \fBlength\fR (but see the section OUTPUT DRIVERS in the \fBamanda\fR(8) manpage for exceptions)\&.
 
 .TP
 \fBblocksize\fR \fB int\fR
-Default: \fB32\fR\&. How much data will be written in each tape record expressed in KiloBytes\&. The tape record size (= blocksize) can not be reduced below the default 32 KBytes\&. The parameter blocksize can only be raised if \fBAMANDA\fR was compiled with the configure option \-\-with\-maxtapeblocksize=N set with "N" greater than 32 during \fBconfigure\fR\&.
+Default: \fB32\fR\&. How much data will be written in each tape record expressed in KiloBytes\&. The tape record size (= blocksize) can not be reduced below the default 32 KBytes\&. The parameter blocksize can only be raised if \fBAmanda\fR was compiled with the configure option \-\-with\-maxtapeblocksize=N set with "N" greater than 32 during \fBconfigure\fR\&.
 
 .TP
 \fBfile\-pad\fR \fB boolean\fR
-Default: \fBtrue\fR\&. If true, every record, including the last one in the file, will have the same length\&. This matches the way \fBAMANDA\fR wrote tapes prior to the availability of this parameter\&. It may also be useful on devices that only support a fixed blocksize\&.
+Default: \fBtrue\fR\&. If true, every record, including the last one in the file, will have the same length\&. This matches the way \fBAmanda\fR wrote tapes prior to the availability of this parameter\&. It may also be useful on devices that only support a fixed blocksize\&.
 
 Note that the last record on the tape probably includes trailing null byte padding, which will be passed back to \fBgzip\fR, \fBcompress\fR or the restore program\&. Most programs just ignore this (although possibly with a warning)\&.
 
@@ -756,11 +901,11 @@ If this parameter is false, the last record in a file may be shorter than the bl
 
 .TP
 \fBspeed\fR \fB int\fR
-Default: \fB200 bps\fR\&. How fast the drive will accept data, in bytes per second\&. This parameter is NOT currently used by \fBAMANDA\fR\&.
+Default: \fB200 bps\fR\&. How fast the drive will accept data, in bytes per second\&. This parameter is NOT currently used by \fBAmanda\fR\&.
 
 .TP
 \fBlbl\-templ\fR \fB string\fR
-A PostScript template file used by \fBamreport\fR to generate labels\&. Several sample files are provided with the \fBAMANDA\fR sources in the \fBexample\fR directory\&. See the \fBamreport\fR(8) man page for more information\&.
+A PostScript template file used by \fBamreport\fR to generate labels\&. Several sample files are provided with the \fBAmanda\fR sources in the \fBexample\fR directory\&. See the \fBamreport\fR(8) man page for more information\&.
 
 .PP
 In addition to options, another \fBtapetype\fR name may be entered, which makes this \fBtapetype\fR inherit options from another \fBtapetype\fR\&. For instance, the only difference between a DLT4000 tape drive using Compact\-III tapes and one using Compact\-IV tapes is the length of the tape\&. So they could be entered as:
@@ -795,7 +940,7 @@ define interface \fBname\fR {
 \fBname\fR is the name of this type of network interface\&. It is referenced from the \fBdisklist\fR file\&.
 
 .PP
-Note that these sections define network interface characteristics, not the actual interface that will be used\&. Nor do they impose limits on the bandwidth that will actually be taken up by \fBAMANDA\fR\&. \fBAMANDA\fR computes the estimated bandwidth each file system backup will take based on the estimated size and time, then compares that plus any other running backups with the limit as another of the criteria when deciding whether to start the backup\&. Once a backup starts, \fBAMANDA\fR will use as much of the network as it can leaving throttling up to the operating system and network hardware\&.
+Note that these sections define network interface characteristics, not the actual interface that will be used\&. Nor do they impose limits on the bandwidth that will actually be taken up by \fBAmanda\fR\&. \fBAmanda\fR computes the estimated bandwidth each file system backup will take based on the estimated size and time, then compares that plus any other running backups with the limit as another of the criteria when deciding whether to start the backup\&. Once a backup starts, \fBAmanda\fR will use as much of the network as it can leaving throttling up to the operating system and network hardware\&.
 
 .PP
 The interface options and values are:
@@ -817,10 +962,10 @@ In addition to options, another \fBinterface\fR name may be entered, which makes
 James da Silva, <jds@amanda\&.org>: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion, major update, splitting
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion, major update, splitting
 
 .SH "SEE ALSO"
 
 .PP
- \fBamanda\fR(8),
+ \fBamanda\fR(8), \fBamcrypt\fR(8), \fBaespipe\fR(1),
 
index 75cb5c88397ff6f324145d36c3ab799425ffc344..e9723af5ff12342d009b5cd71db33f6c425cf619 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMCHECK" 8 "" "" ""
 .SH NAME
-amcheck \- run AMANDA self-checks
+amcheck \- run Amanda self-checks
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,7 +31,7 @@ amcheck \- run AMANDA self-checks
 .SH "DESCRIPTION"
 
 .PP
-\fBAmcheck\fR runs a number of self\-checks on both the \fBAMANDA\fR tape server host and the \fBAMANDA\fR client hosts\&.
+\fBAmcheck\fR runs a number of self\-checks on both the \fBAmanda\fR tape server host and the \fBAmanda\fR client hosts\&.
 
 .PP
 On the tape server host, \fBamcheck\fR can go through the same tape checking used at the start of the nightly \fBamdump\fR run to verify the correct tape for the next run is mounted\&.
@@ -43,7 +43,7 @@ On the tape server host, \fBamcheck\fR can go through the same tape checking use
 You can specify many host/disk expressions, only disks that match an expression will be checked\&. All disks are checked if no expressions are given\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -65,7 +65,7 @@ Run the tape tests on the server host\&.
 
 .TP
 \fB\-w\fR
-Enables a destructive check for write\-protection on the tape (which would otherwise cause the subsequent \fBamdump\fR to fail)\&. If the tape is writable, this check causes all data after the tape label to be erased (actually depends on the device driver: there is no portable non\-destructive way to check for write\-protection)\&. The check implies \fB\-t\fR and is only made if the tape is otherwise correct\&.
+Enables a DESTRUCTIVE check for write\-protection on the tape (which would otherwise cause the subsequent \fBamdump\fR to fail)\&. If the tape is writable, this check causes all data after the tape label to be erased\&. If the label_new_tapes option is enabled, this check may ERASE any non\-Amanda tape in the drive or changer\&. The check implies \fB\-t\fR and is only made if the tape is otherwise correct\&.
 
 .TP
 \fB\-m\fR
@@ -89,21 +89,21 @@ In this example, both the tape server and client tests are run\&. The results ar
 .nf
 
 % amcheck daily
-\fBAMANDA\fR Tape Server Host Check
+\fBAmanda\fR Tape Server Host Check
 \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
 /amanda2/amanda/work: 911475 KB disk space available, that's plenty\&.
 NOTE: skipping tape\-writable test\&.
 Tape VOL10 label ok\&.
 Server check took 34\&.966 seconds\&.
 
-\fBAMANDA\fR Backup Client Hosts Check
+\fBAmanda\fR Backup Client Hosts Check
 \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
 WARNING: northstar: selfcheck request timed out\&.  Host down?
 WARNING: drinkme: selfcheck request timed out\&.  Host down?
 WARNING: scruffy: selfcheck request timed out\&.  Host down?
 Client check: 136 hosts checked in 51\&.945 seconds, 3 problems found\&.
 
-(brought to you by \fBAMANDA\fR 2\&.4\&.5
+(brought to you by \fBAmanda\fR 2\&.5\&.0
 .fi
 
 .PP
@@ -166,7 +166,7 @@ ERROR: running as user \fBrunuser\fR instead of \fBdumpuser\fR
 
 .TP
 ERROR: program dir \fBdirectory\fR: not accessible
-(error) The directory \fBAMANDA\fR expects to find its auxiliary programs in, \fBdirectory\fR, is not accessible\&.
+(error) The directory \fBAmanda\fR expects to find its auxiliary programs in, \fBdirectory\fR, is not accessible\&.
 
 .TP
 ERROR: program \fBprogram\fR: does not exist
@@ -192,7 +192,7 @@ ERROR: \fBXXX\fR dir \fBdirectory\fR: not writable
 
 .TP
 log
-for the \fBAMANDA\fR log directory (see \fBlogdir\fR in \fBamanda\&.conf\fR)
+for the \fBAmanda\fR log directory (see \fBlogdir\fR in \fBamanda\&.conf\fR)
 
 .TP
 oldlog
@@ -200,15 +200,15 @@ for the directory that holds the old log files (see \fBlogdir\fR in \fBamanda\&.
 
 .TP
 info
-for an \fBAMANDA\fR database information directory (see \fBcurinfo\fR in \fBamanda\&.conf\fR) or
+for an \fBAmanda\fR database information directory (see \fBcurinfo\fR in \fBamanda\&.conf\fR) or
 
 .TP
 index
-for an \fBAMANDA\fR index directory (see \fBindexdir\fR in \fBamanda\&.conf\fR)
+for an \fBAmanda\fR index directory (see \fBindexdir\fR in \fBamanda\&.conf\fR)
 
 .TP
 tapelist
-for the \fBAMANDA\fR tapelist directory (see \fBtapelist\fR in \fBamanda\&.conf\fR)
+for the \fBAmanda\fR tapelist directory (see \fBtapelist\fR in \fBamanda\&.conf\fR)
 
 .RE
 .IP
@@ -243,15 +243,15 @@ ERROR: log file \fIfile\fR: not writable
 
 .TP
 ERROR: tape list \fBtapelist\fR: not writable
-(error) \fBAMANDA\fR tape list file \fBtapelist\fR (see \fBtapelist\fR in \fBamanda\&.conf\fR) is not writable or was not found\&.
+(error) \fBAmanda\fR tape list file \fBtapelist\fR (see \fBtapelist\fR in \fBamanda\&.conf\fR) is not writable or was not found\&.
 
 .TP
 ERROR: tape list \fBtapelist\fR: parse error
-(error) \fBAMANDA\fR tape list file \fBtapelist\fR (see \fBtapelist\fR in \fBamanda\&.conf\fR) could not be read or parsed\&.
+(error) \fBAmanda\fR tape list file \fBtapelist\fR (see \fBtapelist\fR in \fBamanda\&.conf\fR) could not be read or parsed\&.
 
 .TP
 WARNING: tapedev is /dev/null, dumps will be thrown away
-(warning) The \fBtapedev\fR parameter in \fBamanda\&.conf\fR is set to \fI/dev/null\fR and \fBAMANDA\fR uses that when debugging to throw all the dump images away\&.
+(warning) The \fBtapedev\fR parameter in \fBamanda\&.conf\fR is set to \fI/dev/null\fR and \fBAmanda\fR uses that when debugging to throw all the dump images away\&.
 
 .TP
 WARNING: hold file \fIfile\fR exists
@@ -288,7 +288,7 @@ WARNING: holding disk \fBdisk\fR: only \fBF\fR KB free, using nothing
 
 .TP
 Holding disk \fBdisk\fR: \fBF\fR KB disk space available, using \fBU\fR KB
-(info) Holding disk \fBdisk\fR has \fBF\fR KBytes of free space and \fBAMANDA\fR will be using up to \fBU\fR Kbytes\&.
+(info) Holding disk \fBdisk\fR has \fBF\fR KBytes of free space and \fBAmanda\fR will be using up to \fBU\fR Kbytes\&.
 
 .TP
 WARNING: if a tape changer is not available, runtapes must be set to 1\&.
@@ -331,7 +331,7 @@ NOTE: skipping tape\-writable test\&.
 (info) The tape write test (see the \fB\-w\fR option) was not enabled\&.
 
 .TP
-WARNING: skipping tape test because amdump or amflush seem to be running, WARNING: if they are not, you must run amcleanup
+WARNING: skipping tape test because amdump or amflush seem to be running, WARNING: if they are not, you must run amcleanup
 (warning) It looked to \fBamcheck\fR like either \fBamdump\fR or \fBamflush\fR were running because a log file or amdump file exists\&. If they are not running, you probably need to run \fBamcleanup\fR to clear up a previous failure\&. Otherwise, you need to wait until they complete before running \fBamcheck\fR\&.
 
 .TP
@@ -368,7 +368,7 @@ ERROR: \fBhost\fR NAK: \fBmessage\fR
 
 .TP
 ERROR: \fBhost\fR NAK: [NAK parse failed]
-(error) \fBAmcheck\fR could not parse the negative acknowledgment error from \fBhost\fR\&. There might be an \fBAMANDA\fR version mismatch between the host running \fBamcheck\fR and \fBhost\fR\&.
+(error) \fBAmcheck\fR could not parse the negative acknowledgment error from \fBhost\fR\&. There might be an \fBAmanda\fR version mismatch between the host running \fBamcheck\fR and \fBhost\fR\&.
 
 .TP
 ERROR: \fBhost\fR [mutual\-authentication failed]
@@ -384,7 +384,7 @@ ERROR: \fBhost\fR: \fBmessage\fR
 James da Silva, <jds@amanda\&.org> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index d5f4b4c8c74de7185f47bcf7eb935746187aff7f..d4701b144a20e2ded3b0490d1240420854eb4bfb 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMCHECKDB" 8 "" "" ""
 .SH NAME
-amcheckdb \- check AMANDA database for tape consistency
+amcheckdb \- check Amanda database for tape consistency
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,10 +31,10 @@ amcheckdb \- check AMANDA database for tape consistency
 .SH "DESCRIPTION"
 
 .PP
-\fBAmcheckdb\fR verifies that every tape mentioned in the \fBAMANDA\fR database is still valid in the \fBtapelist\fR file\&.
+\fBAmcheckdb\fR verifies that every tape mentioned in the \fBAmanda\fR database is still valid in the \fBtapelist\fR file\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "EXAMPLE"
 
@@ -61,7 +61,7 @@ Ready\&.
 Adrian T\&. Filipi\-Martin <atf3r@cs\&.virginia\&.edu>: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index d9246055b66a7a6378a559603c89ccf1bc896e78..931909dfcbbe9d361826f608c60f7afff78f45af 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMCLEANUP" 8 "" "" ""
 .SH NAME
-amcleanup \- run the AMANDA cleanup process after a failure
+amcleanup \- run the Amanda cleanup process after a failure
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,22 +31,22 @@ amcleanup \- run the AMANDA cleanup process after a failure
 .SH "DESCRIPTION"
 
 .PP
-\fBAmcleanup\fR generates the \fB\fBAMANDA\fR Mail Report\fR and updates the \fBAMANDA\fR databases after a system failure on a tape server host\&. This cleanup process is normally done automatically as part of the \fBamdump\fR program, but if \fBamdump\fR cannot complete for some reason (usually because of a tape server host crash), \fBamcleanup\fR must be run some time later (usually during system boot)\&.
+\fBAmcleanup\fR generates the \fB\fBAmanda\fR Mail Report\fR and updates the \fBAmanda\fR databases after a system failure on a tape server host\&. This cleanup process is normally done automatically as part of the \fBamdump\fR program, but if \fBamdump\fR cannot complete for some reason (usually because of a tape server host crash), \fBamcleanup\fR must be run some time later (usually during system boot)\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "EXAMPLES"
 
 .PP
-This example runs the \fBAMANDA\fR cleanup process by hand after a failure\&.
+This example runs the \fBAmanda\fR cleanup process by hand after a failure\&.
 .nf
 
 % amcleanup daily
 .fi
 
 .PP
-Putting the following line in a system boot script (e\&.g\&. \fI/etc/rc\&.local\fR) runs the \fBAMANDA\fR cleanup process as part of the reboot, eliminating the need to run it by hand\&.
+Putting the following line in a system boot script (e\&.g\&. \fI/etc/rc\&.local\fR) runs the \fBAmanda\fR cleanup process as part of the reboot, eliminating the need to run it by hand\&.
 .nf
 
 /usr/local/sbin/amcleanup daily
@@ -65,7 +65,7 @@ amcleanup: no unprocessed logfile to clean up\&.
 James da Silva, <jds@amanda\&.org>: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
diff --git a/man/amcrypt.8 b/man/amcrypt.8
new file mode 100644 (file)
index 0000000..4cf34d9
--- /dev/null
@@ -0,0 +1,77 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "AMCRYPT" 8 "" "" ""
+.SH NAME
+amcrypt \- reference crypt program for Amanda symmetric data encryption
+.SH "SYNOPSIS"
+.ad l
+.hy 0
+.HP 8
+\fBamcrypt\fR
+.ad
+.hy
+
+.SH "DESCRIPTION"
+
+.PP
+ \fBamcrypt\fR requires \fBaespipe\fR and \fBgpg\fR to work\&. Aespipe is available from : http://loop-aes.sourceforge.net
+
+.PP
+ \fBamcrypt\fR will search for the aespipe program in the following directories: /usr/bin:/usr/local/bin:/sbin:/usr/sbin\&.
+\fBamcrypt\fR calls  \fBamaespipe\fR and pass the
+\fBpassphrase\fR through file descriptor 3\&.
+The passphrase should be stored in ~amanda/\&.am_passphrase\&.
+
+.SH "HOW TO CREATE ENCRYPTION KEYS FOR AMCRYPT"
+
+1\&. Create 65 random encryption keys and encrypt those keys using gpg\&. Reading
+from /dev/random may take indefinitely long if kernel's random entropy pool
+is empty\&. If that happens, do some other work on some other console (use
+keyboard, mouse and disks)\&. 
+
+.PP
+head \-c 2925 /dev/random | uuencode \-m \- | head \-n 66 | tail \-n 65 \\ | gpg \-\-symmetric \-a > ~amanda/\&.gnupg/am_key\&.gpg
+
+.PP
+This will ask for a passphrase\&. Remember this passphrase as you will need it in the next step\&.
+
+.PP
+2\&. Store the passphrase inside the home\-directory of the AMANDA\-user and protect it with proper permissions:
+.nf
+
+echo my_secret_passphrase > ~amanda/\&.am_passphrase
+chown amanda:disk ~amanda/\&.am_passphrase
+chmod 700 ~amanda/\&.am_passphrase
+.fi
+
+.SH "KEY AND PASSPHRASE"
+
+.PP
+ \fBamcrypt\fR uses the same key to encrypt and decrypt data\&.
+
+It is very important to store and protect the key and the passphrase
+properly\&. Encrypted backup data can \fBonly\fR be recovered with the correct key and
+passphrase\&.
+
+.SH "SEE ALSO"
+
+.PP
+\fBamanda\fR(8), \fBamanda\&.conf\fR(5), \fBaespipe\fR(1), \fBamaespipe\fR(8), \fBgpg\fR(1) 
+
index 39e8f183115281f9e32678d56ed9de537f733497..afb8c0dadcae71987b5e2d761cfb6030ab9dfc48 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMDD" 8 "" "" ""
 .SH NAME
-amdd \- AMANDA version of dd
+amdd \- Amanda version of dd
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,13 +31,13 @@ amdd \- AMANDA version of dd
 .SH "DESCRIPTION"
 
 .PP
-\fBAmdd\fR provides just enough of the standard UNIX \fBdd\fR command for the needs of \fBAMANDA\fR\&. This is handy when doing a full restore and the standard \fBdd\fR program has not yet been found\&.
+\fBAmdd\fR provides just enough of the standard UNIX \fBdd\fR command for the needs of \fBAmanda\fR\&. This is handy when doing a full restore and the standard \fBdd\fR program has not yet been found\&.
 
 .PP
-\fBAmdd\fR also provides access to the \fBAMANDA\fR output drivers that support various tape simulations\&. This may be used for debugging or to convert from one format to another\&.
+\fBAmdd\fR also provides access to the \fBAmanda\fR output drivers that support various tape simulations\&. This may be used for debugging or to convert from one format to another\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&. See the \fBOUTPUT DRIVERS\fR section of \fBamanda(8)\fR for more information on the \fBAMANDA\fR output drivers\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&. See the \fBOUTPUT DRIVERS\fR section of \fBamanda(8)\fR for more information on the \fBAmanda\fR output drivers\&.
 
 .SH "OPTIONS"
 
@@ -99,7 +99,7 @@ Number of records to skip before copying input to output\&. Default is zero\&.
 Marc Mengel <mengel@fnal\&.gov>, John R\&. Jackson <jrj@purdue\&.edu> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index f571ab6700bf2fb05e46a6de7fcd8b13c47560c6..e58c3f72713ae46d767d6e7f4b1d0edc9303773c 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMDUMP" 8 "" "" ""
 .SH NAME
-amdump \- back up all disks in an AMANDA configuration
+amdump \- back up all disks in an Amanda configuration
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,7 +31,7 @@ amdump \- back up all disks in an AMANDA configuration
 .SH "DESCRIPTION"
 
 .PP
-\fBAmdump\fR switches to the appropriate \fBAMANDA\fR configuration directory, e\&.g\&. /usr/local/etc/amanda/\fBconfig\fR, then attempts to back up every disk specified by the \fBamanda\&.conf\fR file\&. \fBAmdump\fR is normally run by \fBcron\fR\&.
+\fBAmdump\fR switches to the appropriate \fBAmanda\fR configuration directory, e\&.g\&. /usr/local/etc/amanda/\fBconfig\fR, then attempts to back up every disk specified by the \fBamanda\&.conf\fR file\&. \fBAmdump\fR is normally run by \fBcron\fR\&.
 
 .PP
 You can specify many host/disk expressions, only disks that match an expression will be dumped\&. All disks are dumped if no expressions are given\&.
@@ -40,7 +40,7 @@ You can specify many host/disk expressions, only disks that match an expression
 If the file /usr/local/etc/amanda/\fBconfig\fR/hold exists, \fBamdump\fR will wait until it is removed before starting the backups\&. This allows scheduled backups to be delayed when circumstances warrant, for example, if the tape device is being used for some other purpose\&. While waiting, \fBamdump\fR checks for the hold file every minute\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "EXAMPLE"
 
@@ -70,7 +70,7 @@ Amdump detected another \fBamdump\fR or \fBamflush\fR running, or the remains of
 James da Silva, <jds@amanda\&.org> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
diff --git a/man/amfetchdump.8 b/man/amfetchdump.8
new file mode 100644 (file)
index 0000000..8aa2616
--- /dev/null
@@ -0,0 +1,173 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "AMFETCHDUMP" 8 "" "" ""
+.SH NAME
+amfetchdump \- extract backup images from multiple Amanda tapes.
+.SH "SYNOPSIS"
+.ad l
+.hy 0
+.HP 12
+\fBamfetchdump\fR [\-pcClawns] [\-d\ \fIdevice\fR] [\-o\ \fIdirectory\fR] [\-i\ \fIlogfile\fR] [\-b\ \fIblocksize\fR] \fIconfig\fR \fIhostname\fR [\fIdisk\fR\ [\fIdate\fR\ [\fIlevel\fR\ [\fIhostname\fR\ [\&.\&.\&.]]]]]
+.ad
+.hy
+
+.SH "DESCRIPTION"
+
+.PP
+\fBAmfetchdump\fR pulls one or more matching dumps from tape or from the holding disk, handling the reassembly of multi\-tape split dump files as well as any tape autochanger operations\&.
+
+.PP
+It will automatically use the logs created by \fBamdump\fR(8) to locate available dumps on tape, in the same way that the \fBfind\fR feature of \fBamadmin\fR(8) lists available dumps\&. If these logs are unavailable, it can search tape\-by\-tape to find what it needs, and can generate new logs to serve as an emergency tape inventory\&.
+
+.PP
+The \fBhostname\fR, \fBdiskname\fR, \fBdatestamp\fR, and \fBlevel\fR dump pattern\-matching works as in \fBamrestore\fR(8), with the added requirement that at minimum a \fBhostname\fR must be specified when not in inventory mode\&.
+
+.PP
+Unless \fB\-p\fR is used, backup images are extracted to files in the current directory named:
+
+.PP
+\fBhostname\&.diskname\&.datestamp\&.dumplevel\fR
+
+.SH "OPTIONS"
+
+.TP
+\fB\-p\fR
+Pipe exactly one complete dump file to \fBstdout\fR, instead of writing the file to disk\&. This will restore only the first matching dumpfile (where "first" is determined by the dump log search facility)\&.
+
+.TP
+\fB\-d\fR \fIdevice\fR
+Restore from this tape device instead of the default\&.
+
+.TP
+\fB\-o\fR \fIdirectory\fR
+Output restored files to this directory, instead of to the current working directory\&.
+
+.TP
+\fB\-c\fR
+Compress output, fastest method available\&.
+
+.TP
+\fB\-C\fR
+Compress output, smallest file size method available\&.
+
+.TP
+\fB\-l\fR
+Leave dumps in the compressed/uncompressed state in which they were found on tape\&. By default, \fBamfetchdump\fR will automatically uncompress when restoring\&.
+
+.TP
+\fB\-a\fR
+Assume that all tapes are already available, via tape changer or otherwise, instead of prompting the operator to ensure that all tapes are loaded\&.
+
+.TP
+\fB\-i\fR \fIfilename\fR
+Generate an inventory of all dumps "seen" on the tapes we search, for later use as a log\&.
+
+.TP
+\fB\-w\fR
+Wait to put split dumps together until all chunks have been restored\&. Normally, \fBamfetchdump\fR will attempt to read pieces of a split file from tape in order, so that it can assemble them simply by appending each file to the first\&. This option disables the appending behavior, and instead restores each piece as an individual file and reassembles them only after all have been restored\&.
+
+
+.RS
+.Sh "Note"
+This requires at least double the size of your dump in free
+disk space, in order to build the final assembled dumpfile\&.
+.RE
+This behavior is implicitly invoked in circumstances where knowing the location of all dumps on tape in advance is not possible, such as when you are restoring without log files\&.
+
+.TP
+\fB\-n\fR
+Do not reassemble split dump files at all, just restore each piece as an individual file\&.
+
+.TP
+\fB\-s\fR
+Do not fast\-forward straight to needed files on tape\&. This will slow down most restores substantially\&. Only use this option if your tape drive does not properly support the fast\-forward operation\&.
+
+.TP
+\fB\-b\fR \fIblocksize\fR
+Force a particular block size when reading from tapes\&. This value will usually be autodetected, and should not normally need to be set\&.
+
+.SH "EXAMPLES"
+
+.PP
+All the examples here assume your configuration is called \fISetA\fR\&.
+
+.PP
+Here's a simple case, restoring all known dumps of the host vanya to the current working directory\&.
+
+.nf
+
+$ amfetchdump SetA vanya
+
+.fi
+
+.PP
+A more likely scenario involves restoring a particular dump from a particular date\&. We'll pipe this one to \fBGNU\-tar\fR as well, to automatically extract the dump\&.
+
+.nf
+
+$ amfetchdump \-p SetA vanya /home 20051020 | gtar \-xvpf \-
+
+.fi
+
+.PP
+In a situation where all of our dump logs have been wiped out, we could also use amfetchdump to inventory our tapes and recreate an imitation of those logs, which we'll send to \fBstdout\fR for casual perusal\&.   
+
+.nf
+
+$ amfetchdump \-i \- SetA
+
+.fi
+  
+
+.PP
+Note that you can specify a restore while in inventory mode, and \fBamfetchdump\fR will continue searching for more dumps from this host even after successfully restoring a dump, inventorying all the while\&. If your backup searcher has been trashed, this is a handy way to recover what you have\&.   
+
+.nf
+
+$ amfetchdump \-i /var/amanda/log SetA backupserver
+
+.fi
+  
+
+.SH "CAVEATS"
+\fBAmfetchdump\fR is dependent on accessing your server's config,
+tape changer, and (normally) dump logs\&. As such, it's not necessarily
+the most useful tool when those have all been wiped out and you
+desperately need to pull things from your tape\&. Pains have been taken
+to make it as capable as possible, but for seriously minimialist
+restores, look to
+\fBamrestore\fR(8)
+or
+\fBdd\fR(8)
+instead\&.
+
+.SH "AUTHOR"
+
+.PP
+John Stange, <building@nap\&.edu>, National Academies Press
+
+.PP
+Ian Turner, <ian@zmanda\&.com>: XML\-conversion
+
+.SH "SEE ALSO"
+
+.PP
+\fBamanda\fR(8), \fBamadmin\fR(8), \fBamrestore\fR(8), \fBtar\fR(1)  \fBrestore\fR(8)
+
index 9276731c58912e1ce34da981926161ec314646fb..f4051814a20426b72902e94035767c95a4d11c4a 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMFLUSH" 8 "" "" ""
 .SH NAME
-amflush \- flush AMANDA backup files from holding disk to tape
+amflush \- flush Amanda backup files from holding disk to tape
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,7 +31,7 @@ amflush \- flush AMANDA backup files from holding disk to tape
 .SH "DESCRIPTION"
 
 .PP
-\fBAmflush\fR writes \fBAMANDA\fR backups from the holding disks to tape, and updates the \fBAMANDA\fR info database and tapelist accordingly\&. Backups may stay in a holding disk when something is wrong with the tape at the time \fBamdump\fR is run\&. When this happens, the problem must be corrected and \fBamflush\fR run by hand\&.
+\fBAmflush\fR writes \fBAmanda\fR backups from the holding disks to tape, and updates the \fBAmanda\fR info database and tapelist accordingly\&. Backups may stay in a holding disk when something is wrong with the tape at the time \fBamdump\fR is run\&. When this happens, the problem must be corrected and \fBamflush\fR run by hand\&.
 
 .SH "OPTIONS"
 
@@ -55,10 +55,10 @@ specify a datestamp expression you want to flush, see the "DATESTAMP EXPRESSION"
 You can specify many host/disk expressions, only disks that match an expression will be flushed\&. All disks are flushed if no expressions are given\&. see the "HOST & DISK EXPRESSION" section of \fBamanda\fR(8) for a description\&.
 
 .PP
-\fBAmflush\fR will look in the holding disks specified by the \fBamanda\&.conf\fR file in /usr/local/etc/amanda/\fBconfig\fR for any non\-empty \fBAMANDA\fR work directories\&. It then prompts you to select a directory or to process all of the directories\&. The work directories in the holding disks are named by the date at the time \fBamdump\fR was run, e\&.g\&. 19910215\&.
+\fBAmflush\fR will look in the holding disks specified by the \fBamanda\&.conf\fR file in /usr/local/etc/amanda/\fBconfig\fR for any non\-empty \fBAmanda\fR work directories\&. It then prompts you to select a directory or to process all of the directories\&. The work directories in the holding disks are named by the date at the time \fBamdump\fR was run, e\&.g\&. 19910215\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "EXAMPLE"
 
@@ -68,10 +68,10 @@ See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
 
 % amflush daily
 Scanning /amanda\-hold\&.\&.\&.
-  20001113: found \fBAMANDA\fR directory\&.
-  20001114: found \fBAMANDA\fR directory\&.
+  20001113: found \fBAmanda\fR directory\&.
+  20001114: found \fBAmanda\fR directory\&.
 
-Multiple \fBAMANDA\fR directories, please pick one by letter:
+Multiple \fBAmanda\fR directories, please pick one by letter:
   A\&. 20001113
   B\&. 20001114
 Select directories to flush [A\&.\&.B]: [ALL] all
@@ -91,7 +91,7 @@ You'll get mail when amflush is finished\&.
 James da Silva, <jds@amanda\&.org> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index b13e40785c4cd5dfb8c3fbe8cf392af59d0f9e08..8fef610a059ec46db859fe596987b1ca92735634 100644 (file)
@@ -31,7 +31,7 @@ amgetconf \- look up amanda.conf variables
 .SH "DESCRIPTION"
 
 .PP
-\fBAmgetconf\fR looks up parameters in \fBamanda\&.conf\fR, the \fBAMANDA\fR configuration file, or from the build and runtime environment, and returns their corresponding value\&.
+\fBAmgetconf\fR looks up parameters in \fBamanda\&.conf\fR, the \fBAmanda\fR configuration file, or from the build and runtime environment, and returns their corresponding value\&.
 
 .PP
 If \fBconfig\fR is not specified, \fBamgetconf\fR assumes it is being run from the configuration directory and that \fBamanda\&.conf\fR is present\&.
@@ -40,13 +40,13 @@ If \fBconfig\fR is not specified, \fBamgetconf\fR assumes it is being run from t
 If \fBparameter\fR begins with \fBbuild\&.\fR, the (case insensitive) string following the period is a build environment variable\&. Variables without a value (e\&.g\&. \fBXFSDUMP\fR on a system that does not support that type of file system) will not report an error and will return an empty string as the value\&. Flag variables (e\&.g\&. \fBUSE_AMANDAHOSTS\fR) will return 1 if the flag is set or an empty string if it is not\&.
 
 .PP
-If \fBparameter\fR begins with \fBdbopen\&.\fR, the string following the period is a program name and an \fBAMANDA\fR debug file will be created for the caller\&. The name of the file is returned\&.
+If \fBparameter\fR begins with \fBdbopen\&.\fR, the string following the period is a program name and an \fBAmanda\fR debug file will be created for the caller\&. The name of the file is returned\&.
 
 .PP
 If \fBparameter\fR begins with \fBdbclose\&.\fR, the string following the period is a program name previously used with \fBdbopen\&.\fR, followed by a colon (:) and the previously opened file name\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "EXAMPLE"
 
index e4568aefc298b1b06fdd4eb9e7619ec169d10e73..a9a965cfa1c6d1b49095309d650e885de77230d8 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMLABEL" 8 "" "" ""
 .SH NAME
-amlabel \- label an AMANDA tape
+amlabel \- label an Amanda tape
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,27 +31,27 @@ amlabel \- label an AMANDA tape
 .SH "DESCRIPTION"
 
 .PP
-All \fBAMANDA\fR tapes must be pre\-labeled before they are used\&. \fBAMANDA\fR verifies the label in \fBamdump\fR and \fBamflush\fR before writing to make sure the proper tape is loaded\&.
+All \fBAmanda\fR tapes must be pre\-labeled before they are used\&. \fBAmanda\fR verifies the label in \fBamdump\fR and \fBamflush\fR before writing to make sure the proper tape is loaded\&.
 
 .PP
-\fBAmlabel\fR writes an \fBAMANDA\fR label on the tape in the device specified by the \fBamanda\&.conf\fR file in /usr/local/etc/amanda/\fBconfig\fR\&. \fBLabel\fR may be any string that does not contain whitespace and that matches the \fBamanda\&.conf\fR  \fBlabelstr\fR regular expression option\&. It is up to the system administrator to define a naming convention\&.
+\fBAmlabel\fR writes an \fBAmanda\fR label on the tape in the device specified by the \fBamanda\&.conf\fR file in /usr/local/etc/amanda/\fBconfig\fR\&. \fBLabel\fR may be any string that does not contain whitespace and that matches the \fBamanda\&.conf\fR  \fBlabelstr\fR regular expression option\&. It is up to the system administrator to define a naming convention\&.
 
 .PP
-\fBAmlabel\fR appends the new tape to the \fBtapelist\fR file so it will be used by \fBAMANDA\fR before it reuses any other tapes\&. When you \fBamlabel\fR multiple tapes, they will be used in the order you \fBamlabel\fR them\&.
+\fBAmlabel\fR appends the new tape to the \fBtapelist\fR file so it will be used by \fBAmanda\fR before it reuses any other tapes\&. When you \fBamlabel\fR multiple tapes, they will be used in the order you \fBamlabel\fR them\&.
 
 .PP
-\fBAmlabel\fR will not write the label if the tape contains an active \fBAMANDA\fR tape or if the label specified is on an active tape\&. The \fB\-f\fR (force) flag bypasses these verifications\&.
+\fBAmlabel\fR will not write the label if the tape contains an active \fBAmanda\fR tape or if the label specified is on an active tape\&. The \fB\-f\fR (force) flag bypasses these verifications\&.
 
 .PP
 An optional \fBslot\fR may be specified after the tape label\&. If a tape changer is in use, \fBamlabel\fR will label the tape in the specified slot instead of the currently loaded tape\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "EXAMPLE"
 
 .PP
-Write an \fBAMANDA\fR label with the string "DMP000" on the tape loaded in the device named in the \fBtapedev\fR option in /usr/local/etc/amanda/daily/amanda\&.conf:
+Write an \fBAmanda\fR label with the string "DMP000" on the tape loaded in the device named in the \fBtapedev\fR option in /usr/local/etc/amanda/daily/amanda\&.conf:
 .nf
 
 % amlabel daily DMP000 
@@ -72,7 +72,7 @@ Label \fBlabel\fR on the command line does not match the \fBlabelstr\fR regular
 
 .TP
 label \fBlabel\fR already on a tape
-Label \fBlabel\fR is already listed as an active \fBAMANDA\fR tape\&.
+Label \fBlabel\fR is already listed as an active \fBAmanda\fR tape\&.
 
 .TP
 no tpchanger specified in \fBpath\fR , so slot command invalid
@@ -80,15 +80,15 @@ The command line has the \fBslot\fR parameter but the \fBamanda\&.conf\fR file i
 
 .TP
 reading label \fBlabel\fR, tape is in another amanda configuration
-This tape appears to be a valid \fBAMANDA\fR tape, but label does not match \fBlabelstr\fR for this configuration so it is probably part of a different \fBAMANDA\fR configuration\&.
+This tape appears to be a valid \fBAmanda\fR tape, but label does not match \fBlabelstr\fR for this configuration so it is probably part of a different \fBAmanda\fR configuration\&.
 
 .TP
 reading label \fBlabel\fR, tape is active
-Tape \fBlabel\fR appears to already be part of this \fBAMANDA\fR configuration and active, i\&.e\&. has valid data on it\&.
+Tape \fBlabel\fR appears to already be part of this \fBAmanda\fR configuration and active, i\&.e\&. has valid data on it\&.
 
 .TP
 no label found, are you sure \fBtape\fR is non\-rewinding?
-While checking that the label was written correctly, \fBamlabel\fR got an error that might be caused by mis\-configuring \fBAMANDA\fR with a rewinding tape device name instead of a non\-rewinding device name for \fBtape\&.\fR
+While checking that the label was written correctly, \fBamlabel\fR got an error that might be caused by mis\-configuring \fBAmanda\fR with a rewinding tape device name instead of a non\-rewinding device name for \fBtape\&.\fR
 
 .SH "AUTHOR"
 
@@ -96,7 +96,7 @@ While checking that the label was written correctly, \fBamlabel\fR got an error
 James da Silva, <jds@amanda\&.org>: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index e6c3739cb9904750c8d2022d312419658f4dfe48..50ddffead73bfa8680f37d59b98bfc52f2df09b1 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMMT" 8 "" "" ""
 .SH NAME
-ammt \- AMANDA version of mt
+ammt \- Amanda version of mt
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,13 +31,13 @@ ammt \- AMANDA version of mt
 .SH "DESCRIPTION"
 
 .PP
-\fBAmmt\fR provides just enough of the standard UNIX \fBmt\fR command for the needs of \fBAMANDA\fR\&. This is handy when doing a full restore and the standard \fBmt\fR program has not yet been found\&.
+\fBAmmt\fR provides just enough of the standard UNIX \fBmt\fR command for the needs of \fBAmanda\fR\&. This is handy when doing a full restore and the standard \fBmt\fR program has not yet been found\&.
 
 .PP
-\fBAmmt\fR also provides access to the \fBAMANDA\fR output drivers that support various tape simulations\&.
+\fBAmmt\fR also provides access to the \fBAmanda\fR output drivers that support various tape simulations\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&. See the \fBOUTPUT DRIVERS\fR section of \fBamanda(8)\fR for more information on the \fBAMANDA\fR output drivers\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&. See the \fBOUTPUT DRIVERS\fR section of \fBamanda(8)\fR for more information on the \fBAmanda\fR output drivers\&.
 
 .SH "OPTIONS"
 
@@ -146,7 +146,7 @@ Many systems only report good data when a tape is in the drive and ready\&.
 Marc Mengel <mengel@fnal\&.gov>, John R\&. Jackson <jrj@purdue\&.edu>: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index 275d07624df24cf3b38489e3a2e12fb155cf0ad6..0cd2fb62169929557514333bfa69f2ec5e02f5f1 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMOVERVIEW" 8 "" "" ""
 .SH NAME
-amoverview \- display file systems processed by AMANDA over time
+amoverview \- display file systems processed by Amanda over time
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,10 +31,10 @@ amoverview \- display file systems processed by AMANDA over time
 .SH "DESCRIPTION"
 
 .PP
-\fBAmoverview\fR displays a chart showing hosts and file systems processed by \fBAMANDA\fR along with the backup level performed each day\&.
+\fBAmoverview\fR displays a chart showing hosts and file systems processed by \fBAmanda\fR along with the backup level performed each day\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -52,11 +52,11 @@ Set \fBdisk\fR field column width to \fBwidth\fR characters instead of 20\&.
 
 .TP
 \fB\-skipmissed\fR
-Compacts the output by only printing stats for the days \fBAMANDA\fR actually ran\&.
+Compacts the output by only printing stats for the days \fBAmanda\fR actually ran\&.
 
 .TP
 \fB\-last\fR
-Outputs the last status of each disk at the start Useful for long tapecycles and/or sparse reports\&.
+Outputs the last status of each disk at the start\&. Useful for long tapecycles and/or sparse reports\&.
 
 .TP
 \fB\-num0\fR
@@ -82,7 +82,7 @@ A number indicates the level of backup and it succeeded\&. An "E" indicates an e
 You can have an "E" followed by a number if a filesystem ran into end\-of\-tape once (gives an "E", and later that day, you flush it to a second tape (a number: the level, indicating success)\&. If the flush failed too, you get a double "EE" for that day\&.
 
 .PP
-You can also have a double code if you have two tapes in the changer and \fBAMANDA\fR failed to write to tape the first time because it hit end of tape (resulting in "E0", for a full, "E1" for an incremental etc\&.) or twice with error ("EE"), and may a successful flush afterwards giving maybe "EE0"\&. (Only the latest 2 characters are printed)\&.
+You can also have a double code if you have two tapes in the changer and \fBAmanda\fR failed to write to tape the first time because it hit end of tape (resulting in "E0", for a full, "E1" for an incremental etc\&.) or twice with error ("EE"), and may a successful flush afterwards giving maybe "EE0"\&. (Only the latest 2 characters are printed)\&.
 
 .SH "EXAMPLE"
 
index 450b9bed6033512fb27bbc116f6be3c1118e5bff..1021d737409c8c7a72e0065d95430d7ca630666f 100644 (file)
 ..
 .TH "AMPLOT" 8 "" "" ""
 .SH NAME
-amplot \- visualize the behavior of AMANDA
+amplot \- visualize the behavior of Amanda
 .SH "SYNOPSIS"
 .ad l
 .hy 0
 .HP 7
 \fBamplot\fR [\-b] [\-c] [\-e] [\-g] [\-l] [\-p] [\-t\ \fIT\fR] \fIamdump_files\fR
+.br
+
 .ad
 .hy
 
 .SH "DESCRIPTION"
 
 .PP
-\fBAmplot\fR reads an \fBamdump\fR output file that \fBAMANDA\fR generates each run (e\&.g\&. \fBamdump\&.1\fR) and translates the information into a picture format that may be used to determine how your installation is doing and if any parameters need to be changed\&. \fBAmplot\fR also prints out \fBamdump\fR lines that it either does not understand or knows to be warning or error lines and a summary of the start, end and total time for each backup image\&.
+\fBAmplot\fR reads an \fBamdump\fR output file that \fBAmanda\fR generates each run (e\&.g\&. \fBamdump\&.1\fR) and translates the information into a picture format that may be used to determine how your installation is doing and if any parameters need to be changed\&. \fBAmplot\fR also prints out \fBamdump\fR lines that it either does not understand or knows to be warning or error lines and a summary of the start, end and total time for each backup image\&.
 
 .PP
 \fBAmplot\fR is a shell script that executes an \fBawk\fR program \fB\fR(\fBamplot\&.awk\fR) to scan the \fBamdump\fR output file\&. It then executes a \fBgnuplot\fR program \fB\fR(\fBamplot\&.g\fR) to generate the graph\&. The \fBawk\fR program is written in an enhanced version of awk, such as GNU awk \fB\fR(\fBgawk\fR version 2\&.15 or later) or \fBnawk\fR\&.
@@ -40,7 +42,7 @@ amplot \- visualize the behavior of AMANDA
 During execution, \fBamplot\fR generates a few temporary files that \fBgnuplot\fR uses\&. These files are deleted at the end of execution\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -104,7 +106,7 @@ The idle period at the left of the graph is time \fBamdump\fR is asking the mach
 Olafur Gudmundsson <ogud@tis\&.com>, Trusted Information Systems, formerly at University of Maryland, College Park: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "BUGS"
 
index 7fdf97f2249442c156a34fda2987a89977c17862..9379a6f4cf4faba4cc2ac834dbf537032e1487df 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMRECOVER" 8 "" "" ""
 .SH NAME
-amrecover \- AMANDA index database browser
+amrecover \- Amanda index database browser
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,36 +31,38 @@ amrecover \- AMANDA index database browser
 .SH "DESCRIPTION"
 
 .PP
-\fBAmrecover\fR browses the database of \fBAMANDA\fR index files to determine which tapes contain files to recover\&. Furthermore, it is able to recover files\&.
+\fBAmrecover\fR browses the database of \fBAmanda\fR index files to determine which tapes contain files to recover\&. Furthermore, it is able to recover files\&.
 
 .PP
 In order to restore files in place, you must invoke \fBamrecover\fR from the root of the backed up filesystem, or use \fBlcd\fR to move into that directory, otherwise a directory tree that resembles the backed up filesystem will be created in the current directory\&. See the examples below for details\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
 .RS
 .Sh "Note"
-The listed defaults map to the values you ran the configure\-script with\&.
+The Default values are those set at compile\-time\&.
+Use \fBamrestore\fR to recover client\-encrypted or
+client\-custom\-compressed tapes\&.
 .RE
 
 .TP
 \fB[ \-C ] config\fR
-\fBAMANDA\fR configuration (default: daily)\&.
+\fBAmanda\fR configuration\&.
 
 .TP
 \fB\-s index\-server\fR
-Host that runs the index daemon (default: oops)\&.
+Host that runs the index daemon\&.
 
 .TP
 \fB\-t tape\-server\fR
-Host that runs the tape server daemon (default: 192\&.168\&.0\&.10)\&.
+Host that runs the tape server daemon\&.
 
 .TP
 \fB\-d tape\-device\fR
-Tape device to use on the tape server host (default: /dev/nst0)\&.
+Tape device to use on the tape server host\&.
 
 .SH "COMMANDS"
 
@@ -116,7 +118,7 @@ dates in the current month of the current year
 .IP
 
 .TP
-\fBsetdisk diskname mountpoint\fR
+\fBsetdisk \fIdiskname\fR [\fImountpoint\fR]\fR
 Specifies which disk to consider (default: the disk holding the working directory where \fBamrecover\fR is started)\&. It can only be set after the host is set with \fBsethost\fR\&. \fBDiskname\fR is the device name specified in the \fBamanda\&.conf\fR or \fBdisklist\fR configuration file\&. The disk must be local to the host\&. If \fBmountpoint\fR is not specified, all pathnames will be relative to the (unknown) mount point instead of full pathnames\&.
 
 .TP
@@ -125,7 +127,7 @@ List all \fBdiskname\fR
 
 .TP
 \fBsettape [[server]:][tapedev|default]\fR
-Specifies the host to use as the tape server, and which of its tape devices to use\&. If the server is omitted, but the colon is not, the server name reverts to 192\&.168\&.0\&.10, the configure\-time default\&. If the tape device is omitted, it remains unchanged\&. To use the default tape device selected by the tape server, the word \fBdefault\fR must be specified\&. If no argument is specified, or the argument is an empty string, no changes occur, and the current settings are displayed\&.
+Specifies the host to use as the tape server, and which of its tape devices to use\&. If the server is omitted, but the colon is not, the server name reverts to the configure\-time default\&. If the tape device is omitted, it remains unchanged\&. To use the default tape device selected by the tape server, the word \fBdefault\fR must be specified\&. If no argument is specified, or the argument is an empty string, no changes occur, and the current settings are displayed\&.
 
 If you want amrecover to use your changer, the \fBtapedev\fR must be equal to the amrecover_changer setting on the server\&.
 
@@ -199,7 +201,7 @@ Delete the specified files or directories from the restore list\&. Each item may
 
 .TP
 \fBlist file\fR
-Display the contents of the restore list\&. If a file name is specified, the restore list is written to that file\&. This can be used to manually extract the files from the \fBAMANDA\fR tapes with \fBamrestore\fR\&.
+Display the contents of the restore list\&. If a file name is specified, the restore list is written to that file\&. This can be used to manually extract the files from the \fBAmanda\fR tapes with \fBamrestore\fR\&.
 
 .TP
 \fBclear\fR
@@ -232,7 +234,7 @@ The following shows the recovery of an old \fBsyslog\fR file\&.
 syslog\&.7: No such file or directory
 # amrecover
 AMRECOVER Version 2\&.4\&.2\&. Contacting server on oops \&.\&.\&.
-220 oops \fBAMANDA\fR index server (2\&.4\&.2) ready\&.
+220 oops \fBAmanda\fR index server (2\&.4\&.2) ready\&.
 Setting restore date to today (1997\-12\-09)
 200 Working date set to 1997\-12\-09\&.
 200 Config set to daily\&.
@@ -369,10 +371,10 @@ amrecover> quit
 Alan M\&. McIvor <alan@kauri\&.auck\&.irl\&.cri\&.nz> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
 .PP
-\fBamanda\fR(8), \fBamrestore\fR(8), \fBreadline\fR(3)
+\fBamanda\fR(8), \fBamrestore\fR(8), \fBamfetchdump\fR(8), \fBreadline\fR(3)
 
index 8d91fe679c2e318b1788f7cb462e3c8fc25c1371..dc98ad485d561da20ffa7b2e5c2eeb7466a62161 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMREPORT" 8 "" "" ""
 .SH NAME
-amreport \- generate a formatted output of statistics for an AMANDA run
+amreport \- generate a formatted output of statistics for an Amanda run
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -34,7 +34,7 @@ amreport \- generate a formatted output of statistics for an AMANDA run
 \fBAmreport\fR generates a summary report of an \fBamanda\fR(8) backup run\&. If no configuration name is specified, amanda\&.conf is read from the current directory\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -63,7 +63,7 @@ Send the postscript output to the file \fBpostscriptfile\fR instead of to the \f
 .SH "LABEL PRINTING"
 
 .PP
-\fBAMANDA\fR can print postscript labels describing the contents of tape(s) written in a run\&. The labels are designed to be folded and inserted into the tape case along with the tape or hole punched and put in a 3\-ring binder\&. Various label templates are provided to format data for different tape sizes\&.
+\fBAmanda\fR can print postscript labels describing the contents of tape(s) written in a run\&. The labels are designed to be folded and inserted into the tape case along with the tape or hole punched and put in a 3\-ring binder\&. Various label templates are provided to format data for different tape sizes\&.
 
 .PP
 The information printed varies slightly between label templates due to size constraints\&. Labels contain one line for each host/file\-system pair and may also contain the file number on the tape, the level of the dump, the original size of the dump and the size of the (possibly compressed) tape file\&.
@@ -77,7 +77,7 @@ You may use the \fBremap='I'>printer\fR keyword in amanda\&.conf to print to oth
 .SH "TEMPLATES"
 
 .PP
-\fBAMANDA\fR provides label templates for the following tape types\&. These are pretty generic labels and should be easy to customize for other tape types or particular site needs\&.
+\fBAmanda\fR provides label templates for the following tape types\&. These are pretty generic labels and should be easy to customize for other tape types or particular site needs\&.
 
 .nf
 
index 0e0f418ecf4d6a3508f64bf8c2ec8a51d3b53c26..e4afea3ad07641cab674165259b34dfcc5669365 100644 (file)
 ..
 .TH "AMRESTORE" 8 "" "" ""
 .SH NAME
-amrestore \- extract backup images from an AMANDA tape
+amrestore \- extract backup images from an Amanda tape
 .SH "SYNOPSIS"
 .ad l
 .hy 0
 .HP 10
-\fBamrestore\fR [\fB\-r\fR | \fB\-c\fR | \fB\-C\fR] [\-b\ \fIblocksize\fR] [\-f\ \fIfileno\fR] [\-l\ \fIlabel\fR] [\-p] [\-h] \fB\fItapedevice\fR\fR | \fB\fIholdingfile\fR\fR | \fB\fIhostname\fR\ [\fIdiskname\fR\ [\fIdatestamp\fR\ [\fIhostname\fR\ [\fIdiskname\fR\ [\fIdatestamp\fR...]]]]]\fR 
+\fBamrestore\fR [\fB\-r\fR | \fB\-c\fR | \fB\-C\fR] [\-b\ \fIblocksize\fR] [\-f\ \fIfileno\fR] [\-l\ \fIlabel\fR] [\-p] [\-h] \fB\fItapedevice\fR\fR | \fB\fIholdingfile\fR\fR | \fB\fIhostname\fR\ [\fIdiskname\fR\ [\fIdatestamp\fR]]\fR \&.\&.\&. 
 .ad
 .hy
 
@@ -157,7 +157,7 @@ This asks \fBamrestore\fR to find images for host \fBno\-such\-host\fR\&. It wil
 James da Silva, <jds@amanda\&.org>, University of Maryland, College Park: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index b625a5f7693ff31f953f88d6928618028c4926fb..b4fff7c19b20875c3f2dd7c03b634b34a8f172a5 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMRMTAPE" 8 "" "" ""
 .SH NAME
-amrmtape \- remove a tape from the AMANDA database
+amrmtape \- remove a tape from the Amanda database
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -34,7 +34,7 @@ amrmtape \- remove a tape from the AMANDA database
 \fBAmrmtape\fR invalidates the contents of an existing backup tape in the configuration database\&. This is meant as a recovery mechanism when a good backup is damaged either by faulty hardware or user error, e\&.g\&. the tape is eaten by the drive or is overwritten\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -69,7 +69,7 @@ Remove tape labeled \fBDAILY034\fR from the \fBDailySet1\fR configuration\&.
 Adrian T\&. Filipi\-Martin <atf3r@cs\&.virginia\&.edu>: Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index 87ea0fefea811ea8b0634e64b4c514bdff1cfc51..cee417fc3adecd9688f317f3ba0a607e52ffb673 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMSTATUS" 8 "" "" ""
 .SH NAME
-amstatus \- display the state of an AMANDA run
+amstatus \- display the state of an Amanda run
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,10 +31,10 @@ amstatus \- display the state of an AMANDA run
 .SH "DESCRIPTION"
 
 .PP
-\fBAmstatus\fR gives the current state of the \fBAMANDA\fR run specified by the \fBconfig\fR configuration\&. If there is no active \fBAMANDA\fR running, it summarizes the result of the last run\&. It may also be used to summarize the results of a previous run\&.
+\fBAmstatus\fR gives the current state of the \fBAmanda\fR run specified by the \fBconfig\fR configuration\&. If there is no active \fBAmanda\fR running, it summarizes the result of the last run\&. It may also be used to summarize the results of a previous run\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -43,7 +43,7 @@ All options may be abbreviated to the shortest non\-ambiguous sub\-string\&. If
 
 .TP
 \fB[\-\-config] config\fR
-Specify the \fBAMANDA\fR configuration you want to display the state for\&.
+Specify the \fBAmanda\fR configuration you want to display the state for\&.
 
 .TP
 \fB\-\-file amdumpfile\fR
index 1741d4f74bbba2d227f876b73cd9a73245eac665..4ff969f82ab4829d812a9fafb8f413105ead8757 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMTAPE" 8 "" "" ""
 .SH NAME
-amtape \- user interface to AMANDA tape changer controls
+amtape \- user interface to Amanda tape changer controls
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,19 +31,19 @@ amtape \- user interface to AMANDA tape changer controls
 .SH "DESCRIPTION"
 
 .PP
-\fBAmtape\fR performs tape changer control operations\&. It uses the underlying tape changer script defined by the \fBtpchanger\fR option for a particular \fBAMANDA\fR configuration as specified by the \fBconfig\fR argument\&.
+\fBAmtape\fR performs tape changer control operations\&. It uses the underlying tape changer script defined by the \fBtpchanger\fR option for a particular \fBAmanda\fR configuration as specified by the \fBconfig\fR argument\&.
 
 .PP
 Tape changers maintain a notion of the \fBcurrent\fR and \fBnext\fR slot for each configuration\&. These may or may not correspond to an actual physical state of the device, but do tend to minimize searching through the tape storage slots\&. If the desired tape is in the current slot, it is likely the next tape needed is in the next slot rather than at some random position in the storage slots\&.
 
 .PP
-See the \fBamanda\fR(8) man page for more details about \fBAMANDA\fR\&.
+See the \fBamanda\fR(8) man page for more details about \fBAmanda\fR\&.
 
 .SH "COMMANDS"
 
 .TP
 \fBreset\fR
-Reset the tape changer to a known state\&. The \fBcurrent\fR slot is set to the \fBfirst\fR slot\&. Other device\-specific side effects may occur\&. Some gravity stackers need to be reset to the top position by hand\&. This command notifies \fBAMANDA\fR the stacker is back in that position\&.
+Reset the tape changer to a known state\&. The \fBcurrent\fR slot is set to the \fBfirst\fR slot\&. Other device\-specific side effects may occur\&. Some gravity stackers need to be reset to the top position by hand\&. This command notifies \fBAmanda\fR the stacker is back in that position\&.
 
 .TP
 \fBeject\fR
@@ -59,7 +59,7 @@ Show the contents of all slots\&. This can be slow\&.
 
 .TP
 \fBlabel\fR \fBlabel\fR
-Search for and load the \fBAMANDA\fR tape with label \fBlabel\fR\&.
+Search for and load the \fBAmanda\fR tape with label \fBlabel\fR\&.
 
 .TP
 \fBtaper\fR
@@ -106,7 +106,7 @@ Eject any tape in the drive and put it away, then load the tape from the last sl
 Eject any tape in the drive and put it away\&. Advance \fBcurrent\fR to the next tape, but do not load it\&.
 
 .PP
-This is useful with non\-gravity stackers to unload the last tape used and set up \fBAMANDA\fR for the next run\&. If you just use \fBeject\fR, the current tape will be mounted again in the next run, where it will be rejected as being still in use, ejected and the next tape requested\&. Using \fBslot next\fR followed by \fBeject\fR does an unnecessary mount\&.
+This is useful with non\-gravity stackers to unload the last tape used and set up \fBAmanda\fR for the next run\&. If you just use \fBeject\fR, the current tape will be mounted again in the next run, where it will be rejected as being still in use, ejected and the next tape requested\&. Using \fBslot next\fR followed by \fBeject\fR does an unnecessary mount\&.
 
 .PP
 Note: most changers optimize the \fBslot\fR commands to not eject the loaded tape if it is the one being requested\&.
@@ -117,7 +117,7 @@ Note: most changers optimize the \fBslot\fR commands to not eject the loaded tap
 James da Silva, <jds@amanda\&.org> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index 61c350c5ca734e479c89ceebfff063c69bf25da9..d338de5ffbf7d4cef57442285271255c5d0520c7 100644 (file)
@@ -31,7 +31,7 @@ amtapetype \- generate a tapetype definition.
 .SH "DESCRIPTION"
 
 .PP
-\fBamtapetype\fR generates a tapetype entry for \fBAMANDA\fR\&.
+\fBamtapetype\fR generates a tapetype entry for \fBAmanda\fR\&.
 
 .SH "OPTIONS"
 
@@ -45,22 +45,22 @@ Run only the hardware compression detection heuristic test and stop\&. This take
 
 .TP
 \fB\-o\fR
-Overwrite the tape, even if it's an \fBAMANDA\fR tape\&.
+Overwrite the tape, even if it's an \fBAmanda\fR tape\&.
 
 .TP
-\fB\-b\fR\fI&#8201; blocksize\fR
+\fB\-b\fR\fI blocksize\fR
 record block size (default: 32k)
 
 .TP
-\fB\-e\fR\fI&#8201; estsize\fR
+\fB\-e\fR\fI estsize\fR
 estimated tape size (default: 1g == 1024m)
 
 .TP
-\fB\-f\fR\fI&#8201; tapedev\fR
+\fB\-f\fR\fI tapedev\fR
 tape device name (default: $TAPE) The device to perform the test\&.
 
 .TP
-\fB\-t\fR\fI&#8201; typename\fR
+\fB\-t\fR\fI typename\fR
 tapetype name (default: unknown\-tapetype)
 
 .SH "EXAMPLE"
index 87b6ac24a93afa630dfa83b1f7654e4e5dbd360b..79b1275a321fdd05e76f521115cece32baf2d65d 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMTOC" 8 "" "" ""
 .SH NAME
-amtoc \- generate TOC (Table Of Contents) for an AMANDA run
+amtoc \- generate TOC (Table Of Contents) for an Amanda run
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,7 +31,7 @@ amtoc \- generate TOC (Table Of Contents) for an AMANDA run
 .SH "DESCRIPTION"
 
 .PP
-\fBAmtoc\fR generates a table of contents for an \fBAMANDA\fR run\&. It's a perl script (if you don't have perl, install it first!)\&.
+\fBAmtoc\fR generates a table of contents for an \fBAmanda\fR run\&. It's a perl script (if you don't have perl, install it first!)\&.
 
 .SH "OPTIONS"
 
@@ -127,5 +127,5 @@ which will generate /usr/local/etc/amanda//daily/\fBtape_label\fR\&.toc\&. You m
 Nicolas Mayencourt <Nicolas\&.Mayencourt@cui\&.unige\&.ch>, University of Geneva/Switzerland : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
index 5939a40812d6ec064fc8b181a32b666055322b6d..53a8d50312295fba91eac0695eb422530f1e73ee 100644 (file)
@@ -54,7 +54,7 @@ See the \fBamanda\fR(8) man page for more details about Amanda\&.
 Axel Zinser <fifi@icem\&.de> : Original text
 
 .PP
-Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAMANDA\fR\-documentation: XML\-conversion
+Stefan G\&. Weichinger, <sgw@amanda\&.org>, maintainer of the \fBAmanda\fR\-documentation: XML\-conversion
 
 .SH "SEE ALSO"
 
index 3255b7c855b869231e669c9e2808d71779e53eee..a491e98af53fdccf0a6bedbfba0941d39a4775a1 100644 (file)
@@ -19,7 +19,7 @@
 ..
 .TH "AMVERIFYRUN" 8 "" "" ""
 .SH NAME
-amverifyrun \- check the tapes written by the last AMANDA run
+amverifyrun \- check the tapes written by the last Amanda run
 .SH "SYNOPSIS"
 .ad l
 .hy 0
@@ -31,7 +31,7 @@ amverifyrun \- check the tapes written by the last AMANDA run
 .SH "DESCRIPTION"
 
 .PP
-\fBAmverifyrun\fR read the log from the last \fBAMANDA\fR run to find the slot of the first tape used and the number of tapes used\&. It call \fBamverify\fR with these argument\&.
+\fBAmverifyrun\fR read the log from the last \fBAmanda\fR run to find the slot of the first tape used and the number of tapes used\&. It call \fBamverify\fR with these argument\&.
 
 .SH "SEE ALSO"
 
diff --git a/man/entities/global.entities b/man/entities/global.entities
new file mode 100644 (file)
index 0000000..7adc417
--- /dev/null
@@ -0,0 +1,92 @@
+<!-- Global Entities File -->
+
+<!ENTITY email.sgw '<email>sgw@amanda.org</email>'>
+<!ENTITY maintainer.sgw 'Stefan G. Weichinger, &email.sgw;, maintainer of the
+&A;-documentation'>
+<!ENTITY email.jds '<email>jds@amanda.org</email>'>
+<!ENTITY email.itt '<email>ian@zmanda.com</email>'>
+<!ENTITY email.jstange '<email>building@nap.edu</email>'>
+<!ENTITY A '<application><emphasis>Amanda</emphasis></application>'>
+
+<!-- IDs for AMANDA files-->
+<!ENTITY amandaddebug ' <filename>amandad.debug</filename>'>
+<!ENTITY amconf '<filename>amanda.conf</filename>'>
+<!ENTITY amandahosts '<filename>.amandahosts</filename>'>
+<!ENTITY disklist '<filename>disklist</filename>'>
+<!ENTITY amandapass '<filename>/etc/amandapass</filename>'>
+<!ENTITY inetdconf '<filename>/etc/inetd.conf</filename>'>
+<!ENTITY tapelist '<filename>tapelist</filename>'>
+
+<!-- IDs for files used by AMANDA-->
+<!ENTITY dumpdates '<filename>/etc/dumpdates</filename>'>
+
+<!-- IDs for AMANDA commands-->
+<!ENTITY amadmin ' <command>amadmin</command>'>
+<!ENTITY amaespipe ' <command>amaespipe</command>'>
+<!ENTITY amcheck ' <command>amcheck</command>'>
+<!ENTITY amcheckdb ' <command>amcheckdb</command>'>
+<!ENTITY amcleanup ' <command>amcleanup</command>'>
+<!ENTITY amcrypt ' <command>amcrypt</command>'>
+<!ENTITY amdd ' <command>amdd</command>'>
+<!ENTITY amdump ' <command>amdump</command>'>
+<!ENTITY amflush ' <command>amflush</command>'>
+<!ENTITY amgetconf ' <command>amgetconf</command>'>
+<!ENTITY amlabel ' <command>amlabel</command>'>
+<!ENTITY ammt ' <command>ammt</command>'>
+<!ENTITY amoverview ' <command>amoverview</command>'>
+<!ENTITY amplot ' <command>amplot</command>'>
+<!ENTITY amrecover ' <command>amrecover</command>'>
+<!ENTITY amreport ' <command>amreport</command>'>
+<!ENTITY amrestore ' <command>amrestore</command>'>
+<!ENTITY amrmtape ' <command>amrmtape</command>'>
+<!ENTITY amstatus ' <command>amstatus</command>'>
+<!ENTITY amtape ' <command>amtape</command>'>
+<!ENTITY amtapetype ' <command>amtapetype</command>'>
+<!ENTITY amtoc ' <command>amtoc</command>'>
+<!ENTITY amverify ' <command>amverify</command>'>
+<!ENTITY amverifyrun ' <command>amverifyrun</command>'>
+
+<!ENTITY amandad ' <command>amandad</command>'>
+<!ENTITY amandaidx ' <command>amandaidx</command>'>
+<!ENTITY amgetidx ' <command>amgetidx</command>'>
+<!ENTITY amidxtape ' <command>amidxtape </command>'>
+<!ENTITY amidxtaped ' <command>amidxtaped</command>'>
+<!ENTITY amindexd ' <command>amindexd</command>'>
+<!ENTITY amtrmidx ' <command>amtrmidx</command>'>
+<!ENTITY calcsize ' <command>calcsize</command>'>
+<!ENTITY driver ' <command>driver</command>'>
+<!ENTITY dumper ' <command>dumper</command>'>
+<!ENTITY planner ' <command>planner</command>'>
+<!ENTITY reporter ' <command>reporter</command>'>
+<!ENTITY runtar ' <command>runtar</command>'>
+<!ENTITY selfcheck ' <command>selfcheck</command>'>
+<!ENTITY sendbackup ' <command>sendbackup</command>'>
+<!ENTITY sendsize ' <command>sendsize</command>'>
+<!ENTITY taper ' <command>taper</command>'>
+
+<!-- IDs for commands used by AMANDA-->
+<!ENTITY mt '<command>mt</command>'>
+<!ENTITY mtx '<command>mtx</command>'>
+<!ENTITY tar '<command>tar</command>'>
+<!ENTITY gnutar '<command>GNU-tar</command>'>
+<!ENTITY gzip '<command>GNU-zip</command>'>
+
+<!ENTITY dump '<command>dump</command>'>
+<!ENTITY restore.binary '<command>restore</command>'>
+
+<!ENTITY dd '<command>dd</command>'>
+<!ENTITY cpio '<command>cpio</command>'>
+
+<!ENTITY gcc '<command>gcc</command>'>
+<!ENTITY configure '<command>configure</command>'>
+<!ENTITY make '<command>make</command>'>
+<!ENTITY ssh '<command>ssh</command>'>
+<!ENTITY rsh '<command>rsh</command>'>
+<!ENTITY inetd '<command>inetd</command>'>
+<!ENTITY xinetd '<command>xinetd</command>'>
+<!ENTITY lsof '<command>lsof</command>'>
+
+<!ENTITY runtapes '<command>runtapes</command>'>
+<!ENTITY dumpers '<command>dumpers</command>'>
+<!ENTITY dumptype '<command>dumptype</command>'>
+<!ENTITY dumpcycle '<command>dumpcycle</command>'>
diff --git a/man/entities/xinclude.dtd b/man/entities/xinclude.dtd
new file mode 100644 (file)
index 0000000..ec1bd2c
--- /dev/null
@@ -0,0 +1,31 @@
+<!--
+   $Id: xinclude.dtd,v 1.1 2005/11/19 00:51:20 paddy_s Exp $
+
+ The XInclude DTD is from
+
+   http://www.w3.org/TR/xinclude/
+
+ and modified in a way which support our needs.
+
+-->
+
+<!ENTITY % xmlnsxi 'xmlns:xi CDATA  #FIXED "http://www.w3.org/2001/XInclude"'>
+
+
+<!ELEMENT xi:include (xi:fallback)?>
+
+<!-- Just for some modifications -->
+<!ENTITY % local.xinclude.attrib "">
+<!ATTLIST xi:include
+       %xmlnsxi;
+       href       CDATA       #REQUIRED
+       parse      (xml|text)  "xml"
+       encoding   CDATA       #IMPLIED
+       %local.xinclude.attrib;
+>
+
+<!ELEMENT xi:fallback ANY>
+<!ATTLIST xi:fallback
+       %xmlnsxi;
+       %local.xinclude.attrib;
+>
diff --git a/man/xml-source/amadmin.8.xml b/man/xml-source/amadmin.8.xml
new file mode 100644 (file)
index 0000000..5cfc4b4
--- /dev/null
@@ -0,0 +1,406 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amadmin.8'>
+
+<refmeta>
+<refentrytitle>amadmin</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amadmin</refname>
+<refpurpose>administrative interface to control &A; backups</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amadmin</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>command</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>command</replaceable></arg><arg choice='plain'><replaceable>options</replaceable></arg></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amadmin</emphasis>
+performs various administrative tasks on the
+<emphasis remap='I'>config</emphasis>
+&A; configuration.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>COMMANDS</title>
+<para>Commands that take a
+<emphasis remap='I'>hostname</emphasis>
+[
+<emphasis remap='I'>disks</emphasis>
+]
+parameter pair operate on all disks in the
+<emphasis remap='I'>disklist</emphasis>
+for that
+<emphasis remap='I'>hostname</emphasis>
+if no disks are specified.
+Where
+<emphasis remap='I'>hostname</emphasis>
+is also marked as being optional,
+the command operates on all hosts and disks in the
+<emphasis remap='I'>disklist</emphasis>.
+Both
+<emphasis remap='I'>hostname</emphasis>
+and
+<emphasis remap='I'>disks</emphasis>
+are special expressions, see the &quot;HOST &amp; DISK EXPRESSION&quot; section
+of 
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+for a description.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>version</emphasis></term>
+  <listitem>
+<para>Show the current version and some compile time and runtime parameters.
+The
+<emphasis remap='I'>config</emphasis>
+parameter must be present but is ignored.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>force-bump</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]+</term>
+  <listitem>
+<para>Force the
+<emphasis remap='I'>disks</emphasis>
+on
+<emphasis remap='I'>hostname</emphasis>
+to bump to a new incremental level during the next &A; run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>force-no-bump</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]+</term>
+  <listitem>
+<para>Force the
+<emphasis remap='I'>disks</emphasis>
+on
+<emphasis remap='I'>hostname</emphasis>
+to not bump to a new incremental level during the next &A; run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>unforce-bump</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]+</term>
+  <listitem>
+<para>Undo a previous
+<emphasis remap='B'>force-bump</emphasis>
+or
+<emphasis remap='B'>force-no-bump</emphasis>
+command.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>force</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]+</term>
+  <listitem>
+<para>Force the
+<emphasis remap='I'>disks</emphasis>
+on
+<emphasis remap='I'>hostname</emphasis>
+to do a full (level 0) backup during the next &A; run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>unforce</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]+</term>
+  <listitem>
+<para>Undo a previous
+<emphasis remap='B'>force</emphasis>
+command.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>reuse</emphasis> <emphasis remap='I'>tapelabel</emphasis> [ ... ]</term>
+  <listitem>
+<para>The tapes listed
+will be available for reuse at their point in the tape cycle.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>no-reuse</emphasis> <emphasis remap='I'>tapelabel</emphasis> [ ... ]</term>
+  <listitem>
+<para>The tapes listed
+will not be reused when their turn comes up again in the tape cycle.
+Note that if this causes the number of reusable tapes to drop below the
+<emphasis remap='B'>amanda.conf</emphasis>
+<emphasis remap='I'>tapecycle</emphasis>
+value, &A; will request new tapes until the count is satisfied again.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>due</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]*</term>
+  <listitem>
+<para>Show when the next full dump is due.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>find</emphasis> [ <option>--sort</option> <replaceable>hkdlpb</replaceable> ]<emphasis remap='B'></emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]*</term>
+  <listitem>
+<para>Display all backups currently on tape or in the holding disk.
+The tape label or holding disk filename,
+file number,
+and status are displayed.</para>
+<para>The <option>--sort</option> option changes the sort order using the following flags:</para>
+
+<para><emphasis remap='B'>h</emphasis> host name
+<emphasis remap='B'>k</emphasis>       disk name
+<emphasis remap='B'>d</emphasis>       dump date
+<emphasis remap='B'>l</emphasis>       backup level
+<emphasis remap='B'>p</emphasis>        dump part
+<emphasis remap='B'>b</emphasis>       tape label</para>
+
+<para>An uppercase letter reverses the sort order for that key.
+The default sort order is <emphasis remap='B'>hkdlpb</emphasis>.</para>
+</listitem>
+</varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>delete</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]+</term>
+  <listitem>
+<para>Delete the specified
+<emphasis remap='I'>disks</emphasis>
+on
+<emphasis remap='I'>hostname</emphasis>
+from the &A; database.</para>
+<note>If you do not also remove the disk from the
+<emphasis remap='I'>disklist</emphasis>
+file, &A; will treat it as a new disk during the next run.</note>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>tape</emphasis></term>
+  <listitem>
+<para>Display the tape(s) &A; expects to write to during the next run.
+See also
+<citerefentry><refentrytitle>amcheck</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>bumpsize</emphasis></term>
+  <listitem>
+<para>Display the current bump threshold parameters, calculated for all backup
+levels.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>balance</emphasis> [ <option>--days</option> <replaceable>&lt;num&gt;</replaceable> ]<emphasis remap='B'></emphasis> <emphasis remap='I'></emphasis> <emphasis remap='I'></emphasis></term>
+  <listitem>
+<para>Display the distribution of full backups throughout the dump schedule.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>export</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]*</term>
+  <listitem>
+<para>Convert records from the &A; database
+to a text format that may be transmitted to another &A; machine and
+<emphasis remap='B'>import</emphasis>ed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>import</emphasis></term>
+  <listitem>
+<para>Convert
+<emphasis remap='B'>export</emphasis>ed
+records read from standard input to a form &A; uses
+and insert them into the database on this machine.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>disklist</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]*</term>
+  <listitem>
+<para>Display the
+<emphasis remap='I'>disklist</emphasis>
+information for each of the
+<emphasis remap='I'>disks</emphasis>
+on
+<emphasis remap='I'>hostname</emphasis>
+(or all hosts).
+Mostly used for debugging.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>info</emphasis> [ <emphasis remap='I'>hostname</emphasis> [ <emphasis remap='I'>disks</emphasis> ]* ]*</term>
+  <listitem>
+<para>Display the
+database record for each of the
+<emphasis remap='I'>disks</emphasis>
+on
+<emphasis remap='I'>hostname</emphasis>
+(or all hosts).
+Mostly used for debugging.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>EXAMPLES</title>
+<para>Request three specific file systems on
+<emphasis remap='I'>machine-a</emphasis>
+get a full level 0 backup during the next &A; run.</para>
+
+<programlisting>
+$ amadmin daily force machine-a / /var /usr
+amadmin: machine-a:/ is set to a forced level 0 tonight.
+amadmin: machine-a:/var is set to a forced level 0 tonight.
+amadmin: machine-a:/usr is set to a forced level 0 tonight.
+</programlisting>
+
+<para>Request all file systems on
+<emphasis remap='I'>machine-b</emphasis>
+get a full level 0 backup during the next &A; run.</para>
+
+<programlisting>
+$ amadmin daily force machine-b
+amadmin: machine-b:/ is set to a forced level 0 tonight.
+amadmin: machine-b:/var is set to a forced level 0 tonight.
+amadmin: machine-b:/usr is set to a forced level 0 tonight.
+amadmin: machine-b:/home is set to a forced level 0 tonight.
+</programlisting>
+
+<para>Undo the previous
+<emphasis remap='B'>force</emphasis>
+request for
+<filename>/home</filename>
+on
+<emphasis remap='I'>machine-b</emphasis>.
+The other file systems will still get a full level 0 backup.</para>
+
+<programlisting>
+$ amadmin daily unforce machine-b /home
+amadmin: force command for machine-b:/home cleared.
+</programlisting>
+
+<para>Locate backup images of
+<filename>/var</filename>
+from
+<emphasis remap='I'>machine-c</emphasis>.
+The
+<emphasis remap='I'>tape or file</emphasis>
+column displays either a tape label or a filename depending on whether
+the image is on tape or is still in the holding disk.
+If the image is on tape, the
+<emphasis remap='I'>file</emphasis>
+column tells you which file on the tape has the image
+(file number zero is a tape label).
+This column shows zero and is not meaningful if the image
+is still in the holding disk.
+The
+<emphasis remap='I'>status</emphasis>
+column tells you whether the backup was successful or had
+some type of error.</para>
+
+<programlisting>
+$ amadmin daily find machine-c /var
+date        host      disk lv tape or file                 file part  status
+2000\-11\-09  machine\-c /var  0 000110                       9   --  OK
+2000\-11\-08  machine\-c /var  2 000109                       2   --  OK
+2000\-11\-07  machine\-c /var  2 /amanda/20001107/machine-c._var.2  0 OK
+2000\-11\-06  machine\-c /var  2 000107                       2   --  OK
+2000\-11\-05  machine\-c /var  2 000106                       3   --  OK
+2000\-11\-04  machine\-c /var  2 000105                       2   --  OK
+2000\-11\-03  machine\-c /var  2 000104                       2   --  OK
+2000\-11\-02  machine\-c /var  2 000103                       2   --  OK
+2000\-11\-01  machine\-c /var  1 000102                       5   --  OK
+2000\-10\-31  machine\-c /var  1 000101                       3   --  OK
+</programlisting>
+
+<para>Forget about the
+<filename>/workspace</filename>
+disk on
+<emphasis remap='I'>machine-d</emphasis>.
+If you do not also remove the disk from the
+<emphasis remap='I'>disklist</emphasis>
+file, &A; will treat it as a new disk during the next run.</para>
+
+<programlisting remap='.nf'>
+$ amadmin daily delete machine-d /workspace
+amadmin: machine-d:/workspace deleted from database.
+amadmin: NOTE: you'll have to remove these from the disklist yourself.
+</programlisting>
+
+<para>Find the next tape &A; will use (in this case, <literal>123456</literal>).</para>
+
+<programlisting>
+$ amadmin daily tape
+The next &A; run should go onto tape 123456 or a new tape.
+</programlisting>
+
+<para>Show how well full backups are balanced across the dump cycle.
+The
+<emphasis remap='I'>due-date</emphasis>
+column is the day the backups are due for a full backup.
+<emphasis remap='I'>#fs</emphasis>
+shows the number of filesystems doing full backups that night, and
+<emphasis remap='I'>orig KB</emphasis>
+and
+<emphasis remap='I'>out KB</emphasis>
+show the estimated total size of the backups
+before and after any compression, respectively.</para>
+
+<para>The
+<emphasis remap='I'>balance</emphasis>
+column shows how far off that night's backups are from the average size
+(shown at the bottom of the balance column).
+&A; tries to keep the backups within +/- 5%,
+but since the amount of data on each filesystem is always changing,
+and &A; will never delay backups just to rebalance the schedule,
+it is common for the schedule to fluctuate by larger percentages.
+In particular, in the case of a tape or backup failure, a bump will occur the following night,
+which will not be smoothed out until the next pass through the schedule.</para>
+
+<para>The last line also shows an estimate of how many &A; runs will be
+made between full backups for a file system.
+In the example, a file system will probably have a full backup done
+every eight times &A; is run (e.g. every eight days).</para>
+
+<programlisting>
+$ amadmin daily balance
+ due-date  #fs   orig KB    out KB  balance
+-------------------------------------------
+11/10 Mon   21    930389    768753    +5.1%
+11/11 Tue   29   1236272    733211    +0.2%
+11/12 Wed   31   1552381    735796    +0.6%
+11/13 Thu   23   1368447    684552    -6.4%
+11/14 Fri   32   1065603    758155    +3.6%
+11/15 Sat   14   1300535    738430    +0.9%
+11/16 Sun   31   1362696    740365    +1.2%
+11/17 Mon   30   1427936    773397    +5.7%
+11/18 Tue   11   1059191    721786    -1.3%
+11/19 Wed   19   1108737    661867    -9.5%
+-------------------------------------------
+TOTAL      241  12412187   7316312   731631  (estimated 8 runs per dumpcycle)
+</programlisting>
+</refsect1>
+
+<refsect1><title>FILES</title>
+<para>/usr/local/etc/amanda/<emphasis remap='I'>config</emphasis>/amanda.conf</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds; : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcheck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amfetchdump</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
diff --git a/man/xml-source/amaespipe.8.xml b/man/xml-source/amaespipe.8.xml
new file mode 100755 (executable)
index 0000000..d08370e
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<refentry id='amaespipe.8'>
+<refmeta>
+<refentrytitle>amaespipe</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amaespipe</refname>
+<refpurpose>wrapper program for aespipe</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amaespipe</command>    
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>DESCRIPTION</title>
+<para>&amaespipe;
+requires <emphasis remap='B'>aespipe</emphasis> and <emphasis remap='B'>gpg</emphasis> to work.
+Aespipe is available from <ulink url="http://loop-aes.sourceforge.net"/></para>
+<para>&amaespipe; will search for the aespipe program in the following directories:
+/usr/bin:/usr/local/bin:/sbin:/usr/sbin. </para>
+&amaespipe; is called by &amcrypt; for &A; data encryption.
+<para>&amaespipe; is based on aespipe's bzaespipe program.
+It calls aespipe to encrypt data using AES256 as the encryption and SHA256 as the
+hash function. GPG key should be stored in $AMANDA_HOME/.gnupg/am_key.gpg.
+&amaespipe; reads passphrase from file descriptor 3.
+During decryption, &amaespipe; autodects encryption type and hash function from
+the encrypted image.</para>
+</refsect1>
+
+
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>aespipe</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcrypt</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>gpg</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+</para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amanda.8.xml b/man/xml-source/amanda.8.xml
new file mode 100644 (file)
index 0000000..493bb74
--- /dev/null
@@ -0,0 +1,1063 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amanda.8'>
+
+<refmeta>
+<refentrytitle>amanda</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amanda</refname>
+<refpurpose>Advanced Maryland Automatic Network Disk Archiver</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+
+<cmdsynopsis>
+    <command>amadmin</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>command</replaceable></arg>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amcheck</command>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amcheckdb</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+
+<cmdsynopsis>
+    <command>amcleanup</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amcrypt</command>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+  <command>amdd</command>    
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+</cmdsynopsis>
+
+<cmdsynopsis>
+  <command>amdump</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amaespipe</command>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+  <command>amflush</command>    
+    <arg choice='opt'>-f </arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amgetconf</command>
+    <arg choice='opt'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>parameter</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amlabel</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>label</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>slot</replaceable></arg><arg choice='plain'><replaceable>slot</replaceable></arg></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+  <command>ammt</command>    
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amoverview</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amplot</command>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <arg choice='plain'><replaceable>amdump-files</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amrecover</command>
+    <arg choice='opt'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amreport</command>
+    <arg choice='opt'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amrestore</command>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <arg choice='plain'><replaceable>tapedevice</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>hostname</replaceable></arg><arg choice='opt'><replaceable>diskname</replaceable></arg></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amfetchdump</command>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>hostname</replaceable></arg><arg choice='opt'><arg choice='plain'><replaceable>diskname</replaceable></arg><arg choice='opt'><arg choice='plain'><replaceable>date</replaceable></arg><arg choice='opt'>level</arg></arg></arg></arg>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amrmtape</command>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>label</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amstatus</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amtape</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>command</replaceable></arg>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+  <command>amtapetype</command>    
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amtoc</command>
+    <arg choice='opt'><replaceable>options</replaceable></arg>
+    <arg choice='plain'><replaceable>logfile</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+    <command>amverify</command>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+
+<cmdsynopsis>
+  <command>amverifyrun</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+</cmdsynopsis>
+
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para>&A; is the 
+&quot;Advanced Maryland Automatic Network Disk Archiver&quot;.
+This manual page gives an overview of the &A; commands and
+configuration files for quick reference.</para>
+
+<para>Here are all the &A; commands.
+Each one has its own manual page.
+See them for all the gory details.</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>amdump</emphasis></term>
+  <listitem>
+<para>Take care of automatic &A; backups.
+This is normally executed by
+<emphasis remap='B'>cron</emphasis>
+on a computer called the
+<emphasis remap='I'>tape server host</emphasis>
+and requests backups of file systems located on
+<emphasis remap='I'>backup</emphasis>
+<emphasis remap='I'>clients</emphasis>.
+<emphasis remap='B'>Amdump</emphasis>
+backs up all disks in the
+<emphasis remap='I'>disklist</emphasis>
+file (discussed below) to tape or, if there is a problem, to a special
+<emphasis remap='I'>holding</emphasis>
+<emphasis remap='I'>disk</emphasis>.
+After all backups are done,
+<command>amdump</command>
+sends mail reporting failures and successes.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amflush</emphasis></term>
+  <listitem>
+<para>Flush backups from the holding disk to tape.
+<emphasis remap='B'>Amflush</emphasis>
+is used after
+<command>amdump</command>
+has reported it could not write backups to tape for some reason.
+When this happens, backups stay in the holding disk.
+Run <emphasis remap='B'>amflush</emphasis> after the tape problem is corrected
+to write backups from the holding disk to tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amcleanup</emphasis></term>
+  <listitem>
+<para>Clean up after an interrupted
+<command>amdump</command>.
+This command is only needed if
+<command>amdump</command>
+was unable to complete for some reason, usually because the
+tape server host crashed while
+<command>amdump</command>
+was running.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amrecover</emphasis></term>
+  <listitem>
+<para>Provides an interactive interface to browse the &A; index files
+(backup image catalogues)
+and select which tapes to recover files from.
+It can also run
+<emphasis remap='B'>amrestore</emphasis>
+and a restore program (e.g.
+<emphasis remap='B'>tar</emphasis>)
+to actually recover the files.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amrestore</emphasis></term>
+  <listitem>
+<para>Read an &A; tape, searching for requested backups.
+<emphasis remap='B'>Amrestore</emphasis>
+is suitable for everything from interactive restores of single files
+to a full restore of all partitions on a failed disk.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amfetchdump</emphasis></term>
+  <listitem>
+<para>Performs &A; tape restoration, similar to <emphasis
+  remap='B'>amrestore</emphasis>. Additional capabilities include
+  "hands-off" searching of multiple tapes, automatic
+  retrieval of specific dump files based on dump logs, and assembly of
+  tape-spanning split dump files.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amlabel</emphasis></term>
+  <listitem>
+<para>Write an &A; format label onto a tape.
+All &A; tapes must be labeled with
+<emphasis remap='B'>amlabel</emphasis>.
+<emphasis remap='B'>Amdump</emphasis>
+and
+<emphasis remap='B'>amflush</emphasis>
+will not write to an unlabeled tape (see TAPE MANAGEMENT below).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amcheck</emphasis></term>
+  <listitem>
+<para>Verify the correct tape is mounted and all file systems on all backup client systems
+are ready to be backed up. Often run by
+<emphasis remap='B'>cron</emphasis>
+before
+<command>amdump</command>
+to generate a mail warning that backups might fail
+unless corrective action is taken.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amadmin</emphasis></term>
+  <listitem>
+<para>Take care of administrative tasks like finding out which
+tapes are needed to restore a filesystem,
+forcing hosts to do full backups of selected disks
+and looking at schedule balance information.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amtape</emphasis></term>
+  <listitem>
+<para>Take care of tape changer control operations like loading particular tapes,
+ejecting tapes and scanning the tape storage slots.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amverify</emphasis></term>
+  <listitem>
+<para>Check &A; backup tapes for errors.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amrmtape</emphasis></term>
+  <listitem>
+<para>Delete a tape from the &A; databases.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amstatus</emphasis></term>
+  <listitem>
+<para>Report the status of a running or completed
+<command>amdump</command>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amoverview</emphasis></term>
+  <listitem>
+<para>Display a chart of hosts and file systems backed up every run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amplot</emphasis></term>
+  <listitem>
+<para>Generate utilization plots of &A; runs for performance tuning.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amreport</emphasis></term>
+  <listitem>
+<para>Generate an &A; summary E-mail report.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amtoc</emphasis></term>
+  <listitem>
+<para>Generate table of content files for &A; tapes.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amcheckdb</emphasis></term>
+  <listitem>
+<para>Verify every tape &A; knows about is consistent in the database.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amgetconf</emphasis></term>
+  <listitem>
+<para>Look up parameters in the &A; configuration file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amtapetype</emphasis></term>
+  <listitem>
+<para>Generate a tapetype definition.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amaespipe</emphasis></term>
+  <listitem>
+<para>Wrapper program from aespipe (data encryption utility)</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amcrypt</emphasis></term>
+  <listitem>
+<para>Reference encryption program for Amanda symmetric data encryption</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>CONFIGURATION</title>
+<para>There are three user-editable files that control the behavior of &A;.
+</para>
+<para>
+The first is
+<emphasis remap='B'>amanda.conf</emphasis>,
+the main configuration file.
+It contains parameters to customize &A; for the site.
+Refer to the 
+<citerefentry><refentrytitle>amanda.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+manpage for details on &A; configuration parameters.
+</para>
+<para>
+Second is the
+<emphasis remap='I'>disklist</emphasis>
+file, which lists hosts and disk partitions to back up.
+</para>
+<para>
+Third is the
+<emphasis remap='I'>tapelist</emphasis>
+file, which lists tapes that are currently active.
+These files are described in more detail in the following sections.</para>
+
+<para>All files are stored in individual configuration
+directories under <filename>/usr/local/etc/amanda/</filename>.
+A site will often have more than
+one configuration.
+For example, it might have a
+<emphasis remap='I'>normal</emphasis>
+configuration for everyday backups and an
+<emphasis remap='I'>archive</emphasis>
+configuration for infrequent full archival backups.
+The configuration files would be stored under directories
+<filename>/usr/local/etc/amanda/normal/</filename> and
+<filename>/usr/local/etc/amanda/archive/</filename>, respectively.
+Part of the job of an &A; administrator is to create,
+populate and maintain these directories.</para>
+
+<para>All log and database files generated by &A; go in corresponding
+directories somewhere.
+The exact location is controlled by entries in
+<emphasis remap='B'>amanda.conf</emphasis>.
+A typical location would be under <filename>/var/adm/amanda</filename>.
+For the above example, the files might go in
+<filename>/var/adm/amanda/normal/</filename> and
+<filename>/var/adm/amanda/archive/</filename>.
+</para>
+
+<para>As log files are no longer needed (no longer contain relevant information),
+&A; cycles them out in various ways, depending on the type of file.</para>
+
+<para>Detailed information about
+<command>amdump</command>
+runs are stored in files named
+<emphasis remap='B'>amdump.</emphasis><emphasis remap='I'>NN</emphasis>
+where
+<emphasis remap='I'>NN</emphasis>
+is a sequence number, with 1 being the most recent file.
+<emphasis remap='B'>Amdump</emphasis>
+rotates these files each run, keeping roughly the last
+<emphasis remap='B'>tapecycle</emphasis>
+(see below)
+worth of them.</para>
+
+<para>The file used by
+<emphasis remap='B'>amreport</emphasis>
+to generate the mail summary is named
+<emphasis remap='B'>log.</emphasis><emphasis remap='I'>YYYYMMDD.NN</emphasis>
+where
+<emphasis remap='I'>YYYYMMDD</emphasis>
+is the datestamp of the start of the
+<command>amdump</command>
+run and
+<emphasis remap='I'>NN</emphasis>
+is a sequence number started at 0.
+At the end of each
+<command>amdump</command>
+run,
+log files for runs whose tapes have been reused are renamed
+into a subdirectory of the main log directory (see the
+<emphasis remap='B'>logdir</emphasis>
+parameter below)
+named
+<emphasis remap='B'>oldlog</emphasis>.
+It is up to the &A; administrator to remove them from this
+directory when desired.</para>
+
+<para>Index (backup image catalogue) files older than the full dump
+matching the oldest backup image for a given client and disk
+are removed by
+<command>amdump</command>
+at the end of each run.</para>
+</refsect1>
+
+<refsect1><title>DISKLIST FILE</title>
+<para>The
+<emphasis remap='I'>disklist</emphasis>
+file determines which disks will be backed up by &A;.
+The file usually contains one line per disk:</para>
+
+<programlisting>
+<emphasis>hostname diskname</emphasis> [<emphasis>diskdevice</emphasis>] <emphasis>dumptype</emphasis> [<emphasis>spindle</emphasis> [<emphasis>interface</emphasis>] ]
+</programlisting>
+
+<para>All pairs [ <emphasis>hostname diskname</emphasis> ] must be unique.</para>
+
+<para>Lines starting with # are ignored, as are blank lines.
+The fields have the following meanings:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>hostname</emphasis></term>
+  <listitem>
+<para>The name of the host to be backed up.
+If
+<emphasis remap='B'>diskdevice</emphasis>
+refers to a PC share, this is the host &A; will run the Samba
+<emphasis remap='B'>smbclient</emphasis> program on to back up the share.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='I'>diskname</emphasis></term>
+  <listitem>
+<para>The name of the disk (a label).
+In most case, you set your
+<emphasis remap='B'>diskname</emphasis>
+to the
+<emphasis remap='B'>diskdevice</emphasis>
+and you don't set the
+<emphasis remap='B'>diskdevice.</emphasis>
+If you want multiple entries with the same
+<emphasis remap='B'>diskdevice</emphasis>,
+you must set a different
+<emphasis remap='B'>diskname</emphasis>
+for each entry. It's the
+<emphasis remap='B'>diskname</emphasis>
+that you use on the commandline for any &A; command.
+Look at the example/disklist file for example.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='I'>diskdevice</emphasis></term>
+  <listitem>
+<para>Default: same as diskname.
+The name of the disk device to be backed up. It may be a full device name,
+a device name without the
+<filename>/dev/</filename>
+prefix, e.g.
+<emphasis remap='I'>sd0a</emphasis>,
+or a mount point such as
+<filename>/usr</filename>.</para>
+
+<para>It may also refer to a PC share by starting the name with two (forward) slashes, e.g.
+<filename>//some-pc/home</filename>.
+In this case, the
+<emphasis remap='B'>program</emphasis>
+option in the associated
+<emphasis remap='B'>dumptype</emphasis>
+must be entered as
+<emphasis remap='B'>GNUTAR</emphasis>.
+It is the combination of the double slash disk name and
+<emphasis remap='B'>program GNUTAR</emphasis>
+in the
+<emphasis remap='B'>dumptype</emphasis>
+that triggers the use of Samba.</para>
+</listitem>
+</varlistentry>
+  
+  <varlistentry>
+  <term><emphasis remap='I'>dumptype</emphasis></term>
+  <listitem>
+<para>Refers to a
+<emphasis remap='B'>dumptype</emphasis>
+defined in the
+<emphasis remap='B'>amanda.conf</emphasis>
+file.
+<emphasis remap='I'>Dumptype</emphasis>s
+specify backup related parameters,
+such as whether to compress the backups,
+whether to record backup results in
+<filename>/etc/dumpdates</filename>, the disk's relative priority, etc.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='I'>spindle</emphasis></term>
+  <listitem>
+<para>Default:
+<option>-1</option>.
+A number used to balance backup load on a host.
+&A; will not run multiple backups at the same time
+on the same spindle, unless the spindle number is -1,
+which means there is no spindle restriction.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='I'>interface</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>local</emphasis>.
+The name of a network interface definition in the
+<emphasis remap='B'>amanda.conf</emphasis>
+file, used to balance network load.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Instead of naming a
+<emphasis remap='B'>dumptype</emphasis>,
+it is possible to define one in-line, enclosing
+<emphasis remap='B'>dumptype</emphasis>
+options within curly braces, one per line, just like a
+<emphasis remap='B'>dumptype</emphasis>
+definition in
+<emphasis remap='B'>amanda.conf</emphasis>.
+Since pre-existing
+<emphasis remap='B'>dumptype</emphasis>s
+are valid option names, this syntax may be used to customize
+<emphasis remap='B'>dumptype</emphasis>s
+for particular disks.</para>
+
+<para>A line break
+<emphasis remap='B'>must</emphasis>
+follow the left curly bracket.</para>
+
+<para>For instance, if a
+<emphasis remap='B'>dumptype</emphasis>
+named
+<emphasis remap='I'>normal</emphasis>
+is used for most disks, but use of the holding disk needs to be disabled
+for the file system that holds it, this would work instead of defining
+a new dumptype:</para>
+
+<programlisting>
+<emphasis remap='I'>hostname diskname</emphasis> [ <emphasis remap='I'>diskdevice</emphasis> ] {
+  normal
+  holdingdisk no
+} [ <emphasis remap='I'>spindle</emphasis> [ <emphasis remap='I'>interface</emphasis> ] ]
+</programlisting>
+
+</refsect1>
+
+<refsect1><title>TAPE MANAGEMENT</title>
+<para>The
+<emphasis remap='I'>tapelist</emphasis>
+file contains the list of tapes in active use.
+This file is maintained entirely by &A; and should not be created
+or edited during normal operation.
+It contains lines of the form:</para>
+
+<para><programlisting>YYYYMMDD label flags
+</programlisting></para>
+
+<para>Where
+<emphasis remap='I'>YYYYMMDD</emphasis>
+is the date the tape was written,
+<emphasis remap='I'>label</emphasis>
+is a label for the tape as written by
+<emphasis remap='B'>amlabel</emphasis>
+and
+<emphasis remap='I'>flags</emphasis>
+tell &A; whether the tape may be reused, etc (see the
+<emphasis remap='B'>reuse</emphasis>
+options of
+<emphasis remap='B'>amadmin</emphasis>).</para>
+
+<para><emphasis remap='B'>Amdump</emphasis>
+and
+<emphasis remap='B'>amflush</emphasis>
+will refuse to write to an unlabeled tape, or to a labeled tape that is considered active.
+There must be more tapes in active rotation (see the
+<emphasis remap='B'>tapecycle</emphasis>
+option) than there are runs in the backup cycle (see the
+<emphasis remap='B'>dumpcycle</emphasis>
+option) to prevent overwriting a backup image that would be needed to do a full recovery.</para>
+</refsect1>
+
+<refsect1 id='output_drivers'><title>OUTPUT DRIVERS</title>
+<para>The normal value for the
+<emphasis remap='B'>tapedev</emphasis>
+parameter, or for what a tape changer returns,
+is a full path name to a non-rewinding tape device, such as
+<filename>/dev/nst0</filename>
+or
+<filename>/dev/rmt/0mn</filename>
+or
+<filename>/dev/nst0.1</filename>
+or whatever conventions the operating system uses. &A; provides additional application level drivers that
+support non-traditional tape-simulations or features. To access a specific output driver, set
+<emphasis remap='B'>tapedev</emphasis>
+(or configure your changer to return) a string of the form
+<emphasis remap='I'>driver</emphasis>:<emphasis remap='I'>driver-info</emphasis>
+where
+<emphasis remap='I'>driver</emphasis>
+is one of the supported drivers and
+<emphasis remap='I'>driver-info</emphasis>
+is optional additional information needed by the driver.</para>
+
+<para>The supported drivers are:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>tape</emphasis></term>
+  <listitem>
+<para>This is the default driver.
+The
+<emphasis remap='I'>driver-info</emphasis>
+is the tape device name.
+Entering
+<programlisting>tapedev /dev/rmt/0mn
+</programlisting>
+is really a short hand for
+<programlisting>tapedev tape:/dev/rmt/0mn
+</programlisting>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='I'>null</emphasis></term>
+  <listitem>
+<para>This driver throws away anything written to it and returns EOF
+for any reads except a special case is made for reading a label,
+in which case a &quot;fake&quot; value is returned that &A; checks for
+and allows through regardless of what you have set in
+<emphasis remap='B'>labelstr</emphasis>.
+The
+<emphasis remap='I'>driver-info</emphasis>
+field is not used and may be left blank:</para>
+
+<para><programlisting>tapedev null:
+</programlisting></para>
+
+<para>The <emphasis remap='I'>length</emphasis>
+value from the associated
+<emphasis remap='B'>tapetype</emphasis>
+is used to limit the amount of data written. When the limit is reached, the driver will simulate end of tape.</para>
+
+<note>This driver should only be used for debugging and testing,
+and probably only with the
+<emphasis remap='B'>record</emphasis>
+option set to
+<emphasis remap='I'>no</emphasis>.</note>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='I'>rait</emphasis></term>
+  <listitem>
+<para><emphasis remap='I'>R</emphasis>edundant
+<emphasis remap='I'>A</emphasis>rray
+of
+<emphasis remap='I'>I</emphasis>nexpensive (?)
+<emphasis remap='I'>T</emphasis>apes.
+Reads and writes tapes mounted on multiple drives by spreading
+the data across N-1 drives and using the last drive for a checksum.
+See docs/RAIT for more information.</para>
+
+<para>The
+<emphasis remap='I'>driver-info</emphasis>
+field describes the devices to use. Curly braces indicate multiple replacements in the string.
+For instance:</para>
+
+<para><programlisting>tapedev rait:/dev/rmt/tps0d{4,5,6}n
+</programlisting></para>
+
+<para>would use the following devices:</para>
+
+<para><filename>/dev/rmt/tps0d4n</filename>
+<filename>/dev/rmt/tps0d5n</filename>
+<filename>/dev/rmt/tps0d6n</filename>
+</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>file</emphasis></term>
+  <listitem>
+<para>This driver emulates a tape device with a set of files in a directory.
+The
+<emphasis remap='I'>driver-info</emphasis>
+field must be the name of an existing directory.
+The driver will test for a subdirectory of that named
+<emphasis remap='I'>data</emphasis>
+and return
+<emphasis remap='B'>offline</emphasis>
+until it is present.
+When present, the driver uses two files in the
+<emphasis remap='I'>data</emphasis>
+subdirectory for each tape file. One contains the actual data.
+The other contains record length information.</para>
+
+<para>The driver uses a file named
+<emphasis remap='I'>status</emphasis>
+in the
+<emphasis remap='B'>file</emphasis>
+device directory to hold driver status information, such as tape position.
+If not present, the driver will create it as though the device is rewound.</para>
+
+<para>The
+<emphasis remap='I'>length</emphasis>
+value from the associated
+<emphasis remap='B'>tapetype</emphasis>
+is used to limit the amount of data written.
+When the limit is reached, the driver will simulate end of tape.</para>
+
+<para>One way to use this driver with a real device such as a CD-writer is to
+create a directory for the
+<emphasis remap='B'>file</emphasis>
+device and one or more other directories for the actual data.
+Create a symlink named
+<emphasis remap='I'>data</emphasis>
+in the
+<emphasis remap='B'>file</emphasis>
+directory to one of the data directories.
+Set the
+<emphasis remap='B'>tapetype</emphasis>
+length to whatever the medium will hold.</para>
+
+<para>When &A; fills the
+<emphasis remap='B'>file</emphasis>
+device, remove the symlink and (optionally) create a new symlink to another
+data area.
+Use a CD writer software package to burn the image from the first data area.</para>
+
+<para>To read the CD, mount it and create the
+<emphasis remap='I'>data</emphasis>
+symlink in the
+<emphasis remap='B'>file</emphasis>
+device directory.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>AUTHORIZATION</title>
+<para>&A; processes on the tape server host run as the
+<emphasis remap='B'>dumpuser</emphasis>
+user listed in
+<emphasis remap='B'>amanda.conf</emphasis>.
+When they connect to a backup client, they do so with an &A;-specific protocol.
+They do not, for instance, use
+<emphasis remap='B'>rsh</emphasis>
+or
+<emphasis remap='B'>ssh</emphasis>
+directly.</para>
+
+<para>On the client side, the
+<emphasis remap='B'>amandad</emphasis>
+daemon validates the connection using one of several methods,
+depending on how it was compiled and on options it is passed:</para>
+
+<variablelist remap='IP'>
+  <varlistentry>
+  <term>.rhosts</term>
+  <listitem>
+<para>Even though &A; does not use
+<emphasis remap='B'>rsh</emphasis>,
+it can use
+<markup>.rhosts</markup>-style
+authentication and a
+<markup>.rhosts</markup>
+file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>.amandahosts</term>
+  <listitem>
+<para>This is essentially the same as
+<markup>.rhosts</markup>
+authentication except a different file, with almost the same format, is used.
+This is the default mechanism built into &A;.</para>
+
+<para>The format of the
+<filename>.amandahosts</filename>
+file is:</para>
+
+<para><emphasis remap='I'>hostname</emphasis>
+[
+<emphasis remap='I'>username</emphasis>
+]</para>
+
+<para>If
+<emphasis remap='I'>username</emphasis>
+is ommitted, it defaults to the user running
+<emphasis remap='B'>amandad</emphasis>,
+i.e. the user listed in the
+<emphasis remap='B'>inetd</emphasis>
+or
+<emphasis remap='B'>xinetd</emphasis>
+configuration file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>Kerberos</term>
+  <listitem>
+<para>&A; may use the Kerberos authentication system.
+Further information is in the
+<emphasis remap='B'>docs/KERBEROS</emphasis>
+<!-- TODO: edit link -->
+file that comes with an &A; distribution.</para>
+
+<para>For Samba access,
+&A; needs a file on the Samba server (which may
+or may not also be the tape server) named
+<filename>/etc/amandapass</filename>
+with share names, (clear text) passwords and (optional) domain names,
+in that order, one per line, whitespace separated.
+By default, the user used to connect to the PC is the same for all
+PC's and is compiled into &A;.
+It may be changed on a host by host basis
+by listing it first in the password field followed
+by a percent sign and then the password.
+For instance:</para>
+
+<programlisting>
+  //some-pc/home normalpw
+  //another-pc/disk otheruser%otherpw</programlisting>
+
+<para>With clear text passwords, this file should obviously be tightly protected.
+It only needs to be readable by the &A;-user on the Samba server.</para>
+
+<para>You can find further information in the
+<emphasis remap='B'>docs/SAMBA</emphasis>
+<!-- TODO: edit link -->
+file that comes with an &A; distribution.</para>
+
+</listitem>
+</varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>HOST &amp; DISK EXPRESSION</title>
+<para>All host and disk arguments to programs are special expressions.
+The command applies to all disks that match your arguments.
+This section describes the matcher.</para>
+
+<para>The matcher matches by word, each word is a glob expression, words
+are separated by the separator '.' for host and '/' for disk. You
+can anchor the expression at left with a '^'. You can
+anchor the expression at right with a '$'. The matcher
+is case insensitive for host but is case sensitive for disk. A match
+succeeds if all words in your expression match contiguous words in 
+the host or disk.</para>
+
+
+<literallayout remap='.nf'>
+.      word separator for a host
+/      word separator for a disk
+^      anchor at left
+$      anchor at right
+?      match exactly one character except the separator
+*      match zero or more characters except the separator
+**     match zero or more characters including the separator
+</literallayout>
+
+
+<para>Some examples:</para>
+
+<literallayout remap='.nf'>
+EXPRESSION     WILL MATCH           WILL NOT MATCH
+hosta          hosta                hostb
+               hoSTA.dOMAIna.ORG 
+               foo.hosta.org 
+host           host                 hosta
+host?          hosta                host
+               hostb 
+ho*na          hoina                ho.aina.org
+ho**na         hoina 
+               ho.aina.org 
+^hosta         hosta                foo.hosta.org
+sda*           /dev/sda1 
+               /dev/sda12 
+/opt/          opt (disk)           opt (host)
+.opt.          opt (host)           opt (disk)
+/              /                    any other disk
+/usr           /usr 
+               /usr/opt 
+/usr$          /usr                 /usr/opt
+</literallayout>
+
+
+</refsect1>
+
+<refsect1><title>DATESTAMP EXPRESSION</title>
+<para>A
+<emphasis remap='I'>datestamp</emphasis>
+expression is a range expression where we only match the prefix.
+Leading ^ is removed. Trailing $ forces an exact match.</para>
+
+<informaltable frame="all">
+<tgroup cols="2" alignment="left">
+<tbody>
+
+<row>
+<entry>20001212-14</entry>
+<entry>match all dates beginning with 20001212, 20001213 or 20001214</entry>
+</row>
+
+<row>
+<entry>20001212-4</entry>
+<entry>same as previous</entry>
+</row>
+
+<row>
+<entry>20001212-24</entry>
+<entry>match all dates between 20001212 and 20001224</entry>
+</row>
+
+<row>
+<entry>2000121</entry>
+<entry>match all dates that start with 2000121 (20001210-20001219)</entry>
+</row>
+
+<row>
+<entry>2</entry>
+<entry>match all dates that start with 2 (20000101-29991231)</entry>
+</row>
+
+<row>
+<entry>2000-10</entry>
+<entry>match all dates between 20000101-20101231</entry>
+</row>
+
+<row>
+<entry>200010$</entry>
+<entry>match only 200010</entry>
+</row>
+
+</tbody>
+</tgroup>
+</informaltable>
+<para/>
+
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds; : Original text</para>
+<para>&maintainer.sgw;: XML-conversion, major update</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para>
+<citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcheck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcheckdb</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcleanup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amfetchdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+<citerefentry><refentrytitle>amflush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amgetconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amlabel</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ammt</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amoverview</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amplot</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrecover</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amreport</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrmtape</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amstatus</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amtape</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amtapetype</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amtoc</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amverify</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amverifyrun</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amanda.conf.5.xml b/man/xml-source/amanda.conf.5.xml
new file mode 100644 (file)
index 0000000..a608c3a
--- /dev/null
@@ -0,0 +1,1811 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<refentry id='amanda.conf.5'>
+
+<refmeta>
+<refentrytitle>amanda.conf</refentrytitle>
+<manvolnum>5</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amanda.conf</refname>
+<refpurpose>Main configuration file for &A;, the Advanced Maryland Automatic Network Disk Archiver</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+
+<refsect1><title>DESCRIPTION</title>
+<para>&amconf; is the main configuration file for &A;. This manpage lists the
+relevant sections and parameters of this file for quick reference.</para> 
+</refsect1>
+
+<refsect1><title>PARAMETERS</title>
+
+<para>There are a number of configuration parameters that control the
+behavior of the &A; programs.
+All have default values,
+so you need not specify the parameter in
+<emphasis remap='B'>amanda.conf</emphasis>
+if the default is suitable.</para>
+
+<para>Lines starting with # are ignored, as are blank lines.
+Comments may be placed on a line with a directive by starting
+the comment with a #.
+The remainder of the line is ignored.</para>
+
+<para>Keywords are case insensitive, i.e.
+<emphasis remap='B'>mailto</emphasis>
+and
+<emphasis remap='B'>MailTo</emphasis>
+are treated the same.</para>
+
+<para>Integer arguments may have one of the following (case insensitive) suffixes,
+some of which have a multiplier effect:</para>
+
+<refsect2><title>POSSIBLE SUFFIXES</title>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>b byte bytes</emphasis></term>
+  <listitem>
+<para>Some number of bytes.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>bps</emphasis></term>
+  <listitem>
+<para>Some number of bytes per second.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>k kb kbyte kbytes kilobyte kilobytes</emphasis></term>
+  <listitem>
+<para>Some number of kilobytes (bytes*1024).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>kps kbps</emphasis></term>
+  <listitem>
+<para>Some number of kilobytes per second (bytes*1024).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>m mb meg mbyte mbytes megabyte megabytes</emphasis></term>
+  <listitem>
+<para>Some number of megabytes (bytes*1024*1024).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>mps mbps</emphasis></term>
+  <listitem>
+<para>Some number of megabytes per second (bytes*1024*1024).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>g gb gbyte gbytes gigabyte gigabytes</emphasis></term>
+  <listitem>
+<para>Some number of gigabytes (bytes*1024*1024*1024).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tape tapes</emphasis></term>
+  <listitem>
+<para>Some number of tapes.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>day days</emphasis></term>
+  <listitem>
+<para>Some number of days.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>week weeks</emphasis></term>
+  <listitem>
+<para>Some number of weeks (days*7).</para>
+
+<note>The value
+<emphasis remap='B'>inf</emphasis>
+may be used in most places where an integer is expected
+to mean an infinite amount.
+
+<para>Boolean arguments may have any of the values
+<emphasis remap='B'>y</emphasis>,
+<emphasis remap='B'>yes</emphasis>,
+<emphasis remap='B'>t</emphasis>,
+<emphasis remap='B'>true</emphasis>
+or
+<emphasis remap='B'>on</emphasis>
+to indicate a true state, or
+<emphasis remap='B'>n</emphasis>,
+<emphasis remap='B'>no</emphasis>,
+<emphasis remap='B'>f</emphasis>,
+<emphasis remap='B'>false</emphasis>
+or
+<emphasis remap='B'>off</emphasis>
+to indicate a false state.
+If no argument is given,
+<emphasis remap='B'>true</emphasis>
+is assumed.
+</para>
+</note>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect2>
+
+<refsect2>
+<title>PARAMETERS</title>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>org</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>daily</emphasis>.
+A descriptive name for the configuration.
+This string appears in the Subject line of mail reports.
+Each &A; configuration should have a different string to keep
+mail reports distinct.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>mailto</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>operators</emphasis>.
+A space separated list of recipients for mail reports.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>dumpcycle</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>10 days</emphasis>.
+The number of days in the backup cycle.
+Each disk will get a full backup at least this often.
+Setting this to zero tries to do a full backup each run.</para>
+<note>This parameter may also be set in a specific
+<emphasis remap='B'>dumptype</emphasis>
+(see below).
+This value sets the default for all
+<emphasis remap='B'>dumptype</emphasis>s
+so must appear in
+<emphasis remap='B'>amanda.conf</emphasis>
+before any
+<emphasis remap='B'>dumptype</emphasis>s
+are defined.</note>
+  </listitem>
+  </varlistentry>
+  
+  <varlistentry>
+  <term><emphasis remap='B'>runspercycle</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>same as dumpcycle</emphasis>.
+The number of amdump runs in 
+<emphasis remap='B'>dumpcycle</emphasis>
+days.
+A value of 0 means the same value as 
+<emphasis remap='B'>dumpcycle</emphasis>.
+A value of -1 means guess the number of runs from the
+<emphasis remap='I'>tapelist</emphasis>
+file, 
+which is the number of tapes used in the last 
+<emphasis remap='B'>dumpcycle</emphasis>
+days / 
+<emphasis remap='B'>runtapes</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tapecycle</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>15 tapes</emphasis>.
+Typically tapes are used by &A; in an ordered rotation. The <emphasis remap='B'>tapecycle</emphasis> parameter 
+defines the size of that rotation. The number of tapes in rotation must be larger than the number of tapes 
+required for a complete dump cycle (see the <emphasis remap='B'>dumpcycle</emphasis> parameter). 
+</para>
+<para>
+This is calculated by multiplying the number of &amdump; runs per dump cycle
+(<emphasis remap='B'>runspercycle</emphasis> parameter) times the number of tapes used per run 
+(<emphasis remap='B'>runtapes</emphasis> parameter). Typically two to four times this calculated number of tapes are in rotation.
+While &A; is always willing to use a new tape in its rotation, it refuses to reuse a tape until at 
+least '<emphasis remap='B'>tapecycle</emphasis> -1' number of other tapes have been used. 
+</para>
+<para>
+It is considered good administrative practice to set the <emphasis remap='B'>tapecycle</emphasis> parameter 
+slightly lower than the actual number of tapes in rotation. This allows the administrator to more easily cope 
+with damaged or misplaced tapes or schedule adjustments that call for slight adjustments in the rotation order.
+</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>label_new_tapes</emphasis>
+        <emphasis remap='I'> string</emphasis></term>
+<listitem>
+    <para>Default: not set.
+When set, this directive will cause &A; to automatically write an &A;
+tape label to any blank tape she encounters. This option is DANGEROUS 
+because when set, &A; will ERASE any non-&A; tapes you may have, and may 
+also ERASE any near-failing tapes. Use with caution.</para>
+<para>When using this directive, specify the template for new tape 
+labels. The template should contain some number of contiguous '%' 
+characters, which will be replaced with a generated number. Be sure to 
+specify enough '%' characters that you do not run out of tape labels. 
+Example: 
+<markup>label_new_tapes "DailySet1-%%%"</markup>
+</para>
+</listitem>
+</varlistentry>
+
+  <varlistentry>
+=======
+  <term><emphasis remap='B'>label_new_tapes</emphasis>
+        <emphasis remap='I'> string</emphasis></term>
+<listitem>
+    <para>Default: not set.
+When set, this directive will cause &A; to automatically write an Amanda 
+tape label to any black tape she encounters. This option is DANGEROUS 
+because when set, &A; will ERASE any non-&A; tapes you may have, and may 
+also ERASE any near-failing tapes. Use with caution.</para>
+<para>When using this directive, specify the template for new tape 
+labels. The template should contain some number of contiguous '%' 
+characters, which will be replaced with a generated number. Be sure to 
+specify enough '%' characters that you do not run out of tape labels. 
+Example: 
+<markup>label_new_tapes "DailySet1-%%%"</markup>
+</para>
+</listitem>
+</varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>dumpuser</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>amanda</emphasis>.
+The login name &A; uses to run the backups.
+The backup client hosts must allow access
+from the tape server host as this user via
+<markup>.rhosts</markup>
+or
+<markup>.amandahosts</markup>,
+depending on how the &A; software was built.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>printer</emphasis> string</term>
+  <listitem>
+<para>Printer to use when doing tape labels.
+See the
+<emphasis remap='B'>lbl-templ</emphasis>
+<emphasis remap='B'>tapetype</emphasis>
+option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tapedev</emphasis> string</term>
+  <listitem>
+<para>Default:
+<filename>null:</filename>.
+The path name of the non-rewinding tape device.
+Non-rewinding tape device names often have an 'n' in the name,
+e.g.
+<filename>/dev/rmt/0mn</filename>,
+however this is operating system specific and you should consult
+that documentation for detailed naming information.</para>
+
+<para>If a tape changer is configured
+(see the
+<emphasis remap='B'>tpchanger</emphasis>
+option), this option might not be used.</para>
+
+<para>If the
+<emphasis remap='B'>null</emphasis>
+output driver is selected
+(see the section OUTPUT DRIVERS in the 
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry> 
+manpage for more information),
+programs such as
+&amdump;
+will run normally but all images will be thrown away.
+This should only be used for debugging and testing,
+and probably only with the
+<emphasis remap='B'>record</emphasis>
+option set to
+<emphasis remap='I'>no</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>rawtapedev</emphasis> string</term>
+  <listitem>
+<para>Default:
+<filename>null:</filename>.
+The path name of the raw tape device.
+This is only used if &A; is compiled for Linux machines with floppy tapes
+and is needed for QIC volume table operations.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tpchanger</emphasis> string</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+The name of the tape changer.
+If a tape changer is not configured, this option is not used
+and should be commented out of the configuration file.</para>
+<para>If a tape changer is configured, choose one of the changer scripts
+(e.g.  <emphasis remap='B'>chg-scsi</emphasis>)
+and enter that here.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>changerdev</emphasis> string</term>
+  <listitem>
+<para>Default:
+<filename>/dev/null</filename>.
+A tape changer configuration parameter.
+Usage depends on the particular changer defined with the
+<emphasis remap='B'>tpchanger</emphasis>
+option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>changerfile</emphasis> string</term>
+  <listitem>
+<para>Default:
+<filename>/usr/adm/amanda/log/changer-status</filename>.
+A tape changer configuration parameter.
+Usage depends on the particular changer defined with the
+<emphasis remap='B'>tpchanger</emphasis>
+option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>runtapes</emphasis> int</term>
+  <listitem>
+<para>Default:
+<literal>1</literal>.
+The maximum number of tapes used in a single run.
+If a tape changer is not configured, this option is not used
+and should be commented out of the configuration file.</para>
+<para>If a tape changer is configured, this may be set larger than one to
+let &A; write to more than one tape.</para>
+<para>Note that this is an upper bound on the number of tapes,
+and &A; may use less.</para>
+<para>Also note that as of this release, &A; does not support true tape overflow.
+When it reaches the end of one tape,
+the backup image &A; was processing starts over again on the next tape.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>maxdumpsize</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>runtapes</emphasis>*<emphasis remap='I'>tape_length</emphasis>.
+Maximum number of bytes the planner will schedule for a run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>taperalgo</emphasis> [first|firstfit|largest|largestfit|smallest|last]</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>first</emphasis>.
+The algorithm used to choose which dump image to send to the taper.</para>
+  <!-- .RS -->
+    <variablelist remap='TP'>
+      <varlistentry>
+      <term><emphasis remap='B'>first</emphasis></term>
+      <listitem>
+<para>First in, first out.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term><emphasis remap='B'>firstfit</emphasis></term>
+      <listitem>
+<para>The first dump image that will fit on the current tape.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term><emphasis remap='B'>largest</emphasis></term>
+      <listitem>
+<para>The largest dump image.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term><emphasis remap='B'>largestfit</emphasis></term>
+      <listitem>
+<para>The largest dump image that will fit on the current tape.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term><emphasis remap='B'>smallest</emphasis></term>
+      <listitem>
+<para>The smallest dump image.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term><emphasis remap='B'>last</emphasis></term>
+      <listitem>
+<para>Last in, first out.</para>
+      </listitem>
+      </varlistentry>
+    </variablelist>
+  
+  </listitem>
+  </varlistentry>
+<varlistentry>
+<term><emphasis remap='B'>labelstr</emphasis> <emphasis remap='I'> string</emphasis></term>
+<listitem>
+<para>Default:
+<emphasis remap='I'>.*</emphasis>.
+The tape label constraint regular expression.
+All tape labels generated (see
+<citerefentry><refentrytitle>amlabel</refentrytitle><manvolnum>8</manvolnum></citerefentry>)
+and used by this configuration must match the regular expression.
+If multiple configurations are run from the same tape server host,
+it is helpful to set their labels to different strings
+(for example, &quot;DAILY[0-9][0-9]*&quot; vs.
+&quot;ARCHIVE[0-9][0-9]*&quot;)
+to avoid overwriting each other's tapes.</para>
+</listitem>
+</varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tapetype</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>EXABYTE</emphasis>.
+The type of tape drive associated with
+<emphasis remap='B'>tapedev</emphasis>
+or
+<emphasis remap='B'>tpchanger</emphasis>.
+This refers to one of the defined <emphasis remap='B'>tapetype</emphasis>s
+in the config file (see below), which specify various tape parameters,
+like the
+<emphasis remap='B'>length</emphasis>,
+<emphasis remap='B'>filemark</emphasis>
+size, and
+<emphasis remap='B'>speed</emphasis>
+of the tape media and device.</para>
+<para>First character of a <emphasis remap='B'>tapetype</emphasis> string must
+be an alphabetic character</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>ctimeout</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>30 seconds</emphasis>.
+Maximum amount of time that
+<emphasis remap='B'>amcheck</emphasis>
+will wait for each client host.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>dtimeout</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>1800 seconds</emphasis>.
+Amount of idle time per disk on a given client that a
+<emphasis remap='B'>dumper</emphasis>
+running from within
+<command>amdump</command>
+will wait before it fails with a data timeout error.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>etimeout</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>300 seconds</emphasis>.
+Amount of time per disk on a given client that the
+<emphasis remap='B'>planner</emphasis>
+step of
+<command>amdump</command>
+will wait to get the dump size estimates.
+For instance, with the default of 300 seconds and four disks on client A, 
+<emphasis remap='B'>planner</emphasis>
+will wait up to 20 minutes for that machine.
+A negative value will be interpreted as a total amount of time to wait
+per client instead of per disk.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>netusage</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>300 Kbps</emphasis>.
+The maximum network bandwidth allocated to &A;, in Kbytes per second.
+See also the
+<emphasis remap='B'>interface</emphasis>
+section.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>inparallel</emphasis> int</term>
+  <listitem>
+<para>Default:
+<literal>10</literal>.
+The maximum number of backups that &A; will attempt to run in parallel.
+&A; will stay within the constraints of network bandwidth and
+holding disk space available, so it doesn't hurt to set
+this number a bit high. Some contention can occur with larger numbers
+of backups, but this effect is relatively small on most systems.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>displayunit</emphasis> &quot;k|m|g|t&quot;</term>
+  <listitem>
+<para>Default:
+<literal>&quot;k&quot;</literal>.
+The unit used to print many numbers, k=kilo, m=mega, g=giga, t=tera.
+</para>
+  </listitem>
+  </varlistentry>
+  
+  <varlistentry>
+  <term><emphasis remap='B'>dumporder</emphasis> string</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>tttTTTTTTT</emphasis>.
+The priority order of each dumper:</para>
+
+<itemizedlist>
+<listitem><para>s: smallest size</para></listitem>
+<listitem><para>S: largest size</para></listitem>
+<listitem><para>t: smallest time</para></listitem>
+<listitem><para>T: largest time</para></listitem>
+<listitem><para>b: smallest bandwidth</para></listitem>
+<listitem><para>B: largest bandwidth</para></listitem>
+</itemizedlist>
+
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>maxdumps</emphasis> int</term>
+  <listitem>
+<para>Default:
+<literal>1</literal>.
+The maximum number of backups from a single host that &A; will
+attempt to run in parallel. See also the
+<emphasis remap='B'>inparallel</emphasis>
+option.</para>
+
+<para>Note that this parameter may also be set in a specific
+<emphasis remap='B'>dumptype</emphasis>
+(see below).
+This value sets the default for all
+<emphasis remap='B'>dumptype</emphasis>s
+so must appear in
+<emphasis remap='B'>amanda.conf</emphasis>
+before any
+<emphasis remap='B'>dumptype</emphasis>s
+are defined.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>bumpsize</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>10 Mbytes</emphasis>.
+The minimum savings required to trigger an automatic
+bump from one incremental level to the next, expressed as size.
+If &A; determines that the next higher backup level
+will be this much smaller than the current level,
+it will do the next level.
+The value of this parameter is used only if the parameter 
+<emphasis>bumppercent</emphasis> is set to 0.
+</para>
+<para>
+The global setting of this parameter can be overwritten inside of a  
+dumptype-definition.  
+</para>
+<para>
+See also the options 
+<emphasis remap='B'>bumppercent</emphasis>,
+<emphasis remap='B'>bumpmult</emphasis> and
+<emphasis remap='B'>bumpdays</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>bumppercent</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>0 percent</emphasis>.
+The minimum savings required to trigger an automatic
+bump from one incremental level to the next, expressed as percentage of the
+current size of the DLE (size of current level 0).
+If &A; determines that the next higher backup level
+will be this much smaller than the current level,
+it will do the next level.
+</para>
+<para>
+If this parameter is set to 0, the value of the
+parameter <emphasis>bumpsize</emphasis> is used to trigger bumping.
+</para>
+<para>
+The global setting of this parameter can be overwritten inside of a  
+dumptype-definition.  
+</para>
+<para>
+See also the options 
+<emphasis remap='B'>bumpsize</emphasis>,
+<emphasis remap='B'>bumpmult</emphasis> and
+<emphasis remap='B'>bumpdays</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>bumpmult</emphasis> <emphasis remap='I'> float</emphasis></term>
+  <listitem>
+<para>Default:
+<literal>1.5</literal>.
+The bump size multiplier.
+&A; multiplies
+<emphasis remap='B'>bumpsize</emphasis>
+by this factor for each level.
+This prevents active filesystems from
+bumping too much by making it harder to bump to the next level.
+For example, with the default
+<emphasis remap='B'>bumpsize</emphasis>
+and
+<emphasis remap='B'>bumpmult</emphasis>
+set to 2.0, the bump threshold will be 10 Mbytes for level one, 20
+Mbytes for level two, 40 Mbytes for level three, and so on.</para>
+<para>
+The global setting of this parameter can be overwritten inside of a  
+dumptype-definition.  
+</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>bumpdays</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>2 days</emphasis>.
+To insure redundancy in the dumps, &A; keeps filesystems at the
+same incremental level for at least
+<emphasis remap='B'>bumpdays</emphasis>
+days, even if the other bump threshold criteria are met.</para>
+<para>
+The global setting of this parameter can be overwritten inside of a  
+dumptype-definition.  
+</para>
+  </listitem>
+  </varlistentry>
+  
+  <varlistentry>
+  <term><emphasis remap='B'>diskfile</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>disklist</emphasis>.
+The file name for the
+<emphasis remap='I'>disklist</emphasis>
+file holding client hosts, disks and other client dumping information.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>infofile</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<filename>/usr/adm/amanda/curinfo</filename>.
+The file or directory name for the historical information database.
+If &A; was configured to use DBM databases, this is the base file
+name for them.
+If it was configured to use text formated databases (the default),
+this is the base directory and within here will be a directory per
+client, then a directory per disk, then a text file of data.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>logdir</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<filename>/usr/adm/amanda</filename>.
+The directory for the
+<command>amdump</command>
+and
+<emphasis remap='B'>log</emphasis>
+files.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>indexdir</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default
+<filename>/usr/adm/amanda/index</filename>.
+The directory where index files (backup image catalogues) are stored.
+Index files are
+only generated for filesystems whose
+<emphasis remap='B'>dumptype</emphasis>
+has the
+<emphasis remap='B'>index</emphasis>
+option enabled.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tapelist</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>tapelist</emphasis>.
+The file name for the active
+<emphasis remap='I'>tapelist</emphasis>
+file.
+&A; maintains this file with information about the active set of tapes.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>tapebufs</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<literal>20</literal>.
+The number of buffers used by the
+<emphasis remap='B'>taper</emphasis>
+process run by
+<command>amdump</command>
+and
+<emphasis remap='B'>amflush</emphasis>
+to hold data as it is read from the network or disk before it is written to tape.
+Each buffer is a little larger than 32 KBytes and is held in a shared memory region.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>reserve</emphasis> <emphasis remap='I'> number</emphasis></term>
+  <listitem>
+<para>Default:
+<literal>100</literal>.
+The part of holding-disk space that should be reserved for incremental
+backups if no tape is available, expressed as a percentage of the 
+available holding-disk space (0-100).
+By default, when there is no tape to write to, degraded mode (incremental) backups 
+will be performed to the holding disk. If full backups should also be allowed in this case,
+the amount of holding disk space reserved for incrementals should be lowered.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>autoflush</emphasis> <emphasis remap='I'> bool</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>off</emphasis>.
+Whether an amdump run will flush the dumps from holding disk to tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amrecover_do_fsf</emphasis> <emphasis remap='I'> bool</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>off</emphasis>.
+Amrecover will call amrestore with the -f flag for faster positioning of the tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amrecover_check_label</emphasis> <emphasis remap='I'> bool</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>off</emphasis>.
+Amrecover will call amrestore with the -l flag to check the label.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>amrecover_changer</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default: ''.
+Amrecover will use the changer if you use 'settape &lt;string&gt;' and that string
+is the same as the amrecover_changer setting.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>columnspec</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Defines the width of columns <emphasis remap='B'>amreport</emphasis>
+should use.
+<emphasis remap='I'>String</emphasis>
+is a comma (',') separated list of triples. Each triple consists
+of three parts which are separated by a equal sign ('=') and a colon (':') (see the example).
+These three parts specify:</para>
+  
+  <itemizedlist>
+  <listitem>
+      <para>the name of the column, which may be:</para>
+
+       <itemizedlist>
+       <listitem><para>Compress (compression ratio)</para></listitem>
+       <listitem><para>Disk (client disk name)</para></listitem>
+       <listitem><para>DumpRate (dump rate in KBytes/sec)</para></listitem>
+       <listitem><para>DumpTime (total dump time in hours:minutes)</para></listitem>
+       <listitem><para>HostName (client host name)</para></listitem>
+       <listitem><para>Level (dump level)</para></listitem>
+       <listitem><para>OrigKB (original image size in KBytes)</para></listitem>
+       <listitem><para>OutKB (output image size in KBytes)</para></listitem>
+       <listitem><para>TapeRate (tape writing rate in KBytes/sec)</para></listitem>
+       <listitem><para>TapeTime (total tape time in hours:minutes)</para></listitem>
+       </itemizedlist>
+
+  </listitem>
+
+  <listitem>
+<para>the amount of space to display before the column (used to get whitespace between columns).</para>
+  </listitem>
+  <listitem>
+<para>the width of the column itself.
+If set to a negative value, the width will be calculated on demand to fit the largest entry in
+this column.</para>
+  </listitem>
+  </itemizedlist>
+
+<para>Here is an example:</para>
+
+<programlisting>
+<para>columnspec &quot;Disk=1:18,HostName=0:10,OutKB=1:7&quot;</para>
+</programlisting>
+The above will display the disk information in 18 characters
+and put one space before it. The hostname column will be 10 characters wide with
+no space to the left. The output KBytes column is seven characters wide
+with one space before it.
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>includefile</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+The name of an &A; configuration file to include within the current file.
+Useful for sharing dumptypes, tapetypes and interface definitions among several configurations.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect2>
+</refsect1>
+
+<refsect1><title>HOLDINGDISK SECTION</title>
+<para>The <emphasis remap='B'>amanda.conf</emphasis>
+file may define one or more holding disks used as buffers to hold
+backup images before they are written to tape.
+The syntax is:</para>
+
+<programlisting>
+holdingdisk <emphasis remap='I'>name</emphasis> {
+    <emphasis remap='I'>holdingdisk-option</emphasis> <emphasis remap='I'>holdingdisk-value</emphasis>
+    <literal>...</literal>
+}</programlisting>
+
+<para><emphasis remap='I'>Name</emphasis>
+is a logical name for this holding disk.</para>
+
+<para>The options and values are:</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>comment</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+A comment string describing this holding disk.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>directory</emphasis> <emphasis remap='I'> disk</emphasis></term>
+  <listitem>
+<para>Default:
+<filename>/dumps/amanda</filename>.
+The path to this holding area.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>use</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+Default:
+<emphasis remap='I'>0 Gb</emphasis>.
+Amount of space that can be used in this holding disk area.
+If the value is zero, all available space on the file system is used.
+If the value is negative, &A; will use all available space minus that value.
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>chunksize</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+Default:
+<emphasis remap='I'>1 Gb</emphasis>.
+Holding disk chunk size. Dumps larger than the specified size will be stored in multiple
+holding disk files. The size of each chunk will not exceed the specified value.
+However, even though dump images are split in the holding disk, they are concatenated as 
+they are written to tape, so each dump image still corresponds to a single continuous 
+tape section.
+
+If 0 is specified, &A; will create holding disk chunks as large as
+((INT_MAX/1024)-64) Kbytes.
+
+Each holding disk chunk includes a 32 Kbyte header, so the minimum
+chunk size is 64 Kbytes (but that would be really silly).
+
+Operating systems that are limited to a maximum file size of 2 Gbytes
+actually cannot handle files that large.
+They must be at least one byte less than 2 Gbytes.
+Since &A; works with 32 Kbyte blocks, and
+to handle the final read at the end of the chunk, the chunk size
+should be at least 64 Kbytes (2 * 32 Kbytes) smaller than the maximum
+file size, e.g. 2047 Mbytes.
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>DUMPTYPE SECTION</title>
+<para>The &amconf; file may define multiple sets of backup options 
+and refer to them by name from the &disklist; file.
+For instance, one set of options might be defined for file systems
+that can benefit from high compression, another set that does not compress well,
+another set for file systems that should always get a full backup and so on.</para>
+
+<para>A set of backup options are entered in a
+<emphasis remap='B'>dumptype</emphasis>
+section, which looks like this:</para>
+
+<programlisting>
+define dumptype <emphasis remap='I'>name</emphasis> {
+    <emphasis remap='I'>dumptype-option</emphasis> <emphasis remap='I'>dumptype-value</emphasis>
+    <literal>...</literal>
+}
+</programlisting>
+
+<para><emphasis remap='I'>Name</emphasis>
+is the name of this set of backup options.
+It is referenced from the &disklist; file.</para>
+
+<para>Some of the options in a
+<emphasis remap='B'>dumptype</emphasis>
+section are the same as those in the main part of &amconf;.
+The main option value is used to set the default for all
+<emphasis remap='B'>dumptype</emphasis>
+sections. For instance, setting
+<emphasis remap='B'>dumpcycle</emphasis>
+to 50 in the main part of the config file causes all following
+<emphasis remap='B'>dumptype</emphasis>
+sections to start with that value,
+but the value may be changed on a section by section basis.
+Changes to variables in the main part of the config file must be
+done before (earlier in the file) any
+<emphasis remap='B'>dumptype</emphasis>s
+are defined.</para>
+
+<para>The dumptype options and values are:</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>auth</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>bsd</emphasis>.
+Type of authorization to perform between tape server and backup client hosts.</para>
+<para><emphasis remap='B'>krb4</emphasis> to use Kerberos-IV
+authorization.</para>
+<para><emphasis remap='B'>krb5</emphasis> to use Kerberos-V
+authorization.</para>
+<para><emphasis remap='B'>ssh</emphasis> to use OpenSSH
+authorization.</para>
+
+  </listitem>
+  </varlistentry>
+
+<!-- bumping parameters yanked from the global section above -->
+
+  <varlistentry>
+  <term><emphasis remap='B'>bumpsize</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>10 Mbytes</emphasis>.
+The minimum savings required to trigger an automatic
+bump from one incremental level to the next, expressed as size.
+If &A; determines that the next higher backup level
+will be this much smaller than the current level,
+it will do the next level.
+The value of this parameter is used only if the parameter 
+<emphasis>bumppercent</emphasis> is set to 0.
+</para>
+<para>
+See also the options 
+<emphasis remap='B'>bumppercent</emphasis>,
+<emphasis remap='B'>bumpmult</emphasis> and
+<emphasis remap='B'>bumpdays</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>bumppercent</emphasis> int</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>0 percent</emphasis>.
+The minimum savings required to trigger an automatic
+bump from one incremental level to the next, expressed as percentage of the
+current size of the DLE (size of current level 0).
+If &A; determines that the next higher backup level
+will be this much smaller than the current level,
+it will do the next level.
+</para>
+<para>
+If this parameter is set to 0, the value of the
+parameter <emphasis>bumpsize</emphasis> is used to trigger bumping.
+</para>
+<para>
+See also the options 
+<emphasis remap='B'>bumpsize</emphasis>,
+<emphasis remap='B'>bumpmult</emphasis> and
+<emphasis remap='B'>bumpdays</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>bumpmult</emphasis> <emphasis remap='I'> float</emphasis></term>
+  <listitem>
+<para>Default:
+<literal>1.5</literal>.
+The bump size multiplier.
+&A; multiplies
+<emphasis remap='B'>bumpsize</emphasis>
+by this factor for each level.
+This prevents active filesystems from
+bumping too much by making it harder to bump to the next level.
+For example, with the default
+<emphasis remap='B'>bumpsize</emphasis>
+and
+<emphasis remap='B'>bumpmult</emphasis>
+set to 2.0, the bump threshold will be 10 Mbytes for level one, 20
+Mbytes for level two, 40 Mbytes for level three, and so on.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>bumpdays</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>2 days</emphasis>.
+To insure redundancy in the dumps, &A; keeps filesystems at the
+same incremental level for at least
+<emphasis remap='B'>bumpdays</emphasis>
+days, even if the other bump threshold criteria are met.</para>
+  </listitem>
+  </varlistentry>
+  
+  <varlistentry>
+  <term><emphasis remap='B'>comment</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+A comment string describing this set of backup options.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>comprate</emphasis> <emphasis remap='I'>float</emphasis> [, <emphasis remap='I'>float</emphasis> ]</term>
+  <listitem>
+<para>Default:
+<literal>0.50</literal>,
+<literal>0.50</literal>.
+The expected full and incremental compression factor for dumps.
+It is only used if &A; does not have any history information on
+compression rates for a filesystem, so should not usually need to be set.
+However, it may be useful for the first time a very large filesystem that 
+compresses very little is backed up.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>compress [client|server]</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>client fast</emphasis>.
+If &A; does compression of the backup images, it can do so either on the backup client 
+host before it crosses the network or on the tape server host as it goes from the
+network into the holding disk or to tape.  Which place to do compression (if at all) depends on how well the
+dump image usually compresses, the speed and load on the client or server, network capacity, 
+holding disk capacity, availability of tape hardware compression, etc.</para>
+
+<para>For either type of compression, &A; also allows the selection
+of three styles of compression.
+<emphasis remap='B'>Best</emphasis>
+is the best compression available, often at the expense of CPU overhead.
+<emphasis remap='B'>Fast</emphasis>
+is often not as good a compression as
+<emphasis remap='B'>best</emphasis>,
+but usually less CPU overhead. Or to specify <emphasis remap='B'>Custom</emphasis>
+to use your own compression method. (See dumptype custom-compress in example/amanda.conf for reference)</para>
+
+
+
+<para>So the <emphasis remap='B'>compress</emphasis> options line may be one of:</para>
+
+<itemizedlist>
+<listitem><para>compress none</para></listitem>
+<listitem><para>compress [client] fast</para></listitem>
+<listitem><para>compress [client] best</para></listitem>
+<listitem><para>compress client custom</para>
+<para>Specify client_custom_compress &quot;PROG&quot;</para>
+<para>PROG must not contain white space and it must accept -d for uncompress.</para></listitem>
+<listitem><para>compress server fast</para></listitem>
+<listitem><para>compress server best</para></listitem>
+<listitem><para>compress server custom</para>
+<para>Specify server_custom_compress &quot;PROG&quot;</para>
+<para>PROG must not contain white space and it must accept -d for uncompress.</para></listitem>
+</itemizedlist>
+
+<para>Note that some tape devices do compression and this option has nothing
+to do with whether that is used. If hardware compression is used (usually via a particular tape device name
+or <emphasis remap='B'>mt</emphasis> option), &A; (software) compression should be disabled.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>dumpcycle</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default: <emphasis remap='I'>10 days</emphasis>.
+The number of days in the backup cycle. Each disk using this set of options will get a full 
+backup at least this of
+ten. Setting this to zero tries to do a full backup each run.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>encrypt [none|client|server]</emphasis></term>
+  <listitem>
+<para>Default: <emphasis remap='I'>none</emphasis>.
+To encrypt backup images, it can do so either on the backup client host before it crosses the network or on the tape
+server host as it goes from the network into the holding disk or to tape.</para>
+
+<para>So the <emphasis remap='B'>encrypt</emphasis> options line may be one
+           of:</para>
+
+<itemizedlist>
+<listitem><para>encrypt none</para></listitem>
+<listitem><para>encrypt client</para>
+<para>Specify client_encrypt &quot;PROG&quot;</para>
+<para>PROG must not contain white space.</para>
+<para>Specify client_decrypt_option &quot;decryption-parameter&quot; Default: &quot;-d&quot;</para>
+<para>decryption-parameter must not contain white space.</para>
+<para>(See dumptype encrypt-fast in example/amanda.conf for reference)</para>
+</listitem>
+<listitem><para>encrypt server</para>
+<para>Specify server_encrypt &quot;PROG&quot;</para>
+<para>PROG must not contain white space.</para>
+<para>Specify server_decrypt_option &quot;decryption-parameter&quot; Default: &quot;-d&quot;</para>
+<para>decryption-parameter must not contain white space.</para>
+</listitem>
+</itemizedlist>
+</listitem>
+<para>Note that current logic assumes compression then encryption during
+backup(thus decrypt then uncompress during restore). So specifying
+client-encryption AND server-compression is not supported.
+<emphasis remap='I'>amcrypt</emphasis> which is a wrapper of
+           <emphasis remap='I'>aespipe</emphasis> is provided as a reference
+               encryption program.</para>
+</varlistentry>
+
+
+  <varlistentry>
+  <term><emphasis remap='B'>estimate</emphasis> <emphasis remap='I'>client|calcsize|server</emphasis></term>
+  <listitem>
+<para>Default: <emphasis remap='I'>client</emphasis>.
+Determine the way &A; does it's estimate.</para>
+<itemizedlist>
+<listitem>
+<para>client:</para>
+<para>
+Use the same program as the dumping program, this is the most accurate way to do estimates, but it can take a long time.
+</para>
+</listitem>
+<listitem>
+<para>calcsize:</para>
+<para>Use a faster program to do estimates, but the result is less accurate.</para>
+</listitem>
+<listitem>
+<para>server:</para>
+<para>Use only statistics from the previous run to give an estimate, 
+it takes only a few seconds but the result is not accurate if your disk 
+usage changes from day to day.
+</para>
+  </listitem>
+  </itemizedlist>
+  </listitem>
+  </varlistentry>
+
+  
+  <varlistentry>
+  <term><emphasis remap='B'>exclude</emphasis> [ <emphasis remap='I'>list|file</emphasis> ][[optional][ <emphasis remap='I'>append</emphasis> ][ <emphasis remap='I'> string</emphasis> ]+]</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>file</emphasis>.
+There are two exclude lists,
+<emphasis remap='B'>exclude file</emphasis>
+and
+<emphasis remap='B'>exclude list.</emphasis>
+With
+<emphasis remap='B'>exclude file</emphasis>
+, the
+<emphasis remap='I'>string</emphasis>
+is a &gnutar; exclude expression. With
+<emphasis remap='B'>exclude list</emphasis>
+, the
+<emphasis remap='I'>string</emphasis>
+is a file name on the client containing &gnutar; exclude expressions.
+The path to the specified exclude list file, if present (see description of
+'optional' below), must be readable by the &A; user.</para>
+
+<para>All exclude expressions are concatenated in one file and passed to &gnutar;
+as an <option>--exclude-from</option> argument.</para>
+
+<para>Exclude expressions must always be specified as relative to the
+head directory of the DLE.</para>
+
+<para>With the
+<emphasis remap='B'>append</emphasis> keyword, the
+<emphasis remap='I'>string</emphasis> is appended to the current list, without it, the
+<emphasis remap='I'>string</emphasis> overwrites the list.</para>
+
+<para>If <emphasis remap='B'>optional</emphasis>
+is specified for <emphasis remap='B'>exclude list</emphasis>,
+then amcheck will not complain if the file doesn't exist or is not readable.</para>
+
+<para>For <emphasis remap='B'>exclude list</emphasis>,
+if the file name is relative, the disk name being backed up is prepended.
+So if this is entered:</para>
+
+<programlisting>
+    exclude list &quot;.amanda.excludes&quot;
+</programlisting>
+
+<para>the actual file used would be
+<filename>/var/.amanda.excludes</filename>
+for a backup of <filename>/var</filename>,
+<filename>/usr/local/.amanda.excludes</filename> for a backup of
+<filename>/usr/local</filename>, and so on.</para>
+</listitem>
+</varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>holdingdisk</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>yes</emphasis>.
+Whether a holding disk should be used for these backups or whether they should go directly to tape.
+If the holding disk is a portion of another file system that &A;
+is backing up, that file system should refer to a dumptype with
+<emphasis remap='B'>holdingdisk</emphasis>
+set to
+<emphasis remap='I'>no</emphasis>
+to avoid backing up the holding disk into itself.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>ignore</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>no</emphasis>.
+Whether disks associated with this backup type should be backed up or not.
+This option is useful when the
+<emphasis remap='I'>disklist</emphasis>
+file is shared among several configurations,
+some of which should not back up all the listed file systems.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>include</emphasis> [ <emphasis remap='I'>list|file</emphasis> ][[optional][ <emphasis remap='I'>append</emphasis> ][ <emphasis remap='I'> string</emphasis> ]+]</term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>file</emphasis>
+&quot;.&quot;.
+There are two include lists,
+<emphasis remap='B'>include file</emphasis>
+and
+<emphasis remap='B'>include list.</emphasis>
+With
+<emphasis remap='B'>include file</emphasis>
+, the
+<emphasis remap='I'>string</emphasis>
+is a glob expression. With
+<emphasis remap='B'>include list</emphasis>
+, the
+<emphasis remap='I'>string</emphasis>
+is a file name on the client containing glob expressions.</para>
+
+<para>All include expressions are expanded by &A;, concatenated in one file and passed to &gnutar; as a
+<option>--files-from</option> argument. They must start with &quot;./&quot; and contain no other &quot;/&quot;.</para>
+
+<para>Include expressions must always be specified as relative to the
+head directory of the DLE.</para>
+
+<note>For globbing to work at all, even the limited single level, 
+the top level directory of the DLE must be readable by the &A; user.</note>
+
+<para>With the <emphasis remap='B'>append</emphasis> keyword, the
+<emphasis remap='I'>string</emphasis> is appended to the current list, without it, the
+<emphasis remap='I'>string</emphasis> overwrites the list.</para>
+
+<para>If
+<emphasis remap='B'>optional</emphasis> is specified for
+<emphasis remap='B'>include list,</emphasis> then amcheck will not complain if the file 
+doesn't exist or is not readable.</para>
+
+<para>For <emphasis remap='B'>include list</emphasis>,
+If the file name is relative, the disk name being backed up is prepended.</para>
+</listitem>
+</varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>index</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default: <emphasis remap='I'>no</emphasis>.
+Whether an index (catalogue) of the backup should be generated and saved in
+<emphasis remap='B'>indexdir</emphasis>.
+These catalogues are used by the <emphasis remap='B'>amrecover</emphasis> utility.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>kencrypt</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>no</emphasis>.
+Whether the backup image should be encrypted by Kerberos as it is sent
+across the network from the backup client host to the tape server host.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>maxdumps</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<literal>1</literal>.
+The maximum number of backups from a single host that &A; will attempt to run in parallel.
+See also the main section parameter <emphasis remap='B'>inparallel</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>maxpromoteday</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<literal>10000</literal>.
+The maximum number of day for a promotion, set it 0 if you don't want
+promotion, set it to 1 or 2 if your disks get overpromoted.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>priority</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default: <emphasis remap='I'>medium</emphasis>.
+When there is no tape to write to, &A; will do incremental backups
+in priority order to the holding disk. The priority may be
+high (2), medium (1), low (0) or a number of your choice.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>program</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>DUMP</emphasis>.
+The type of backup to perform. Valid values are
+<emphasis remap='B'>DUMP</emphasis>
+for the native operating system backup program, and
+<emphasis remap='B'>GNUTAR</emphasis>
+to use &gnutar; or to do PC backups using Samba.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>record</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>yes</emphasis>.
+Whether to ask the backup program to update its database (e.g. <filename>/etc/dumpdates</filename>
+for DUMP or <filename>/usr/local/var/amanda/gnutar-lists</filename> for GNUTAR) of time stamps.
+This is normally enabled for daily backups and turned off for periodic archival runs.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>skip-full</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>no</emphasis>. If <emphasis remap='I'>true</emphasis> and
+<emphasis remap='B'>planner</emphasis> has scheduled a full backup, these disks will be skipped, and
+full backups should be run off-line on these days. It was reported that &A; only schedules 
+level 1 incrementals in this configuration; this is probably a bug.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>skip-incr</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>no</emphasis>. If <emphasis remap='I'>true</emphasis> and
+<emphasis remap='B'>planner</emphasis> has scheduled an incremental backup, these disks will be skipped.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>starttime</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+Backups will not start until after this time of day.
+The value should be hh*100+mm, e.g. 6:30PM (18:30) would be entered as
+<literal>1830</literal>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>strategy</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+  <para>Default: <emphasis remap='I'>standard</emphasis>.
+  Strategy to use when planning what level of backup to run next. Values are:</para>
+
+  <variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>standard</emphasis></term>
+  <listitem>
+  <para>The standard &A; schedule.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>nofull</emphasis></term>
+  <listitem>
+  <para>Never do full backups, only level 1 incrementals.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>noinc</emphasis></term>
+  <listitem>
+  <para>Never do incremental backups, only full dumps.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>skip</emphasis></term>
+  <listitem>
+  <para>Never do backups (useful when sharing the <emphasis remap='I'>disklist</emphasis> file).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>incronly</emphasis></term>
+  <listitem>
+  <para>Only do incremental dumps. <command>amadmin force</command> should be used to tell
+  &A; that a full dump has been performed off-line, so that it resets to level 1.
+  It is similar to skip-full, but with incronly full dumps may be scheduled manually.
+  Unfortunately, it appears that &A; will perform full backups with this configuration,
+  which is probably a bug.</para>
+  </listitem>
+  </varlistentry>
+  </variablelist>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>tape_splitsize</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+Split dump file on tape into pieces of a specified size.
+This allows dumps to be spread across multiple tapes, and can potentially
+make more efficient use of tape space.
+Note that if this value is too large (more than half the size of the
+average dump being split), substantial tape space can be wasted.
+If too small, large dumps will be split into innumerable tiny dumpfiles,
+adding to restoration complexity.
+A good rule of thumb, usually, is 1/10 of the size of your tape.</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>split_diskbuffer</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+When dumping a split dump in PORT-WRITE mode (usually meaning "no holding disk"), buffer the split chunks to a file in the directory specified by this option.
+</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><emphasis remap='B'>fallback_splitsize</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>10M</emphasis>.
+When dumping a split dump in PORT-WRITE mode, if no split_diskbuffer is
+specified (or if we somehow fail to use our split_diskbuffer), we must
+buffer split chunks in memory.
+This specifies the maximum size split chunks can be in this scenario,
+and thus the maximum amount of memory consumed for in-memory splitting.
+The size of this buffer can be changed from its (very conservative) default
+to a value reflecting the amount of memory that each taper process on
+the dump server may reasonably consume.
+</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The following <emphasis remap='B'>dumptype</emphasis> entries are predefined by &A;:</para>
+
+<programlisting remap='.nf'>
+define dumptype no-compress {
+    compress none
+}
+define dumptype compress-fast {
+    compress client fast
+}
+define dumptype compress-best {
+    compress client best
+}
+define dumptype srvcompress {
+    compress server fast
+}
+define dumptype bsd-auth {
+    auth bsd
+}
+define dumptype krb4-auth {
+    auth krb4
+}
+define dumptype no-record {
+    record no
+}
+define dumptype no-hold {
+    holdingdisk no
+}
+define dumptype no-full {
+    skip-full yes
+} 
+</programlisting>
+
+<para>In addition to options in a
+<emphasis remap='B'>dumptype</emphasis>
+section, one or more other
+<emphasis remap='B'>dumptype</emphasis>
+names may be entered, which make this
+<emphasis remap='B'>dumptype</emphasis>
+inherit options from other previously defined
+<emphasis remap='B'>dumptype</emphasis>s.
+For instance, two sections might be the same except for the
+<emphasis remap='B'>record</emphasis> option:</para>
+
+<programlisting remap='.nf'>
+define dumptype normal {
+    comment &quot;Normal backup, no compression, do indexing&quot;
+    no-compress
+    index yes
+    maxdumps 2
+}
+define dumptype testing {
+    comment &quot;Test backup, no compression, do indexing, no recording&quot;
+    normal
+    record no
+}
+</programlisting>
+
+<para>&A; provides a
+<emphasis remap='B'>dumptype</emphasis>
+named
+<emphasis remap='I'>global</emphasis>
+in the sample
+<emphasis remap='B'>amanda.conf</emphasis>
+file that all
+<emphasis remap='B'>dumptype</emphasis>s
+should reference.
+This provides an easy place to make changes that will affect every
+<emphasis remap='B'>dumptype</emphasis>.</para>
+</refsect1>
+
+<refsect1><title>TAPETYPE SECTION</title>
+<para>The <emphasis remap='B'>amanda.conf</emphasis>
+file may define multiple types of tape media and devices.
+The information is entered in a
+<emphasis remap='B'>tapetype</emphasis>
+section, which looks like this in the config file:</para>
+
+<programlisting>
+define tapetype <emphasis remap='I'>name</emphasis> {
+    <emphasis remap='I'>tapetype-option</emphasis> <emphasis remap='I'>tapetype-value</emphasis>
+    <literal>...</literal>
+}
+</programlisting>
+
+<para><emphasis remap='I'>Name</emphasis>
+is the name of this type of tape medium/device.
+It is referenced from the
+<emphasis remap='B'>tapetype</emphasis>
+option in the main part of the config file.</para>
+
+<para>The tapetype options and values are:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>comment</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+A comment string describing this set of tape information.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>filemark</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>1000 bytes</emphasis>.
+How large a file mark (tape mark) is, measured in bytes.
+If the size is only known in some linear measurement (e.g. inches),
+convert it to bytes using the device density.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>length</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>2000 kbytes</emphasis>. How much data will fit on a tape.</para>
+
+<para>Note that this value is only used by &A; to schedule which backups will be run.
+Once the backups start, &A; will continue to write to a tape until it gets an error, 
+regardless of what value is entered for <emphasis remap='B'>length</emphasis>
+(but see the section OUTPUT DRIVERS in the 
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry> 
+manpage for exceptions).
+ </para> </listitem>
+  </varlistentry>
+
+<varlistentry>
+<term><emphasis remap='B'>blocksize</emphasis> <emphasis remap='I'> int</emphasis></term>
+<listitem>
+<para>Default:
+<emphasis remap='I'>32</emphasis>.
+How much data will be written in each tape record expressed in KiloBytes.
+The tape record size (= blocksize) can not be reduced below the default 32 KBytes.
+The parameter blocksize can only be raised if &A; was compiled with the configure option
+--with-maxtapeblocksize=N set with &quot;N&quot; greater than 32 during
+&configure;.
+</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>file-pad</emphasis> <emphasis remap='I'> boolean</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>true</emphasis>.
+If true, every record, including the last one in the file, will have the same length.
+This matches the way &A; wrote tapes prior to the availability of this parameter.
+It may also be useful on devices that only support a fixed blocksize.</para>
+
+<para>Note that the last record on the tape probably includes trailing
+null byte padding, which will be passed back to
+<emphasis remap='B'>gzip</emphasis>,
+<emphasis remap='B'>compress</emphasis>
+or the restore program. Most programs just ignore this (although possibly with a warning).</para>
+
+<para>If this parameter is false, the last record in a file may be shorter
+than the block size. The file will contain the same amount of data the dump program generated,
+without trailing null byte padding. When read, the same amount of data that was written 
+will be returned.</para>
+  </listitem>
+  </varlistentry>
+  
+  <varlistentry>
+  <term><emphasis remap='B'>speed</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>200 bps</emphasis>.
+How fast the drive will accept data, in bytes per second.
+This parameter is NOT currently used by &A;.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>lbl-templ</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>A PostScript template file used by
+<emphasis remap='B'>amreport</emphasis>
+to generate labels. Several sample files are provided with the &A; sources in the
+<emphasis remap='I'>example</emphasis> directory.
+See the
+<citerefentry><refentrytitle>amreport</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more information.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>In addition to options, another
+<emphasis remap='B'>tapetype</emphasis>
+name may be entered, which makes this
+<emphasis remap='B'>tapetype</emphasis>
+inherit options from another
+<emphasis remap='B'>tapetype</emphasis>.
+For instance, the only difference between a DLT4000 tape drive using
+Compact-III tapes and one using Compact-IV tapes is the length of the tape.
+So they could be entered as:</para>
+
+<programlisting remap='.nf'>
+define tapetype DLT4000-III {
+    comment &quot;DLT4000 tape drives with Compact-III tapes&quot;
+    length 12500 mbytes         # 10 Gig tapes with some compression
+    filemark 2000 kbytes
+    speed 1536 kps
+}
+define tapetype DLT4000-IV {
+    DLT4000-III
+    comment &quot;DLT4000 tape drives with Compact-IV tapes&quot;
+    length 25000 mbytes         # 20 Gig tapes with some compression
+}
+</programlisting>
+
+<!-- If anybody has read this, where do all those stupid 
+     pseudo-duplicate FOM-tapetype-entries come from?? 
+       - sgw, Jan. 2005 
+-->
+
+</refsect1>
+
+<refsect1><title>INTERFACE SECTION</title>
+<para>The
+<emphasis remap='B'>amanda.conf</emphasis>
+file may define multiple types of network interfaces.
+The information is entered in an <emphasis remap='B'>interface</emphasis>
+section, which looks like this:</para>
+
+<programlisting>
+define interface <emphasis remap='I'>name</emphasis> {
+    <emphasis remap='I'>interface-option</emphasis> <emphasis remap='I'>interface-value</emphasis>
+    <literal>...</literal>
+}
+</programlisting>
+
+<para><emphasis remap='I'>name</emphasis>
+is the name of this type of network interface. It is referenced from the
+<emphasis remap='I'>disklist</emphasis> file.</para>
+
+<para>Note that these sections define network interface characteristics,
+not the actual interface that will be used. Nor do they impose limits on the bandwidth that will 
+actually be taken up by &A;.
+&A; computes the estimated bandwidth each file system backup will take
+based on the estimated size and time, then compares that plus any other running
+backups with the limit as another of the criteria when deciding whether
+to start the backup. Once a backup starts, &A; will use as much of the network as it can
+leaving throttling up to the operating system and network hardware.</para>
+
+<para>The interface options and values are:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>comment</emphasis> <emphasis remap='I'> string</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>none</emphasis>.
+A comment string describing this set of network information.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>use</emphasis> <emphasis remap='I'> int</emphasis></term>
+  <listitem>
+<para>Default:
+<emphasis remap='I'>300 Kbps</emphasis>.
+The speed of the interface in Kbytes per second.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>In addition to options, another
+<emphasis remap='B'>interface</emphasis>
+name may be entered, which makes this
+<emphasis remap='B'>interface</emphasis>
+inherit options from another
+<emphasis remap='B'>interface</emphasis>.
+At the moment, this is of little use.</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds;: Original text</para>
+<para>&maintainer.sgw;: XML-conversion, major update, splitting</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para>
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcrypt</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>aespipe</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+</para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amcheck.8.xml b/man/xml-source/amcheck.8.xml
new file mode 100644 (file)
index 0000000..f4a17cb
--- /dev/null
@@ -0,0 +1,854 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amcheck.8'>
+
+<refmeta>
+<refentrytitle>amcheck</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amcheck</refname>
+<refpurpose>run &A; self-checks</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amcheck</command>    
+    <arg choice='opt'>-mwsclt </arg>
+    <arg choice='opt'>-Maddress </arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt' rep='repeat'><arg choice='plain'><replaceable>host</replaceable></arg><arg choice='opt' rep='repeat'><replaceable>disk</replaceable></arg></arg>
+    
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amcheck</emphasis>
+runs a number of self-checks on both the &A; tape server host and
+the &A; client hosts.</para>
+
+<para>On the tape server host,
+<command>amcheck</command>
+can go through the same tape checking used at the start of the nightly
+<emphasis remap='B'>amdump</emphasis>
+run to verify the correct tape for the next run is mounted.</para>
+
+<para><emphasis remap='B'>Amcheck</emphasis>
+can also do a self-check on all client hosts
+to make sure each host is running and that permissions
+on filesystems to be backed up are correct.</para>
+
+<para>You can specify many host/disk expressions, only disks that
+match an expression will be checked. All disks are checked if no
+expressions are given.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-s</option></term>
+  <listitem>
+<para>Run the tape server local and tape checks (same as
+<option>-lt</option>).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-c</option></term>
+  <listitem>
+<para>Run the client host checks.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-l</option></term>
+  <listitem>
+<para>Run the local tests (e.g. permissions) on the server host.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-t</option></term>
+  <listitem>
+<para>Run the tape tests on the server host.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-w</option></term>
+  <listitem>
+<para>Enables a DESTRUCTIVE check for write-protection on the
+tape (which would otherwise cause the subsequent
+<emphasis remap='B'>amdump</emphasis>
+to fail).
+If the tape
+is writable, this check causes all data after the tape label to be
+erased. If the label_new_tapes option is enabled, this check may ERASE
+any non-Amanda tape in the drive or changer.
+The check implies
+<option>-t</option>
+and is only made if the tape is otherwise correct.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-m</option></term>
+  <listitem>
+<para>Nothing is printed, but mail is sent if any errors are detected.
+The mail goes to the
+<emphasis remap='B'>mailto</emphasis>
+address specified in the
+<emphasis remap='I'>amanda.conf</emphasis>
+file or the
+<emphasis remap='I'>address</emphasis>
+value if
+<option>-M</option>
+is set.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-a</option></term>
+  <listitem>
+<para>Like
+<option>-m</option>
+but the mail is always sent.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-M</option><replaceable>address</replaceable></term>
+  <listitem>
+<para>Mail the report to
+<emphasis remap='I'>address</emphasis>
+instead of the
+<emphasis remap='B'>mailto</emphasis>
+value from
+<emphasis remap='I'>amanda.conf</emphasis>.
+Implies
+<option>-m</option>.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The default is
+<option>-cs</option>.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLES</title>
+<para>In this example, both the tape server and client tests are run.
+The results are displayed on standard output.</para>
+
+<programlisting>
+% amcheck daily
+&A; Tape Server Host Check
+-----------------------------
+/amanda2/amanda/work: 911475 KB disk space available, that's plenty.
+NOTE: skipping tape-writable test.
+Tape VOL10 label ok.
+Server check took 34.966 seconds.
+
+&A; Backup Client Hosts Check
+--------------------------------
+WARNING: northstar: selfcheck request timed out.  Host down?
+WARNING: drinkme: selfcheck request timed out.  Host down?
+WARNING: scruffy: selfcheck request timed out.  Host down?
+Client check: 136 hosts checked in 51.945 seconds, 3 problems found.
+
+(brought to you by &A; 2.5.0) 
+</programlisting>
+
+<para>In this example, if the line
+<emphasis remap='B'>mailto csd-amanda</emphasis>
+is in
+<emphasis remap='I'>amanda.conf</emphasis>,
+mail will be sent to
+<emphasis remap='B'>csd-amanda</emphasis>
+if the server check returns an error.</para>
+
+<programlisting>
+% amcheck -s -m daily 
+</programlisting>
+</refsect1>
+
+<refsect1><title>MESSAGES</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term>fatal slot <emphasis remap='I'>slot</emphasis>: <emphasis remap='I'>error message</emphasis></term>
+  <listitem>
+<para>(error)
+The tape changer detected some kind of fatal error while trying to load slot
+<emphasis remap='I'>slot</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>slot <emphasis remap='I'>slot</emphasis>: <emphasis remap='I'>error message</emphasis></term>
+  <listitem>
+<para>(warning)
+The tape changer detected some kind of non-fatal error
+(e.g. an empty slot was detected)
+while trying to load slot
+<emphasis remap='I'>slot</emphasis>,
+or an error was detected trying to read the tape label.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>slot <emphasis remap='I'>slot</emphasis>: date <emphasis remap='I'>YYYYMMDD</emphasis> label <emphasis remap='I'>label</emphasis> (<emphasis remap='I'>result</emphasis>)</term>
+  <listitem>
+<para>(info)
+Tape
+<emphasis remap='I'>label</emphasis>
+in slot
+<emphasis remap='I'>slot</emphasis>
+was loaded and found to have been last written on
+<emphasis remap='I'>YYYYMMDD</emphasis>.
+If the tape is new, the date field will be an
+<emphasis remap='I'>X</emphasis>.
+The
+<emphasis remap='I'>result</emphasis>
+may be one of:</para>
+  <!-- .RS -->
+    <variablelist remap='TP'>
+      <varlistentry>
+      <term>exact label match</term>
+      <listitem>
+<para>This is the expected tape.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>no match</term>
+      <listitem>
+<para>This label does not match the
+<emphasis remap='B'>labelstr</emphasis>
+pattern in
+<emphasis remap='I'>amanda.conf</emphasis>.
+Tape scanning will continue.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>active tape</term>
+      <listitem>
+<para>This tape is still active and cannot be overwritten.
+Tape scanning will continue.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>first labelstr match</term>
+      <listitem>
+<para>This tape is the first one that matches the
+<emphasis remap='B'>labelstr</emphasis>
+pattern in
+<emphasis remap='I'>amanda.conf</emphasis>.
+Tape scanning will continue if necessary.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>labelstr match</term>
+      <listitem>
+<para>This tape is the next one that matches the
+<emphasis remap='B'>labelstr</emphasis>
+pattern in
+<emphasis remap='I'>amanda.conf</emphasis>.
+Tape scanning will continue.</para>
+      </listitem>
+      </varlistentry>
+    </variablelist>
+  <!-- .RE -->
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: cannot look up dump user <emphasis remap='I'>user</emphasis></term>
+  <listitem>
+<para>(error)
+Dump user
+<emphasis remap='I'>user</emphasis>
+from
+<emphasis remap='I'>amanda.conf</emphasis>
+could not be found in the system password information.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: cannot look up my own uid (<emphasis remap='I'>uid</emphasis>)</term>
+  <listitem>
+<para>(error)
+User id
+<emphasis remap='I'>uid</emphasis>
+running
+<command>amcheck</command>
+could not be found in the system password information.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: running as user <emphasis remap='I'>runuser</emphasis> instead of <emphasis remap='I'>dumpuser</emphasis></term>
+  <listitem>
+<para>(error)
+<emphasis remap='B'>Amcheck</emphasis>
+should be run as the dump user
+<emphasis remap='I'>dumpuser</emphasis>
+from
+<emphasis remap='I'>amanda.conf</emphasis>
+instead of
+<emphasis remap='I'>runuser</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: program dir <emphasis remap='I'>directory</emphasis>: not accessible</term>
+  <listitem>
+<para>(error)
+The directory &A; expects to find its auxiliary programs in,
+<emphasis remap='I'>directory</emphasis>,
+is not accessible.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: program <emphasis remap='I'>program</emphasis>: does not exist</term>
+  <listitem>
+<para>(error)
+Program
+<emphasis remap='I'>program</emphasis>
+needed on the tape server could not be found.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: program <emphasis remap='I'>program</emphasis>: not a file</term>
+  <listitem>
+<para>(error)
+Program
+<emphasis remap='I'>program</emphasis>
+needed on the tape server exists but is not a file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: program <emphasis remap='I'>program</emphasis>: not executable</term>
+  <listitem>
+<para>(error)
+Program
+<emphasis remap='I'>program</emphasis>
+needed on the tape server exists but is not executable.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: program <emphasis remap='I'>program</emphasis>: not setuid-root</term>
+  <listitem>
+<para>(warning)
+Program
+<emphasis remap='I'>program</emphasis>
+needed on the tape server exists but should be owned by user &quot;root&quot;
+and setuid.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>XXX</emphasis> dir <emphasis remap='I'>directory</emphasis>: not writable</term>
+  <listitem>
+<para>(error)
+Directory
+<emphasis remap='I'>directory</emphasis>
+is either not writable,
+i.e. the dump user will not be able to create or remove files,
+or cannot be accessed, perhaps because a parent directory
+does not allow search permission.
+The
+<emphasis remap='I'>XXX</emphasis>
+may be:</para>
+  <!-- .RS -->
+    <variablelist remap='TP'>
+      <varlistentry>
+      <term>log</term>
+      <listitem>
+<para>for the &A; log directory (see
+<emphasis remap='B'>logdir</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>oldlog</term>
+      <listitem>
+<para>for the directory that holds the old log files (see
+<emphasis remap='B'>logdir</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>info</term>
+      <listitem>
+<para>for an &A; database information directory (see
+<emphasis remap='B'>curinfo</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)
+or</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>index</term>
+      <listitem>
+<para>for an &A; index directory (see
+<emphasis remap='B'>indexdir</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>tapelist</term>
+      <listitem>
+<para>for the &A; tapelist directory (see
+<emphasis remap='B'>tapelist</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)</para>
+      </listitem>
+      </varlistentry>
+    </variablelist>
+  <!-- .RE -->
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>NOTE: <emphasis remap='I'>XXX</emphasis> dir <emphasis remap='I'>directory</emphasis>: does not exist</term>
+  <listitem>
+<para>(info)
+A database (info) or index directory does not exist or cannot be accessed.
+This might just mean this is a new client or disk,
+but if that is not the case, this should be treated as an error.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>NOTE: it will be created on the next run</term>
+  <listitem>
+<para>(info)
+This indicates the info directory listed in the previous message
+will be created on the next run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>XXX</emphasis> dir <emphasis remap='I'>name</emphasis>: not a directory</term>
+  <listitem>
+<para>(error)
+<emphasis remap='B'>Amcheck</emphasis>
+expected
+<emphasis remap='I'>name</emphasis>
+to be a directory,
+but it is something else (e.g. file).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: info file <filename>file</filename>: does not exist</term>
+  <listitem>
+<para>(warning)
+File
+<emphasis remap='I'>file</emphasis>
+does not exist in the text format database.
+Since the parent directories do exist,
+the file should already have been created.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: info file <filename>name</filename>: not a file</term>
+  <listitem>
+<para>(error)
+<emphasis remap='B'>Amcheck</emphasis>
+expected
+<emphasis remap='I'>name</emphasis>
+to be a file,
+but it is something else (e.g. file).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: info file <filename>file</filename>: not readable</term>
+  <listitem>
+<para>(error)
+The text format database file
+<emphasis remap='I'>file</emphasis>
+is not readable.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: log file <filename>file</filename>: not writable</term>
+  <listitem>
+<para>(error)
+Log file
+<emphasis remap='I'>file</emphasis>
+(file
+<emphasis remap='B'>log</emphasis>
+in
+<emphasis remap='B'>logdir</emphasis>
+from
+<emphasis remap='B'>amanda.conf</emphasis>)
+is either not writable,
+or cannot be accessed, perhaps because a parent directory
+does not allow search permission.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: tape list <emphasis remap='I'>tapelist</emphasis>: not writable</term>
+  <listitem>
+<para>(error)
+&A; tape list file
+<emphasis remap='I'>tapelist</emphasis>
+(see
+<emphasis remap='B'>tapelist</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)
+is not writable or was not found.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: tape list <emphasis remap='I'>tapelist</emphasis>: parse error</term>
+  <listitem>
+<para>(error)
+&A; tape list file
+<emphasis remap='I'>tapelist</emphasis>
+(see
+<emphasis remap='B'>tapelist</emphasis>
+in
+<emphasis remap='B'>amanda.conf</emphasis>)
+could not be read or parsed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: tapedev is /dev/null, dumps will be thrown away</term>
+  <listitem>
+<para>(warning)
+The
+<emphasis remap='B'>tapedev</emphasis>
+parameter in
+<emphasis remap='B'>amanda.conf</emphasis>
+is set to
+<filename>/dev/null</filename>
+and &A; uses that when debugging to throw all the dump images away.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: hold file <filename>file</filename> exists</term>
+  <listitem>
+<para>(info)
+Hold file
+<emphasis remap='I'>file</emphasis>
+exists and will cause
+<emphasis remap='B'>amdump</emphasis>
+to pause at the beginning until it is removed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: holding disk <emphasis remap='I'>disk</emphasis>: statfs: <emphasis remap='I'>error message</emphasis></term>
+  <listitem>
+<para>(error)
+An error was returned from the
+<emphasis remap='I'>statfs</emphasis>
+system call on holding disk
+<emphasis remap='I'>disk</emphasis>
+(maybe because it does not exist).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: holding disk <emphasis remap='I'>disk</emphasis>: not writable</term>
+  <listitem>
+<para>(error)
+Holding disk
+<emphasis remap='I'>disk</emphasis>,
+is not writable,
+probably because the caller does not have write permission
+or a parent directory does not allow search permission.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: holding disk <emphasis remap='I'>disk</emphasis>: available space unknown <emphasis remap='I'>N</emphasis> KB requested.</term>
+  <listitem>
+<para>(warning)
+<emphasis remap='B'>Amcheck</emphasis>
+could not determine the amount of available space on holding disk
+<emphasis remap='I'>disk</emphasis>
+to see if there were at least
+<emphasis remap='I'>N</emphasis>
+KBytes available.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: holding disk <emphasis remap='I'>disk</emphasis>: only <emphasis remap='I'>F</emphasis> KB free (<emphasis remap='I'>R</emphasis> KB requested).</term>
+  <listitem>
+<para>(warning)
+<emphasis remap='I'>amanda.conf</emphasis>
+requested
+<emphasis remap='I'>R</emphasis>
+KBytes of free space on holding disk
+<emphasis remap='I'>disk</emphasis>,
+but only
+<emphasis remap='I'>F</emphasis>
+KBytes were available.
+10 MBytes is subtracted for each backup process
+(see the
+<emphasis remap='B'>inparallel</emphasis>
+<emphasis remap='I'>amanda.conf</emphasis>
+option)
+to allow for unexpected overruns.</para>
+<note>Even though this message is listed as a warning, it causes &amcheck; to exit with a non-zero status.</note>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term>Holding disk <emphasis remap='I'>disk</emphasis>: <emphasis remap='I'>N</emphasis> KB disk space available, that's plenty.</term>
+  <listitem>
+<para>(info)
+There was sufficient free space on holding disk
+<emphasis remap='I'>disk</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: holding disk <emphasis remap='I'>disk</emphasis>: only <emphasis remap='I'>F</emphasis> KB free, using nothing</term>
+  <listitem>
+<para>(warning)
+Holding disk
+<emphasis remap='I'>disk</emphasis>
+has
+<emphasis remap='I'>F</emphasis>
+KBytes of free space, but that is not enough for what is requested in
+<emphasis remap='I'>amanda.conf</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>Holding disk <emphasis remap='I'>disk</emphasis>: <emphasis remap='I'>F</emphasis> KB disk space available, using <emphasis remap='I'>U</emphasis> KB</term>
+  <listitem>
+<para>(info)
+Holding disk
+<emphasis remap='I'>disk</emphasis>
+has
+<emphasis remap='I'>F</emphasis>
+KBytes of free space and &A; will be using up to
+<emphasis remap='I'>U</emphasis>
+Kbytes.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: if a tape changer is not available, runtapes must be set to 1.</term>
+  <listitem>
+<para>(warning)
+The
+<emphasis remap='B'>runtapes</emphasis>
+<emphasis remap='I'>amanda.conf</emphasis>
+option must be set to 1 if the
+<emphasis remap='B'>tpchanger</emphasis>
+<emphasis remap='I'>amanda.conf</emphasis>
+option is not set.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>error message</emphasis>.</term>
+  <listitem>
+<para>(error)
+An error was detected while initializing the tape changer.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>tape device</emphasis>: <emphasis remap='I'>error message</emphasis>.</term>
+  <listitem>
+<para>(error)
+An error was detected while processing the tape label.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: cannot overwrite active tape <emphasis remap='I'>label</emphasis>.</term>
+  <listitem>
+<para>(error)
+Tape
+<emphasis remap='I'>label</emphasis>
+is still active and cannot be used.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: label <emphasis remap='I'>label</emphasis> doesn't match labelstr <emphasis remap='I'>pattern</emphasis> .</term>
+  <listitem>
+<para>(error)
+The label on tape
+<emphasis remap='I'>label</emphasis>
+does not match the
+<emphasis remap='B'>labelstr</emphasis>
+<emphasis remap='I'>amanda.conf</emphasis>
+option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>(expecting a new tape)</term>
+  <listitem>
+<para>(info)
+The tape is not OK and a new tape was expected.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>(expecting tape <emphasis remap='I'>label</emphasis> or a new tape)</term>
+  <listitem>
+<para>(info)
+The tape is not OK and either tape
+<emphasis remap='I'>label</emphasis>
+or a new tape was expected.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: tape <emphasis remap='I'>label</emphasis> label ok, but is not writable.</term>
+  <listitem>
+<para>(error)
+Tape
+<emphasis remap='I'>label</emphasis>
+is OK, but the write enable test failed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>Tape <emphasis remap='I'>label</emphasis> is writable.</term>
+  <listitem>
+<para>(info)
+Tape
+<emphasis remap='I'>label</emphasis>
+is OK and the write enable test succeeded.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>NOTE: skipping tape-writable test.</term>
+  <listitem>
+<para>(info)
+The tape write test (see the
+<option>-w</option>
+option) was not enabled.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: skipping tape test because amdump or amflush seem to be running</term>
+  <term>WARNING: if they are not, you must run amcleanup</term>
+  <listitem>
+<para>(warning)
+It looked to
+<command>amcheck</command>
+like either
+<emphasis remap='B'>amdump</emphasis>
+or
+<emphasis remap='B'>amflush</emphasis>
+were running because a log file or amdump file exists.
+If they are not running, you probably need to run
+<emphasis remap='B'>amcleanup</emphasis>
+to clear up a previous failure.
+Otherwise, you need to wait until they complete before running
+<command>amcheck</command><literal>.</literal></para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>NOTE: skipping tape checks</term>
+  <listitem>
+<para>(info)
+The tape tests are being skipped because you used the
+<option>-t</option>
+command line option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: <emphasis remap='I'>compress</emphasis> is not executable, server-compression and indexing will not work</term>
+  <listitem>
+<para>(warning)
+Compression program
+<emphasis remap='I'>compress</emphasis>
+is not executable,
+so compression on the tape server host and creating index files will not work.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>Tape <emphasis remap='I'>label</emphasis> label ok.</term>
+  <listitem>
+<para>(info)
+Tape
+<emphasis remap='I'>label</emphasis>
+is OK for the next
+run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>Server check took <emphasis remap='I'>S</emphasis> seconds.</term>
+  <listitem>
+<para>(info)
+Reports how long the tape server host checks took.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>host</emphasis>: could not resolve hostname</term>
+  <listitem>
+<para>(error)
+Could not look up client hostname
+<emphasis remap='I'>host</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>Client check: <emphasis remap='I'>H</emphasis> hosts checked in <emphasis remap='I'>S</emphasis> seconds, <emphasis remap='I'>N</emphasis> problems found.</term>
+  <listitem>
+<para>(info)
+Reports the number of client hosts checked,
+how long it took and the number of errors detected.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>WARNING: <emphasis remap='I'>host</emphasis>: selfcheck request timed out. Host down?</term>
+  <listitem>
+<para>(warning)
+There was no response from
+<emphasis remap='I'>host</emphasis>
+when trying to do the client checks.
+The host might really be down or it might not be configured properly.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>host</emphasis> NAK: <emphasis remap='I'>message</emphasis></term>
+  <listitem>
+<para>(error)
+<emphasis remap='I'>Host</emphasis>
+reported a negative acknowledgment error of
+<emphasis remap='I'>message</emphasis>
+to the status check request.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>host</emphasis> NAK: [NAK parse failed]</term>
+  <listitem>
+<para>(error)
+<emphasis remap='B'>Amcheck</emphasis>
+could not parse the negative acknowledgment error from
+<emphasis remap='I'>host</emphasis>.
+There might be an &A; version mismatch between the host running
+<command>amcheck</command>
+and
+<emphasis remap='I'>host</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>host</emphasis> [mutual-authentication failed]</term>
+  <listitem>
+<para>(error)
+Kerberos authentication failed while contacting
+<emphasis remap='I'>host</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>ERROR: <emphasis remap='I'>host</emphasis>: <emphasis remap='I'>message</emphasis></term>
+  <listitem>
+<para>(error)
+Error
+<emphasis remap='I'>message</emphasis>
+was reported by the status check on
+<emphasis remap='I'>host</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds; : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amcheckdb.8.xml b/man/xml-source/amcheckdb.8.xml
new file mode 100644 (file)
index 0000000..a59a182
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amcheckdb.8'>
+
+<refmeta>
+<refentrytitle>amcheckdb</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amcheckdb</refname>
+<refpurpose>check &A; database for tape consistency</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amcheckdb</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amcheckdb</emphasis>
+verifies that every tape mentioned in the &A; database
+is still valid in the
+<emphasis remap='I'>tapelist</emphasis>
+file.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>This shows a normal response:</para>
+
+<programlisting>
+# amcheckdb daily
+Ready.
+</programlisting>
+
+<para>This shows tape
+<emphasis remap='I'>DMP014</emphasis>
+is still listed in the database but is no longer listed in the
+<emphasis remap='I'>tapelist</emphasis>
+file:</para>
+
+<programlisting>
+# amcheckdb daily
+Tape DMP014 missing in /usr/local/etc/amanda//daily/tapelist
+Ready.
+</programlisting>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Adrian T. Filipi-Martin &lt;atf3r@cs.virginia.edu&gt;: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrmtape</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amcleanup.8.xml b/man/xml-source/amcleanup.8.xml
new file mode 100644 (file)
index 0000000..11a36bc
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amcleanup.8'>
+
+<refmeta>
+<refentrytitle>amcleanup</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amcleanup</refname>
+<refpurpose>run the &A; cleanup process after a failure</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amcleanup</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amcleanup</emphasis>
+generates the
+<emphasis remap='I'>&A; Mail Report</emphasis>
+and updates the &A; databases after a system failure on a tape server host.
+This cleanup process is normally done automatically as part of the
+<emphasis remap='B'>amdump</emphasis>
+program, but if
+<emphasis remap='B'>amdump</emphasis>
+cannot complete for some reason (usually because of a tape server host crash),
+<command>amcleanup</command>
+must be run some time later (usually during system boot).</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLES</title>
+<para>This example runs the &A; cleanup process by hand after
+a failure.</para>
+
+<programlisting>
+% amcleanup daily
+</programlisting>
+
+<para>Putting the following line in a system boot script (e.g.
+<filename>/etc/rc.local</filename>)
+runs the &A; cleanup process as part of the reboot,
+eliminating the need to run it by hand.</para>
+
+<programlisting>
+/usr/local/sbin/amcleanup daily
+</programlisting>
+
+<para>If nothing needs to be done,
+<command>amcleanup</command>
+exits normally with the message:</para>
+
+<programlisting>
+amcleanup: no unprocessed logfile to clean up.
+</programlisting>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds;: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amcrypt.8.xml b/man/xml-source/amcrypt.8.xml
new file mode 100755 (executable)
index 0000000..8a12db1
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<refentry id='amcrypt.8'>
+<refmeta>
+<refentrytitle>amcrypt</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amcrypt</refname>
+<refpurpose>reference crypt program for &A; symmetric data encryption</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amcrypt</command>    
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para>&amcrypt; 
+requires <emphasis remap='B'>aespipe</emphasis> and <emphasis
+remap='B'>gpg</emphasis>  to work. Aespipe is available from <ulink
+url="http://loop-aes.sourceforge.net"/></para>
+<para>&amcrypt; will search for the aespipe program in the following directories:
+/usr/bin:/usr/local/bin:/sbin:/usr/sbin.</para>
+&amcrypt; calls &amaespipe; and pass the
+<emphasis remap='B'>passphrase</emphasis> through file descriptor 3.
+The passphrase should be stored in ~amanda/.am_passphrase.
+</refsect1>
+
+<refsect1><title>How to create encryption keys for amcrypt</title>
+1. Create 65 random encryption keys and encrypt those keys using gpg. Reading
+from /dev/random may take indefinitely long if kernel's random entropy pool
+is empty. If that happens, do some other work on some other console (use
+keyboard, mouse and disks). 
+<para> head -c 2925 /dev/random | uuencode -m - | head -n 66 | tail -n 65 \
+        | gpg --symmetric -a > ~amanda/.gnupg/am_key.gpg
+</para>
+<para>This will ask for a passphrase. Remember this passphrase as you will need
+it in the next step.</para>
+<para>2. Store the passphrase inside the home-directory of the AMANDA-user and
+protect it with proper permissions:</para>
+
+<programlisting>
+echo my_secret_passphrase > ~amanda/.am_passphrase
+chown amanda:disk ~amanda/.am_passphrase
+chmod 700 ~amanda/.am_passphrase
+</programlisting>
+
+</refsect1>
+
+<refsect1><title>Key and Passphrase</title>
+<para>&amcrypt; uses the same key to encrypt and decrypt data.</para>
+It is very important to store and protect the key and the passphrase
+properly. Encrypted backup data can <emphasis remap='B'>only</emphasis> be recovered with the correct key and
+passphrase.
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>aespipe</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amaespipe</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>gpg</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+</para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amdd.8.xml b/man/xml-source/amdd.8.xml
new file mode 100644 (file)
index 0000000..a75c451
--- /dev/null
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man+tkman by doclifter -->
+<refentry id='amdd.8'>
+
+<!-- CO listing suppressed (not used) -->
+<refmeta>
+<refentrytitle>amdd</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amdd</refname>
+<refpurpose>&A; version of dd</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amdd</command>    
+    <arg choice='opt'>-d </arg>
+    <arg choice='opt'><replaceable>if=input</replaceable></arg>
+    <arg choice='opt'><replaceable>of=output</replaceable></arg>
+    <arg choice='opt'><replaceable>bs=blocksize</replaceable></arg>
+    <arg choice='opt'><replaceable>skip=count</replaceable></arg>
+    <arg choice='opt'><replaceable>count=count</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amdd</emphasis>
+provides just enough of the standard UNIX
+<emphasis remap='B'>dd</emphasis>
+command for the needs of &A;.
+This is handy when doing a full restore and the standard
+<emphasis remap='B'>dd</emphasis>
+program has not yet been found.</para>
+
+<para><emphasis remap='B'>Amdd</emphasis>
+also provides access to the &A; output drivers that support various tape simulations.
+This may be used for debugging or to convert from one format to another.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.
+See the
+<emphasis remap='B'>OUTPUT DRIVERS</emphasis>
+section of
+<emphasis remap='I'>amanda(8)</emphasis>
+for more information on the &A; output drivers.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-d</option></term>
+  <listitem>
+<para>Turn on debugging output.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-l</option><replaceable>length</replaceable></term>
+  <listitem>
+<para>Set the output length.
+If the output driver limits the output size, this controls
+when end of tape will be simulated.</para>
+<para><emphasis remap='I'>Length</emphasis>
+may have a multiplier suffix:</para>
+
+<literallayout>
+k -> 1024 (Kilobytes)
+b -> 512 (Blocks)
+M -> 1024*1024 (Megabytes)
+</literallayout>
+
+<para>The default is no multiplier (bytes).</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>if=</emphasis><emphasis remap='I'>input</emphasis></term>
+  <listitem>
+<para>Input to
+<emphasis remap='B'>dd</emphasis>.
+Default is stdin.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>of=</emphasis><emphasis remap='I'>output</emphasis></term>
+  <listitem>
+<para>Where to send the output of
+<emphasis remap='B'>dd</emphasis>.
+Default is stdout.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>bs=</emphasis><emphasis remap='I'>blocksize</emphasis></term>
+  <listitem>
+<para>Size of each record.
+Input records smaller than this will
+<emphasis remap='I'>not</emphasis>
+be padded.
+Output records will be the same size as the corresponding input record.
+Default is 512 bytes.</para>
+<para><emphasis remap='I'>Blocksize</emphasis>
+may have a multiplier suffix:</para>
+<literallayout>
+k -> 1024 (Kilobytes)
+b -> 512 (Blocks)
+M -> 1024*1024 (Megabytes)
+</literallayout>
+<para>The default is no multiplier (bytes).</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>count=</emphasis><emphasis remap='I'>count</emphasis></term>
+  <listitem>
+<para>Number of records to copy.
+Default is all records until end of file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>skip=</emphasis><emphasis remap='I'>count</emphasis></term>
+  <listitem>
+<para>Number of records to skip before copying input to output.
+Default is zero.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Marc Mengel <email>mengel@fnal.gov</email>, John R. Jackson
+<email>jrj@purdue.edu</email> : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amdump.8.xml b/man/xml-source/amdump.8.xml
new file mode 100644 (file)
index 0000000..72840c5
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amdump.8'>
+
+<refmeta>
+<refentrytitle>amdump</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amdump</refname>
+<refpurpose>back up all disks in an &A; configuration</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amdump</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt' rep='repeat'><arg choice='plain'><replaceable>host</replaceable></arg><arg choice='opt' rep='repeat'><replaceable>disk</replaceable></arg></arg>
+    
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amdump</emphasis>
+switches to the appropriate &A; configuration directory,
+e.g. /usr/local/etc/amanda/<emphasis remap='I'>config</emphasis>,
+then attempts to back up every disk specified by the
+<emphasis remap='I'>amanda.conf</emphasis>
+file.
+<emphasis remap='B'>Amdump</emphasis>
+is normally run by
+<emphasis remap='B'>cron</emphasis>.</para>
+
+<para>You can specify many host/disk expressions, only disks that
+match an expression will be dumped. All disks are dumped if no
+expressions are given.</para>
+
+<para>If the file /usr/local/etc/amanda/<emphasis remap='I'>config</emphasis>/hold exists,
+<command>amdump</command>
+will wait until it is removed before starting the backups.
+This allows scheduled backups to be delayed when circumstances warrant, for example, 
+if the tape device is being used for some other purpose.
+While waiting,
+<command>amdump</command>
+checks for the hold file every minute.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>Here is a typical crontab entry. It runs
+<command>amdump</command>
+every weeknight at 1 a.m. as user
+<emphasis remap='B'>bin</emphasis>:</para>
+
+<programlisting>
+0 1 * * 1-5 bin /usr/local/sbin/amdump daily
+</programlisting>
+
+<para>Please see the 
+<citerefentry><refentrytitle>crontab</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+or
+<citerefentry><refentrytitle>crontab</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+manual page for the correct crontab format for your system.</para>
+</refsect1>
+
+<refsect1><title>MESSAGES</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term>amdump: waiting for hold file to be removed</term>
+  <listitem>
+<para>The &quot;hold&quot; file exists and &amdump; is waiting for it to be removed
+before starting backups.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>amdump: amdump or amflush is already running, or you must run amcleanup</term>
+  <listitem>
+<para>Amdump detected another &amdump; or &amflush; running,
+or the remains of a previous incomplete &amdump; or &amflush; run.
+This run is terminated.
+If the problem is caused by the remains of a previous run,
+you must execute
+<citerefentry><refentrytitle>amcleanup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+and then rerun
+<command>amdump</command>.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds; : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcheck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcleanup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amflush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>cron</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amfetchdump.8.xml b/man/xml-source/amfetchdump.8.xml
new file mode 100644 (file)
index 0000000..a1fcdbe
--- /dev/null
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<refentry id='amfetchdump.8'>
+
+<refmeta>
+<refentrytitle>amfetchdump</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amfetchdump</refname>
+<refpurpose>extract backup images from multiple &A; tapes.</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amfetchdump</command>
+    <arg choice='opt'>-pcClawns</arg>
+    <arg choice='opt'>-d <replaceable>device</replaceable></arg>
+    <arg choice='opt'>-o <replaceable>directory</replaceable></arg>
+    <arg choice='opt'>-i <replaceable>logfile</replaceable></arg>
+    <arg choice='opt'>-b <replaceable>blocksize</replaceable></arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>hostname</replaceable></arg>
+    <arg choice='opt'>
+      <arg choice='plain'><replaceable>disk</replaceable></arg>
+      <arg choice='opt'>
+        <arg choice='plain'><replaceable>date</replaceable></arg>
+        <arg choice='opt'>
+          <arg choice='plain'><replaceable>level</replaceable></arg>
+          <arg choice='opt'>
+            <arg choice='plain'><replaceable>hostname</replaceable></arg>
+            <arg choice='opt'>...</arg>
+          </arg>
+        </arg>
+      </arg>
+    </arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amfetchdump</emphasis>
+pulls one or more matching dumps from tape or from the holding disk,
+handling the reassembly of multi-tape split dump files as well as any
+tape autochanger operations.</para>
+
+<para>It will automatically use the logs created by
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+to locate available dumps on tape, in the same way that the <emphasis
+remap='B'>find</emphasis> feature of
+<citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+lists available dumps. If these logs are unavailable, it can search
+tape-by-tape to find what it needs, and can generate new logs to serve
+as an emergency tape inventory.</para>
+
+<para>The 
+<emphasis remap='I'>hostname</emphasis>,
+<emphasis remap='I'>diskname</emphasis>,
+<emphasis remap='I'>datestamp</emphasis>,
+and
+<emphasis remap='I'>level</emphasis> dump pattern-matching works as in
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+with the added requirement that at minimum a <emphasis
+remap='I'>hostname</emphasis> must be specified when not in inventory mode.</para>
+
+<para>Unless
+<option>-p</option>
+is used, backup images are extracted to files in the current directory named:</para>
+
+<!-- .RS -->
+<para><emphasis remap='I'>hostname.diskname.datestamp.dumplevel</emphasis></para>
+<!-- .RE -->
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+    <term><option>-p</option></term>
+<listitem><para>Pipe exactly one complete dump file to <emphasis
+remap='I'>stdout</emphasis>, instead of writing the file to disk. This
+will restore only the first matching dumpfile (where
+&quot;first&quot; is determined by the dump log search
+facility).</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-d</option> <replaceable>device</replaceable></term>
+<listitem><para> Restore from this tape device instead of the default.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-o</option>
+    <replaceable>directory</replaceable></term>
+<listitem><para>Output restored files to this directory, instead of to the
+    current working directory.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-c</option></term>
+    <listitem><para>Compress output, fastest method
+    available.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-C</option></term>
+    <listitem><para>Compress output, smallest file size method
+    available.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-l</option></term>
+<listitem><para>Leave dumps in the compressed/uncompressed state in which they
+were found on tape. By default, <emphasis
+remap='B'>amfetchdump</emphasis> will automatically uncompress when
+restoring.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-a</option></term>
+<listitem><para>Assume that all tapes are already available, via tape changer or
+otherwise, instead of prompting the operator to ensure that all tapes
+are loaded.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-i</option> <replaceable>filename</replaceable></term>
+<listitem><para>Generate an inventory of all dumps &quot;seen&quot; on the
+tapes we search, for later use as a log.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-w</option></term>
+<listitem><para>Wait to put split dumps together until all chunks have been
+restored. Normally, <emphasis remap='B'>amfetchdump</emphasis> will
+attempt to read pieces of a split file from tape in order, so that it
+can assemble them simply by appending each file to the first. This
+option disables the appending behavior, and instead restores each
+piece as an individual file and reassembles them only after all have
+been restored.</para>
+
+<note>This requires at least double the size of your dump in free
+disk space, in order to build the final assembled dumpfile.</note>
+
+<para>This behavior is implicitly invoked in circumstances where knowing the
+location of all dumps on tape in advance is not possible, such as when
+you are restoring without log files.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-n</option></term>
+<listitem><para>Do not reassemble split dump files at all, just restore each
+piece as an individual file.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-s</option></term>
+<listitem><para>Do not fast-forward straight to needed files on tape. This will
+slow down most restores substantially. Only use this option if your
+tape drive does not properly support the fast-forward
+operation.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><option>-b</option>
+    <replaceable>blocksize</replaceable></term>
+<listitem><para>Force a particular block size when reading from tapes. This
+    value will usually be autodetected, and should not normally need
+    to be set.</para></listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>EXAMPLES</title>
+<para>All the examples here assume your configuration is called
+<replaceable>SetA</replaceable>.</para>
+
+<para>Here's a simple case, restoring all known dumps of the host
+vanya to the current working directory.</para>
+<!-- .RS -->
+<literallayout remap='.nf'>
+$ amfetchdump SetA vanya
+</literallayout> <!-- .fi -->
+
+<para>A more likely scenario involves restoring a particular dump from
+a particular date. We'll pipe this one to &gnutar; as well, to
+automatically extract the dump.</para>
+<!-- .RS -->
+<literallayout remap='.nf'>
+$ amfetchdump -p SetA vanya /home 20051020 | gtar -xvpf -
+</literallayout> <!-- .fi -->
+
+<para>In a situation where all of our dump logs have been wiped out,
+we could also use amfetchdump to inventory our tapes and recreate an
+imitation of those logs, which we'll send to <emphasis
+remap="I">stdout</emphasis> for casual perusal.
+<!-- .RS -->
+<literallayout remap='.nf'>
+$ amfetchdump -i - SetA
+</literallayout> <!-- .fi -->
+</para>
+
+<para>Note that you can specify a restore while in inventory mode, and
+<command>amfetchdump</command> will continue searching for more dumps
+from this host even after successfully restoring a dump, inventorying
+all the while. If your backup searcher has been trashed, this is a
+handy way to recover what you have.
+<!-- .RS -->
+<literallayout remap='.nf'>
+$ amfetchdump -i /var/amanda/log SetA backupserver
+</literallayout> <!-- .fi -->
+</para>
+</refsect1>
+
+<refsect1><title>CAVEATS</title>
+<command>Amfetchdump</command> is dependent on accessing your server's config,
+tape changer, and (normally) dump logs. As such, it's not necessarily
+the most useful tool when those have all been wiped out and you
+desperately need to pull things from your tape. Pains have been taken
+to make it as capable as possible, but for seriously minimialist
+restores, look to
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+or
+<citerefentry><refentrytitle>dd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+instead.
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>John Stange, &email.jstange;, National Academies Press</para>
+<para>Ian Turner, &email.itt;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>tar</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+<citerefentry><refentrytitle>restore</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amflush.8.xml b/man/xml-source/amflush.8.xml
new file mode 100644 (file)
index 0000000..457cc42
--- /dev/null
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amflush.8'>
+
+<refmeta>
+<refentrytitle>amflush</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amflush</refname>
+<refpurpose>flush &A; backup files from holding disk to tape</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amflush</command>    
+    <arg choice='opt'>-b </arg>
+    <arg choice='opt'>-f </arg>
+    <arg choice='opt'>-s </arg>
+    <arg choice='opt' rep='repeat'><arg choice='plain'>-D </arg><arg choice='plain'><replaceable>datestamp</replaceable></arg></arg>
+    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt' rep='repeat'><arg choice='plain'><replaceable>host</replaceable></arg><arg choice='opt' rep='repeat'><replaceable>disk</replaceable></arg></arg>
+    
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amflush</emphasis>
+writes &A; backups from the holding disks to tape,
+and updates the &A; info database and tapelist accordingly.
+Backups may stay in a holding disk when something is wrong with the tape
+at the time
+<emphasis remap='B'>amdump</emphasis>
+is run.
+When this happens, the problem must be corrected and
+<command>amflush</command>
+run by hand.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-b</option></term>
+  <listitem>
+<para>Run
+<command>amflush</command>
+in batch mode. All datestamps are selected unless specified.
+The flush is started without confirmation.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-f</option></term>
+  <listitem>
+<para>Run
+<command>amflush</command>
+in foreground.
+<emphasis remap='B'>Amflush</emphasis>
+normally detaches itself from the tty and runs as a background process.
+With the
+<option>-f</option>
+option,
+<command>amflush</command>
+stays in the foreground.
+This is useful if
+<command>amflush</command>
+is run as part of another script that, for example, advances the tape
+after the flush is completed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-s</option></term>
+  <listitem>
+<para>Write log to stdout/stderr instead of the amflush log file. Requires the
+<option>-f</option>
+option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-D datestamp</option></term>
+  <listitem>
+<para>specify a  datestamp expression you want to flush, see the 
+&quot;DATESTAMP EXPRESSION&quot; section of
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+for a description.
+<option>-D 20001225-7</option>
+will flush all
+dumps from 25 december 2000 to 27 december 2000.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>You can specify many host/disk expressions, only disks that
+match an expression will be flushed. All disks are flushed if no
+expressions are given. see the &quot;HOST &amp; DISK EXPRESSION&quot; section of
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+for a description.</para>
+
+<para><emphasis remap='B'>Amflush</emphasis>
+will look in the holding disks specified by the
+<emphasis remap='I'>amanda.conf</emphasis>
+file in /usr/local/etc/amanda/<emphasis remap='I'>config</emphasis>
+for any non-empty &A; work directories.
+It then prompts you to select a directory
+or to process all of the directories.
+The work directories in the holding disks are named by the date at the time
+<emphasis remap='B'>amdump</emphasis>
+was run, e.g.
+<literal>19910215</literal>.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para><emphasis remap='B'>Amflush</emphasis>
+will search for holding areas associated with the
+<emphasis remap='I'>daily</emphasis>
+configuration.
+After you select which holding area to flush,
+<command>amflush</command>
+writes the data to tape, updates the databases and sends
+a mail report similar to
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+
+<programlisting>
+% amflush daily
+Scanning /amanda-hold...
+  20001113: found &A; directory.
+  20001114: found &A; directory.
+
+Multiple &A; directories, please pick one by letter:
+  A. 20001113
+  B. 20001114
+Select directories to flush [A..B]: [ALL] all
+
+Flushing dumps in 20001113, 20001114,
+today: 20001117
+to tape drive /dev/rmt/0mn.
+Expecting tape DMP014 or a new tape.  (The last dumps were to tape DMP013)
+Are you sure you want to do this? yes
+Running in background, you can log off now.
+You'll get mail when amflush is finished.
+</programlisting>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds; : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amgetconf.8.xml b/man/xml-source/amgetconf.8.xml
new file mode 100644 (file)
index 0000000..d824dde
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amgetconf.8'>
+
+<refmeta>
+<refentrytitle>amgetconf</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amgetconf</refname>
+<refpurpose>look up amanda.conf variables</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amgetconf</command>    
+    <arg choice='opt'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>parameter</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amgetconf</emphasis>
+looks up parameters in
+<emphasis remap='I'>amanda.conf</emphasis>,
+the &A; configuration file,
+or from the build and runtime environment,
+and returns their corresponding value.</para>
+
+<para>If
+<emphasis remap='I'>config</emphasis>
+is not specified,
+<command>amgetconf</command>
+assumes it is being run from the configuration directory and that
+<emphasis remap='I'>amanda.conf</emphasis>
+is present.</para>
+
+<para>If
+<emphasis remap='I'>parameter</emphasis>
+begins with
+<emphasis remap='I'>build.</emphasis>,
+the (case insensitive) string following the period
+is a build environment variable.
+Variables without a value (e.g.
+<emphasis remap='I'>XFSDUMP</emphasis>
+on a system that does not support that type of file system)
+will not report an error and will return an empty string as the value.
+Flag variables (e.g.
+<emphasis remap='I'>USE_AMANDAHOSTS</emphasis>)
+will return
+<literal>1</literal>
+if the flag is set or an empty string if it is not.</para>
+
+<para>If
+<emphasis remap='I'>parameter</emphasis>
+begins with
+<emphasis remap='I'>dbopen.</emphasis>,
+the string following the period is a program name and an &A; debug
+file will be created for the caller.
+The name of the file is returned.</para>
+
+<para>If
+<emphasis remap='I'>parameter</emphasis>
+begins with
+<emphasis remap='I'>dbclose.</emphasis>,
+the string following the period is a program name previously used with
+<emphasis remap='I'>dbopen.</emphasis>,
+followed by a colon (:) and the previously opened file name.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>Find out the path to the log file directory:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amgetconf daily logdir
+/usr/local/etc/amanda//daily
+</literallayout> <!-- .fi -->
+
+<para>Find out the current tape type:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amgetconf daily tapetype
+DLT4000-IV
+</literallayout> <!-- .fi -->
+
+<para>Find out the default configuration directory:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amgetconf daily build.CONFIG_DIR
+/usr/local/etc/amanda/
+</literallayout> <!-- .fi -->
+
+<para>Create, use and close a debug file in a script:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% set debug_file = `amgetconf daily dbopen.myscript`
+% echo debug information &gt;&gt; $debug_file
+% amgetconf daily dbclose.myscript:$debug_file
+</literallayout> <!-- .fi -->
+</refsect1>
+
+<refsect1><title>MESSAGES</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term>amgetconf: no such parameter <emphasis remap='I'>param</emphasis></term>
+  <listitem>
+<para>Parameter
+<emphasis remap='I'>param</emphasis>
+is not a known keyword
+(e.g. not a valid
+<emphasis remap='I'>amanda.conf</emphasis>
+keyword).
+In this case,
+<command>amgetconf</command>
+will write &quot;<emphasis remap='B'>BUGGY</emphasis>&quot; to stdout as the value.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amlabel.8.xml b/man/xml-source/amlabel.8.xml
new file mode 100644 (file)
index 0000000..4a8e76e
--- /dev/null
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amlabel.8'>
+
+<refmeta>
+<refentrytitle>amlabel</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amlabel</refname>
+<refpurpose>label an &A; tape</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amlabel</command>    
+    <arg choice='opt'>-f </arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>label</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>slot</replaceable></arg><arg choice='plain'><replaceable>slot</replaceable></arg></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para>All &A; tapes must be pre-labeled before they are used.
+&A; verifies the label in
+<emphasis remap='B'>amdump</emphasis>
+and
+<emphasis remap='B'>amflush</emphasis>
+before writing to make sure the proper tape is loaded.</para>
+
+<para><emphasis remap='B'>Amlabel</emphasis>
+writes an &A; label on the tape in the device specified by the
+<emphasis remap='I'>amanda.conf</emphasis>
+file in /usr/local/etc/amanda/<emphasis remap='I'>config</emphasis>.
+<emphasis remap='I'>Label</emphasis>
+may be any string that does not contain whitespace and that matches the
+<emphasis remap='I'>amanda.conf</emphasis>
+<emphasis remap='B'>labelstr</emphasis>
+regular expression option.
+It is up to the system administrator to define a naming convention.</para>
+
+<para><emphasis remap='B'>Amlabel</emphasis>
+appends the new tape to the
+<emphasis remap='I'>tapelist</emphasis>
+file so it will be used by &A; before it reuses any other tapes.
+When you
+<command>amlabel</command>
+multiple tapes, they will be used in the order you
+<command>amlabel</command>
+them.</para>
+
+<para><emphasis remap='B'>Amlabel</emphasis>
+will not write the label if the tape contains an active
+&A; tape or if the label specified is on an active tape.
+The
+<option>-f</option>
+(force) flag bypasses these verifications.</para>
+
+<para>An optional
+<emphasis remap='I'>slot</emphasis>
+may be specified after the tape label.
+If a tape changer is in use,
+<command>amlabel</command>
+will label the tape in the specified slot instead of the currently loaded tape.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>Write an &A; label with the string &quot;DMP000&quot; on
+the tape loaded in the device named in the
+<emphasis remap='B'>tapedev</emphasis>
+option in /usr/local/etc/amanda/daily/amanda.conf:</para>
+
+<programlisting>
+% amlabel daily DMP000 
+</programlisting>
+
+<para>Label the tape in slot 3 of the currently configured tape changer
+with the string &quot;DMP003&quot;:</para>
+
+<programlisting>
+% amlabel daily DMP003 slot 3 
+</programlisting>
+</refsect1>
+
+<refsect1><title>MESSAGES</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term>label <emphasis remap='I'>label</emphasis> doesn't match labelstr <emphasis remap='I'>str</emphasis></term>
+  <listitem>
+<para>Label
+<emphasis remap='I'>label</emphasis>
+on the command line does not match the
+<emphasis remap='I'>labelstr</emphasis>
+regular expression
+<emphasis remap='I'>str</emphasis>
+from
+<emphasis remap='I'>amanda.conf</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>label <emphasis remap='I'>label</emphasis> already on a tape</term>
+  <listitem>
+<para>Label
+<emphasis remap='I'>label</emphasis>
+is already listed as an active &A; tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>no tpchanger specified in <emphasis remap='I'>path</emphasis> , so slot command invalid</term>
+  <listitem>
+<para>The command line has the
+<emphasis remap='B'>slot</emphasis>
+parameter but the
+<emphasis remap='I'>amanda.conf</emphasis>
+file in
+<emphasis remap='I'>path</emphasis>
+does not have a tape changer configured.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>reading label <emphasis remap='I'>label</emphasis>, tape is in another amanda configuration</term>
+  <listitem>
+<para>This tape appears to be a valid &A; tape,
+but label does not match
+<emphasis remap='B'>labelstr</emphasis>
+for this configuration so it is probably part of a different &A; configuration.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>reading label <emphasis remap='I'>label</emphasis>, tape is active</term>
+  <listitem>
+<para>Tape
+<emphasis remap='I'>label</emphasis>
+appears to already be part of this &A; configuration
+and active, i.e. has valid data on it.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term>no label found, are you sure <emphasis remap='I'>tape</emphasis> is non-rewinding?</term>
+  <listitem>
+<para>While checking that the label was written correctly,
+<command>amlabel</command>
+got an error that might be caused by mis-configuring &A;
+with a rewinding tape device name
+instead of a non-rewinding device name for
+<emphasis remap='I'>tape.</emphasis></para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds;: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+<citerefentry><refentrytitle>amflush</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/ammt.8.xml b/man/xml-source/ammt.8.xml
new file mode 100644 (file)
index 0000000..515fcb5
--- /dev/null
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='ammt.8'>
+
+<refmeta>
+<refentrytitle>ammt</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>ammt</refname>
+<refpurpose>&A; version of mt</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>ammt</command>    
+    <arg choice='opt'>-d </arg>
+    <group choice='opt'><arg choice='plain'>-f </arg><arg choice='plain'>-t </arg><arg choice='plain'><replaceable>device</replaceable></arg></group>
+    <arg choice='plain'><replaceable>command</replaceable></arg>
+    <arg choice='opt'><replaceable>count</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Ammt</emphasis>
+provides just enough of the standard UNIX
+<emphasis remap='B'>mt</emphasis>
+command for the needs of &A;.
+This is handy when doing a full restore and the standard
+<emphasis remap='B'>mt</emphasis>
+program has not yet been found.</para>
+
+<para><emphasis remap='B'>Ammt</emphasis>
+also provides access to the &A; output drivers that support
+various tape simulations.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.
+See the
+<emphasis remap='B'>OUTPUT DRIVERS</emphasis>
+section of
+<emphasis remap='I'>amanda(8)</emphasis>
+for more information on the &A; output drivers.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-d</option></term>
+  <listitem>
+<para>Turn on debugging output.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-f</option><replaceable> device</replaceable></term>
+  <listitem>
+<para>Access tape device
+<emphasis remap='I'>device</emphasis>.
+If not specified, the
+<emphasis remap='B'>TAPE</emphasis>
+environment variable is used.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-t</option><replaceable> device</replaceable></term>
+  <listitem>
+<para>Same as
+<option>-f</option>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>command</emphasis><emphasis remap='I'> count</emphasis></term>
+  <listitem>
+<para>Which command to issue, and an optional count of operations.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>COMMANDS</title>
+<para>Each command may be abbreviated to whatever length makes it unique.</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>eof|weof</emphasis><emphasis remap='I'> count</emphasis></term>
+  <listitem>
+<para>Write
+<emphasis remap='I'>count</emphasis>
+(default: 1) end of file marks (tapemarks).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>fsf</emphasis><emphasis remap='I'> count</emphasis></term>
+  <listitem>
+<para>Skip forward
+<emphasis remap='I'>count</emphasis>
+(default: 1) files.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>bsf</emphasis><emphasis remap='I'> count</emphasis></term>
+  <listitem>
+<para>Skip backward
+<emphasis remap='I'>count</emphasis>
+(default: 1) files.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>asf</emphasis><emphasis remap='I'> count</emphasis></term>
+  <listitem>
+<para>Position to file number
+<emphasis remap='I'>count</emphasis>
+(default: 0)
+where zero is beginning of tape.
+This is the same as a
+<emphasis remap='B'>rewind</emphasis>
+followed by a
+<emphasis remap='B'>fsf</emphasis>
+<emphasis remap='I'>count</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>rewind</emphasis></term>
+  <listitem>
+<para>Rewind to beginning of tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>offline|rewoffl</emphasis></term>
+  <listitem>
+<para>Rewind to beginning of tape and unload the tape from the drive.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>status</emphasis></term>
+  <listitem>
+<para>Report status information about the drive.
+Which data reported, and what it means,
+depends on the underlying operating system,
+and may include:</para>
+    <variablelist remap='TP'>
+      <varlistentry>
+      <term>ONLINE</term>
+      <listitem>
+<para>Indicates the drive is online and ready.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>OFFLINE</term>
+      <listitem>
+<para>Indicates the drive is offline or not ready.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>BOT</term>
+      <listitem>
+<para>Indicates the drive is at beginning of tape.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>EOT</term>
+      <listitem>
+<para>Indicates the drive is at end of tape.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>PROTECTED</term>
+      <listitem>
+<para>Indicates the tape is write protected.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>ds</term>
+      <listitem>
+<para>Device status.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>er</term>
+      <listitem>
+<para>Error register.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>fileno</term>
+      <listitem>
+<para>Current tape file number.</para>
+      </listitem>
+      </varlistentry>
+      <varlistentry>
+      <term>blkno</term>
+      <listitem>
+<para>Current tape block number file.</para>
+      </listitem>
+      </varlistentry>
+    </variablelist>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<note>Many systems only report good data when a tape is in the drive and ready.
+</note>
+<para />
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Marc Mengel <email>mengel@fnal.gov</email>, John R. Jackson
+<email>jrj@purdue.edu</email>: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amoverview.8.xml b/man/xml-source/amoverview.8.xml
new file mode 100644 (file)
index 0000000..e2b7a92
--- /dev/null
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amoverview.8'>
+
+<refmeta>
+<refentrytitle>amoverview</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amoverview</refname>
+<refpurpose>display file systems processed by &A; over time</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amoverview</command>    
+    <arg choice='opt'><arg choice='opt'>-config </arg><arg choice='plain'><replaceable>config</replaceable></arg></arg>
+    <arg choice='opt'>-hostwidth <replaceable>width</replaceable></arg>
+    <arg choice='opt'>-diskwidth <replaceable>width</replaceable></arg>
+    <arg choice='opt'>-skipmissed</arg>
+    <arg choice='opt'>-last</arg>
+    <arg choice='opt'>-num0</arg>
+    <arg choice='opt'>-togo0</arg>
+    <arg choice='opt'>-verbose</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amoverview</emphasis>
+displays a chart showing hosts and file systems processed by &A;
+along with the backup level performed each day.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-config</option> <replaceable>config</replaceable></term>
+  <listitem>
+<para>Use configuration
+<emphasis remap='I'>config</emphasis>
+instead of configuration daily.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-hostwidth</option> <replaceable>width</replaceable></term>
+  <listitem>
+<para>Set
+<emphasis remap='B'>host</emphasis>
+field column width to
+<emphasis remap='I'>width</emphasis>
+characters instead of 8.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-diskwidth</option> <replaceable>width</replaceable></term>
+  <listitem>
+<para>Set
+<emphasis remap='B'>disk</emphasis>
+field column width to
+<emphasis remap='I'>width</emphasis>
+characters instead of 20.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-skipmissed</option></term>
+  <listitem>
+<para>Compacts the output by only printing stats 
+for the days &A; actually ran.
+</para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><option>-last</option></term>
+  <listitem>
+  <para>
+  Outputs the last status of each disk at the start. 
+  Useful for long tapecycles and/or sparse reports.
+  </para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><option>-num0</option></term>
+  <listitem>
+  <para>
+  Outputs the number of level 0 dumps for each disk.
+  </para>
+  </listitem>
+  </varlistentry>
+  
+  <varlistentry>
+  <term><option>-togo0</option></term>
+  <listitem>
+  <para>
+  Outputs the number of runs until the last level 0 dump is overwritten.
+  </para>
+  </listitem>
+  </varlistentry>
+
+  <varlistentry>
+  <term><option>-verbose</option></term>
+  <listitem>
+<para><emphasis remap='B'>Amoverview</emphasis>
+can take a long while on large systems.
+This option reports intermediate steps while it is working.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>RESULTS</title>
+<para><command>amoverview</command>
+is a summary of the output of &quot;
+<emphasis remap='B'>amadmin &lt;config&gt; find</emphasis>
+&quot;.
+When the last column of 
+<emphasis remap='B'>amadmin find</emphasis>
+contains anything other than &quot;OK&quot;,
+amoverview translates this into &quot;E&quot; for that day.</para>
+
+<para>A number indicates the level of backup and it succeeded.
+An &quot;E&quot; indicates an error for that day.
+You get an &quot;E&quot; for all errors, like failed to connect, datatimeout,
+computer crashed, etc, but also for failing to write to tape.</para>
+
+<para>You can have an &quot;E&quot; followed by a number if a filesystem ran into
+end-of-tape once (gives an &quot;E&quot;, and later that day, you flush it to a
+second tape (a number: the level, indicating success).  If the flush
+failed too, you get a double &quot;EE&quot; for that day.</para>
+
+<para>You can also have a double code if you have two tapes in the changer and
+&A; failed to write to tape the first time because it hit end of tape
+(resulting in &quot;E0&quot;, for a full, &quot;E1&quot; for an
+incremental etc.)
+or twice with error (&quot;EE&quot;), and may a successful flush afterwards
+giving maybe &quot;EE0&quot;. (Only the latest 2 characters are printed).</para>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>This shows the
+<filename>/home</filename>
+file system on
+<emphasis remap='I'>host2</emphasis>
+was backed up at level 3 on the 8th, 9th and 10th of December,
+had a full backup on the 11th,
+a level 1 on the 12th and a level 2 on the 13th.</para>
+
+<programlisting remap='.nf'>
+# amoverview
+                         date 12 12 12 12 12 12
+host     disk                 08 09 10 11 12 13
+host1    /                     0  1  1  1  1  1
+host1    /var                  0  1  1  1  1  1
+host2    /                     1  1  1  1  1  0
+host2    /home                 3  3  3  0  1  2
+host2    /opt                  1  1  1  1  1  1
+host2    /var                  1  1  0  1  1  1 
+</programlisting>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amplot.8.xml b/man/xml-source/amplot.8.xml
new file mode 100644 (file)
index 0000000..f37a30e
--- /dev/null
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amplot.8'>
+<refmeta>
+<refentrytitle>amplot</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amplot</refname>
+<refpurpose>visualize the behavior of &A;</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amplot</command>    
+    <arg choice='opt'>-b </arg>
+    <arg choice='opt'>-c </arg>
+    <arg choice='opt'>-e </arg>
+    <arg choice='opt'>-g </arg>
+    <arg choice='opt'>-l </arg>
+    <arg choice='opt'>-p </arg>
+    <arg choice='opt'><arg choice='plain'>-t </arg><arg choice='plain'><replaceable>T</replaceable></arg></arg>
+    <arg choice='plain'><replaceable>amdump_files</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amplot</emphasis>
+reads an
+<emphasis remap='B'>amdump</emphasis>
+output file that &A; generates each run (e.g.
+<emphasis remap='I'>amdump.1</emphasis>)
+and translates the information into a
+picture format that may be used to determine how your installation
+is doing and if any parameters need to be changed.
+<emphasis remap='B'>Amplot</emphasis>
+also prints out
+<emphasis remap='B'>amdump</emphasis>
+lines that it either does not
+understand or knows to be warning or error lines
+and a summary of the start, end and total time for each backup image.</para>
+
+<para><emphasis remap='B'>Amplot</emphasis>
+is a shell script that executes an
+<emphasis remap='B'>awk</emphasis>
+program
+<emphasis remap='I'></emphasis>(<emphasis remap='P->I'>amplot.awk</emphasis>)
+to scan the
+<emphasis remap='B'>amdump</emphasis>
+output file.
+It then executes a
+<emphasis remap='B'>gnuplot</emphasis>
+program
+<emphasis remap='I'></emphasis>(<emphasis remap='P->I'>amplot.g</emphasis>)
+to generate the graph.
+The
+<emphasis remap='B'>awk</emphasis>
+program is written in an enhanced version of awk,
+such as GNU awk
+<emphasis remap='B'></emphasis>(<emphasis remap='P->B'>gawk</emphasis>
+version 2.15 or later) or
+<emphasis remap='B'>nawk</emphasis>.</para>
+
+<para>During execution,
+<command>amplot</command>
+generates a few temporary files that
+<emphasis remap='B'>gnuplot</emphasis>
+uses.
+These files are deleted at the end of execution.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-b</option></term>
+  <listitem>
+<para>Generate b/w postscript file (need
+<option>-p</option>).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-c</option></term>
+  <listitem>
+<para>Compress
+<emphasis remap='I'>amdump_files</emphasis>
+after plotting.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-e</option></term>
+  <listitem>
+<para>Extend the X (time) axis if needed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-g</option></term>
+  <listitem>
+<para>Direct
+<emphasis remap='I'>gnuplot</emphasis>
+output directly to the X11 display (default).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-p</option></term>
+  <listitem>
+<para>Direct postscript output to file
+<emphasis remap='B'></emphasis><emphasis remap='I'>YYYYMMDD</emphasis><emphasis remap='P->B'>.ps</emphasis>
+(opposite of
+<option>-g</option>).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-l</option></term>
+  <listitem>
+<para>Generate landscape oriented output (needs
+<option>-p</option>).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-t </option><emphasis remap='I'>T</emphasis></term>
+  <listitem>
+<para>Set the right edge of the plot to be
+<emphasis remap='I'>T</emphasis>
+hours.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The
+<emphasis remap='I'>amdump_files</emphasis>
+may be in various compressed formats
+<emphasis remap='B'></emphasis>(<emphasis remap='P->B'>compress</emphasis>,
+<emphasis remap='B'>gzip</emphasis>,
+<emphasis remap='B'>pact</emphasis>,
+<emphasis remap='B'>compact</emphasis>).</para>
+</refsect1>
+
+<refsect1><title>INTERPRETATION</title>
+<para>The figure is divided into a number of regions.
+There are titles on the top that show important statistical information
+about the configuration and from this execution of
+<emphasis remap='B'>amdump</emphasis>.
+In the figure, the X axis is time, with 0 being the moment
+<emphasis remap='B'>amdump</emphasis>
+was started.
+The Y axis is divided into 5 regions:</para>
+
+<para><emphasis remap='I'>QUEUES:</emphasis>
+How many backups have not been started,
+how many are waiting on space in the holding disk
+and how many have been transferred successfully to tape.</para>
+
+<para><emphasis remap='I'>%BANDWIDTH:</emphasis>
+Percentage of allowed network bandwidth in use.</para>
+
+<para><emphasis remap='I'>HOLDING DISK:</emphasis>
+The higher line depicts space allocated on the holding disk to
+backups in progress and completed backups waiting to be written to tape.
+The lower line depicts the fraction of the holding disk containing completed
+backups waiting to be written to tape including the file currently being
+written to tape.
+The scale is percentage of the holding disk.</para>
+
+<para><emphasis remap='I'>TAPE:</emphasis>
+Tape drive usage.</para>
+
+<para><emphasis remap='I'>%DUMPERS:</emphasis>
+Percentage of active dumpers.</para>
+
+<para>The idle period at the left of the graph is time
+<emphasis remap='B'>amdump</emphasis>
+is asking the machines how much data they are going to dump.
+This process can take a while if hosts are down
+or it takes them a long time to generate estimates.</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Olafur Gudmundsson <email>ogud@tis.com</email>,
+Trusted Information Systems,
+formerly at University of Maryland, College Park: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>BUGS</title>
+<para>Reports lines it does not recognize, mainly error cases but some are
+legitimate lines the program needs to be taught about.</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>gawk</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>nawk</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>awk</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>gnuplot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>sh</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>compress</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>gzip</refentrytitle><manvolnum>1</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amrecover.8.xml b/man/xml-source/amrecover.8.xml
new file mode 100644 (file)
index 0000000..a3b29d5
--- /dev/null
@@ -0,0 +1,576 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amrecover.8'>
+
+<!-- P1 listing suppressed (not used) -->
+<refmeta>
+<refentrytitle>amrecover</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amrecover</refname>
+<refpurpose>&A; index database browser</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amrecover</command>    
+    <arg choice='opt'><arg choice='opt'>-C </arg><arg choice='plain'><replaceable>config</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-s </arg><arg choice='plain'><replaceable>index-server</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-t </arg><arg choice='plain'><replaceable>tape-server</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-d </arg><arg choice='plain'><replaceable>tape-device</replaceable></arg></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amrecover</emphasis>
+browses the database of &A; index files to determine which tapes
+contain files to recover.  Furthermore, it is able to recover files.</para>
+
+<para>In order to restore files in place, you must invoke
+<command>amrecover</command>
+from the root of the backed up filesystem, or use
+<emphasis remap='B'>lcd</emphasis>
+to move into that directory, otherwise a directory tree that resembles 
+the backed up filesystem will be created in the current directory.
+See the examples below for details.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<note>The Default values are those set at compile-time.
+Use <command>amrestore</command> to recover client-encrypted or
+client-custom-compressed tapes.</note>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>[ -C ] config</emphasis></term>
+  <listitem>
+<para>&A; configuration.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-s index-server</option></term>
+  <listitem>
+<para>Host that runs the index daemon.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-t tape-server</option></term>
+  <listitem>
+<para>Host that runs the tape server daemon.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-d tape-device</option></term>
+  <listitem>
+<para>Tape device to use on the tape server host.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>COMMANDS</title>
+<para><emphasis remap='B'>Amrecover</emphasis>
+connects to the index server and then presents a command line prompt.
+Usage is similar to an ftp client.
+The GNU readline library is used to provide command line history and editing
+if it was built in to
+<command>amrecover</command>.</para>
+
+<para>The purpose of browsing the database is to build up a
+<emphasis remap='I'>restore list</emphasis>
+of files to be extracted from the backup system.
+The following commands are available:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>sethost hostname</emphasis></term>
+  <listitem>
+<para>Specifies which host to look at backup files for (default: the local host).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>setdate YYYY-MM-DD</emphasis></term>
+  <listitem>
+<para>Set the date (default: today).
+File listing commands only return information on
+backup images for this day,
+for the day before with the next lower dump level,
+and so on,
+until the most recent level 0 backup on or before
+the specified date is encountered.</para>
+
+<para>For example, if:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+1996-07-01 was a level 0 backup
+1996-07-02 through 1996-07-05 were level 1 backups
+1996-07-06 through 1997-07-08 were level 2 backups
+</literallayout> <!-- .fi -->
+
+<para>then if 1997-07-08 is the requested date,
+files from the following days would be used:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+1997-07-08 (the latest level 2 backup)
+1997-07-05 (the latest level 1 backup)
+1997-07-01 (the latest level 0 backup)
+</literallayout> <!-- .fi -->
+
+<para>Only the most recent version of a file will be presented.</para>
+
+<para>The following abbreviated date specifications are accepted:</para>
+<!-- .RS -->
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>--MM-DD</option></term>
+  <listitem>
+<para>dates in the current year</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>---DD</option></term>
+  <listitem>
+<para>dates in the current month of the current year</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+  </listitem>
+  </varlistentry>
+</variablelist>
+<!-- .RE -->
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>setdisk <arg
+  choice='plain'><replaceable>diskname</replaceable></arg> <arg
+  choice='opt'><replaceable>mountpoint</replaceable></arg></emphasis></term>
+  <listitem>
+<para>Specifies which disk to consider
+(default: the disk holding the working directory where
+<command>amrecover</command>
+is started).
+It can only be set after the host is set with
+<emphasis remap='B'>sethost</emphasis>.
+<emphasis remap='I'>Diskname</emphasis>
+is the device name specified in the
+<emphasis remap='I'>amanda.conf</emphasis>
+or
+<emphasis remap='I'>disklist</emphasis>
+configuration file.
+The disk must be local to the host.
+If
+<emphasis remap='I'>mountpoint</emphasis>
+is not specified, all pathnames will be relative to the (unknown)
+mount point instead of full pathnames.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>listdisk [diskdevice]</emphasis></term>
+  <listitem>
+<para>List all
+<emphasis remap='B'>diskname</emphasis></para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>settape [[server]:][tapedev|default]</emphasis></term>
+  <listitem>
+<para>Specifies the host to use as the tape server, and which of its tape
+devices to use.
+If the server is omitted, but the colon is not, the
+server name reverts to the configure-time
+default.
+If the tape device is omitted, it remains unchanged.
+To use the default tape device selected by the tape server, the word
+<emphasis remap='I'>default</emphasis>
+must be specified.
+If no argument is specified, or the argument is an
+empty string, no changes occur, and the current settings are
+displayed.</para>
+
+<para>If you want amrecover to use your changer, the 
+<emphasis remap='I'>tapedev</emphasis>
+must be equal to the amrecover_changer setting on the server.</para>
+
+<para>If you need to change the protocol (tape:, rait:, file:, null:) then you
+must specify the hostname.</para>
+
+<programlisting>
+settape 192.168.0.10:file:/file1
+</programlisting>
+
+<para>You can change the tape device when amrecover ask you to load the tape:</para>
+
+<programlisting>
+Load tape DMP014 now
+Continue? [Y/n/t]: t
+Tape device: server2:/dev/nst2
+Continue? [Y/n/t]: Y
+Using tape /dev/nst2 from server server2.
+</programlisting>
+
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>setmode mode</emphasis></term>
+  <listitem>
+<para>Set the extraction mode for Samba shares.
+If
+<emphasis remap='I'>mode</emphasis>
+is
+<emphasis remap='B'>smb</emphasis>,
+shares are sent to the Samba server
+to be restored back onto the PC.
+If
+<emphasis remap='I'>mode</emphasis>
+is
+<emphasis remap='B'>tar</emphasis>,
+they are extracted on the local machine the same way tar volumes are extracted.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>mode</emphasis></term>
+  <listitem>
+<para>Displays the extracting mode for Samba shares.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>history</emphasis></term>
+  <listitem>
+<para>Show the backup history of the current host and disk.
+Dates, levels, tapes and file position on tape of each backup are displayed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>pwd</emphasis></term>
+  <listitem>
+<para>Display the name of the current backup working directory.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>cd dir</emphasis></term>
+  <listitem>
+<para>Change the backup working directory to
+<emphasis remap='I'>dir.</emphasis>
+If the mount point was specified with
+<emphasis remap='B'>setdisk</emphasis>,
+this can be a full pathname or it can be
+relative to the current backup working directory.
+If the mount point was not specified,
+paths are relative to the mount point if they start with &quot;/&quot;,
+otherwise they are relative to the current backup working directory.
+The
+<emphasis remap='I'>dir</emphasis>
+can be a shell style wildcards.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>cdx dir</emphasis></term>
+  <listitem>
+<para>Like the
+<emphasis remap='B'>cd</emphasis>
+command but allow regular expression.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>lpwd</emphasis></term>
+  <listitem>
+<para>Display the
+<command>amrecover</command>
+working directory.
+Files will be restored under this directory,
+relative to the backed up filesystem.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>lcd path</emphasis></term>
+  <listitem>
+<para>Change the
+<command>amrecover</command>
+working directory to
+<emphasis remap='I'>path</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>ls</emphasis></term>
+  <listitem>
+<para>List the contents of the current backup working directory.
+See the description of the
+<emphasis remap='B'>setdate</emphasis>
+command for how the view of the
+directory is built up.
+The backup date is shown for each file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>add item1 item2 ...</emphasis></term>
+  <listitem>
+<para>Add the specified files or directories to the restore list.
+Each item may have shell style wildcards.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>addx item1 item2 ...</emphasis></term>
+  <listitem>
+<para>Add the specified files or directories to the restore list.
+Each item may be a regular expression.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>delete item1 item2 ...</emphasis></term>
+  <listitem>
+<para>Delete the specified files or directories from the restore list.
+Each item may have shell style wildcards.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>deletex item1 item2 ...</emphasis></term>
+  <listitem>
+<para>Delete the specified files or directories from the restore list.
+Each item may be a regular expression.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>list file</emphasis></term>
+  <listitem>
+<para>Display the contents of the restore list.
+If a file name is specified,
+the restore list is written to that file.
+This can be used to manually extract the files from the &A; tapes with
+<emphasis remap='B'>amrestore</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>clear</emphasis></term>
+  <listitem>
+<para>Clear the restore list.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>quit</emphasis></term>
+  <listitem>
+<para>Close the connection to the index server and exit.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>exit</emphasis></term>
+  <listitem>
+<para>Close the connection to the index server and exit.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>extract</emphasis></term>
+  <listitem>
+<para>Start the extract sequence (see the examples below).  Make sure the
+local working directory is the root of the backed up filesystem, or
+another directory that will behave like that.  Use
+<emphasis remap='B'>lpwd</emphasis>
+to display the local working directory, and
+<emphasis remap='B'>lcd</emphasis>
+to change it.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>help</emphasis></term>
+  <listitem>
+<para>Display a brief list of these commands.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>EXAMPLES</title>
+<para>The following shows the recovery of an old
+<emphasis remap='I'>syslog</emphasis>
+file.</para>
+
+<programlisting>
+# cd /var/log
+# ls -l syslog.7
+syslog.7: No such file or directory
+# amrecover
+AMRECOVER Version 2.4.2. Contacting server on oops ...
+220 oops &A; index server (2.4.2) ready.
+Setting restore date to today (1997-12-09)
+200 Working date set to 1997-12-09.
+200 Config set to daily.
+200 Dump host set to this-host.some.org.
+$CWD '/var/log' is on disk '/var' mounted at '/var'.
+200 Disk set to /var.
+/var/log
+WARNING: not on root of selected filesystem, check man-page!
+amrecover&gt; ls
+1997-12-09 daemon.log
+1997-12-09 syslog
+1997-12-08 authlog
+1997-12-08 sysidconfig.log
+1997-12-08 syslog.0
+1997-12-08 syslog.1
+1997-12-08 syslog.2
+1997-12-08 syslog.3
+1997-12-08 syslog.4
+1997-12-08 syslog.5
+1997-12-08 syslog.6
+1997-12-08 syslog.7
+amrecover&gt; add syslog.7
+Added /log/syslog.7
+amrecover&gt; lpwd
+/var/log
+amrecover&gt; lcd ..
+/var
+amrecover&gt; extract
+
+Extracting files using tape drive /dev/nst0 on host 192.168.0.10
+
+The following tapes are needed: DMP014
+
+Restoring files into directory /var
+Continue? [Y/n]: y
+
+Load tape DMP014 now
+Continue? [Y/n/t]: y
+set owner/mode for '.'? [yn] n
+amrecover&gt; quit
+200 Good bye.
+# ls -l syslog.7
+total 26
+-rw-r--r--   1 root     other      12678 Oct 14 16:36 syslog.7
+</programlisting>
+
+<para>If you do not want to overwrite existing files,
+create a subdirectory to run
+<command>amrecover</command>
+from and then move the restored files afterward.</para>
+
+<programlisting>
+# cd /var
+# (umask 077 ; mkdir .restore)
+# cd .restore
+# amrecover
+AMRECOVER Version 2.4.2. Contacting server on oops ...
+...
+amrecover&gt; cd log
+/var/log
+amrecover&gt; ls
+...
+amrecover&gt; add syslog.7
+Added /log/syslog.7
+amrecover&gt; lpwd
+/var/.restore
+amrecover&gt; extract
+
+Extracting files using tape drive /dev/nst0 on host 192.168.0.10
+...
+amrecover&gt; quit
+200 Good bye.
+# mv -i log/syslog.7 ../log/syslog.7-restored
+# cd ..
+# rm -fr .restore
+</programlisting>
+
+<para>If you need to run
+<emphasis remap='B'>amrestore</emphasis>
+by hand instead of letting
+<command>amrecover</command>
+control it,
+use the
+<emphasis remap='B'>list</emphasis>
+command after browsing to display the needed tapes.</para>
+
+<programlisting>
+# cd /var/log
+# amrecover
+AMRECOVER Version 2.4.2. Contacting server on oops ...
+...
+amrecover&gt; ls
+...
+amrecover&gt; add syslog syslog.6 syslog.7
+Added /log/syslog
+Added /log/syslog.6
+Added /log/syslog.7
+amrecover&gt; list
+TAPE DMP014 LEVEL 0 DATE 1997-12-08
+        /log/syslog.7
+        /log/syslog.6
+TAPE DMP015 LEVEL 1 DATE 1997-12-09
+        /log/syslog
+amrecover&gt; quit 
+</programlisting>
+
+<para>The
+<emphasis remap='B'>history</emphasis>
+command shows each tape that has a backup of the
+current disk along with the date of the backup,
+the level,
+the tape label
+and the file position on the tape.
+All active tapes are listed, not just back to
+the most recent full dump.</para>
+
+<para>Tape file position zero is a label.
+The first backup image is in file position one.</para>
+
+<programlisting>
+# cd /var/log
+# amrecover
+AMRECOVER Version 2.4.2. Contacting server on oops ...
+...
+amrecover&gt; history
+200- Dump history for config &quot;daily&quot; host &quot;this-host.some.org&quot; disk &quot;/var&quot;
+201- 1997-12-09 1 DMP015 9
+201- 1997-12-08 1 DMP014 11
+201- 1997-12-07 0 DMP013 22
+201- 1997-12-06 1 DMP012 16
+201- 1997-12-05 1 DMP011 9
+201- 1997-12-04 0 DMP010 11
+201- 1997-12-03 1 DMP009 7
+201- 1997-12-02 1 DMP008 7
+201- 1997-12-01 1 DMP007 9
+201- 1997-11-30 1 DMP006 6
+...
+amrecover&gt; quit 
+</programlisting>
+</refsect1>
+
+<refsect1><title>ENVIRONMENT</title>
+<para><envar>PAGER</envar>
+<!-- .RS -->
+The 
+<emphasis remap='B'>ls</emphasis>
+and 
+<emphasis remap='B'>list</emphasis>
+commands will use $PAGER to display the file lists.
+Defaults to
+<emphasis remap='I'>more</emphasis>
+if PAGER is not set.</para>
+<!-- .RE -->
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Alan M. McIvor <email>alan@kauri.auck.irl.cri.nz</email> : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amfetchdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>readline</refentrytitle><manvolnum>3</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amreport.8.xml b/man/xml-source/amreport.8.xml
new file mode 100644 (file)
index 0000000..b7fd827
--- /dev/null
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amreport.8'>
+
+<refmeta>
+<refentrytitle>amreport</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amreport</refname>
+<refpurpose>generate a formatted output of statistics for an &A; run</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amreport</command>    
+    <arg choice='opt'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'>-l </arg><arg choice='plain'><replaceable>logfile</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-f </arg><arg choice='plain'><replaceable>outputfile</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-p </arg><arg choice='plain'><replaceable>postscriptfile</replaceable></arg></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amreport</emphasis>
+generates a summary report of an
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+backup run.
+If no configuration name is specified, amanda.conf is
+read from the current directory.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>config</emphasis></term>
+  <listitem>
+<para>Name of the configuration to process.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-l</option> <replaceable>logfile</replaceable></term>
+  <listitem>
+<para>Name of the log file to parse to generate the report.
+If a log file is not specified, it defaults to the file:</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<!-- .RS -->
+<!-- .RS -->
+<para><emphasis remap='I'>logdir</emphasis>/log</para>
+<!-- .RE -->
+<!-- .RE -->
+
+<para>where
+<emphasis remap='I'>logdir</emphasis>
+is the log directory defined in amanda.conf.</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-f</option> <replaceable>outputfile</replaceable></term>
+  <listitem>
+<para>Normally,
+<command>amreport</command>
+sends the report via e-mail to the
+<emphasis remap='I'>mailto</emphasis>
+user as defined in the amanda.conf file.
+If
+<emphasis remap='I'>outputfile</emphasis>
+is specified, then the report is put in
+<emphasis remap='I'>outputfile</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-p</option> <replaceable>postscriptfile</replaceable></term>
+  <listitem>
+<para>Send the postscript output to the file
+<emphasis remap='I'>postscriptfile</emphasis>
+instead of to the
+<citerefentry><refentrytitle>lpr</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+command.
+This option has an effect only if the
+<emphasis remap='I'>lbl-templ</emphasis>
+directive is specified in amanda.conf.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>LABEL PRINTING</title>
+<para>&A; can print postscript labels describing the contents
+of tape(s) written in a run.
+The labels are designed to be folded and
+inserted into the tape case along with the tape or hole punched and put 
+in a 3-ring binder.
+Various label templates are provided to
+format data for different tape sizes.</para>
+
+<para>The information printed varies slightly between label templates
+due to size constraints.
+Labels contain one line for each host/file-system
+pair and may also contain the file number on the tape,
+the level of the dump,
+the original size of the dump
+and the size of the (possibly compressed) tape file.</para>
+
+<para>Add the
+<emphasis remap='I'>lbl-templ</emphasis>
+parameter to the tapetype definition in amanda.conf to enable labels.
+If you don't add this line to your
+tapetype definition,
+<command>amreport</command>
+will not print tape labels.</para>
+
+<para>You may use the
+<emphasis>remap='I'>printer</emphasis>
+keyword in amanda.conf to print to other than the system default printer.</para>
+
+</refsect1>
+
+<refsect1><title>TEMPLATES</title>
+
+<para>&A; provides label templates for the following tape types.
+These are pretty generic labels and should be easy to customize for
+other tape types or particular site needs.</para>
+
+<!-- .RS -->
+<!-- .RS -->
+<literallayout remap='.nf'>
+* ExaByte 8mm tapes
+* DAT 4mm tapes
+* DLT tapes
+* 3-ring binder
+</literallayout> <!-- .fi -->
+
+<para>The 3-ring binder type is the most generic.
+It may be used to make a hardcopy log of the tapes.</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amflush</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amrestore.8.xml b/man/xml-source/amrestore.8.xml
new file mode 100644 (file)
index 0000000..21ba7bb
--- /dev/null
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amrestore.8'>
+
+<refmeta>
+<refentrytitle>amrestore</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amrestore</refname>
+<refpurpose>extract backup images from an &A; tape</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amrestore</command>    
+    <group choice='opt'><arg choice='plain'>-r </arg>
+       <arg choice='plain'>-c </arg>
+       <arg choice='plain'>-C </arg>
+    </group>
+    <arg choice='opt'><arg choice='plain'>-b </arg> <arg choice='plain'><replaceable>blocksize</replaceable></arg> </arg>
+    <arg choice='opt'><arg choice='plain'>-f </arg><arg choice='plain'><replaceable>fileno</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-l </arg><arg choice='plain'><replaceable>label</replaceable></arg></arg>
+    <arg choice='opt'>-p </arg>
+    <arg choice='opt'>-h </arg>
+    <group choice='plain'>
+       <arg choice='plain'><replaceable>tapedevice</replaceable></arg>
+       <arg choice='plain'><replaceable>holdingfile</replaceable></arg>
+       <arg choice='opt'><arg choice='plain'><replaceable>hostname</replaceable></arg>
+       <arg choice='opt'><arg choice='plain'><replaceable>diskname</replaceable></arg>
+       <arg choice='opt'><replaceable>datestamp</replaceable></arg> </arg></arg> ...
+    </group>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amrestore</emphasis>
+extracts backup images from the tape mounted on
+<emphasis remap='I'>tapedevice</emphasis>
+or from the holding disk file
+<emphasis remap='I'>holdingfile</emphasis>
+that match
+<emphasis remap='I'>hostname</emphasis>,
+<emphasis remap='I'>diskname</emphasis>
+and
+<emphasis remap='I'>datestamp</emphasis>
+patterns given on the command line.
+The tape or holding file must be in a format written by the
+<emphasis remap='B'>amdump</emphasis>
+or
+<emphasis remap='B'>amflush</emphasis>
+program.</para>
+
+<para>If
+<emphasis remap='I'>diskname</emphasis>
+is not specified, all backups on the tape for the previous
+<emphasis remap='I'>hostname</emphasis>
+are candidates.
+If
+<emphasis remap='I'>datestamp</emphasis>
+is not specified, all backups on the tape for the previous
+<emphasis remap='I'>hostname</emphasis>
+and
+<emphasis remap='I'>diskname</emphasis>
+are candidates.
+If no
+<emphasis remap='I'>hostname</emphasis>,
+<emphasis remap='I'>diskname</emphasis>
+or
+<emphasis remap='I'>datestamp</emphasis>
+are specified, every backup on the tape is a candidate.</para>
+
+<para><emphasis remap='I'>Hostname</emphasis>
+and
+<emphasis remap='I'>diskname</emphasis>
+are special expressions described in the &quot;HOST &amp; DISK EXPRESSION&quot; section
+of
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+<emphasis remap='I'>Datestamp</emphasis>
+are special expression described in the &quot;DATESTAMP EXPRESSION&quot; section
+of
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+For example, if
+<emphasis remap='I'>diskname</emphasis>
+is &quot;rz[23]a&quot;, it would match disks
+<emphasis remap='B'>rz2a</emphasis>
+and
+<emphasis remap='B'>rz3a</emphasis>.</para>
+
+<para><emphasis remap='I'>Datestamp</emphasis>
+is useful if
+<emphasis remap='B'>amflush</emphasis>
+writes multiple backup runs to a single tape.</para>
+
+<para>Unless
+<option>-p</option>
+is used,
+candidate backup images are extracted to files
+in the current directory named:</para>
+
+<!-- .RS -->
+<para><emphasis remap='I'>hostname.diskname.datestamp.dumplevel</emphasis></para>
+<!-- .RE -->
+
+<para>Amrestore doesn't use a changer, it restore from the tape already loaded
+in the
+<emphasis remap='I'>tapedevice.</emphasis></para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-b</option></term>
+  <listitem>
+<para>Set the blocksize used to read the tape or holding file.
+All holding files must be read with a blocksize of 32 KBytes.
+<emphasis remap='B'>Amrestore</emphasis>
+should normally be able to determine the blocksize for tapes
+on its own and not need this parameter.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The default is 32 KBytes.</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-f</option></term>
+  <listitem>
+<para>Do a rewind followed by a fsf &lt;fileno&gt; before trying to restore an image.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-l</option></term>
+  <listitem>
+<para>Check if we restoring from the tape with the right
+<emphasis remap='I'>label</emphasis></para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-p</option></term>
+  <listitem>
+<para>Pipe output.
+The first matching backup image is sent to standard output,
+which is normally a pipe to
+<emphasis remap='B'>restore</emphasis>
+or
+<emphasis remap='B'>tar</emphasis>,
+then
+<command>amrestore</command>
+quits.
+It may be run again to continue selecting backups to process.
+Make sure you specify the no-rewind
+<emphasis remap='I'>tapedevice</emphasis>
+when doing this.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Note:
+<emphasis remap='B'>restore</emphasis>
+may report &quot;short read&quot; errors when reading from a pipe.
+Most versions of
+<emphasis remap='B'>restore</emphasis>
+support a blocking factor option to let you set the read block size,
+and you should set it to 2.
+See the example below.</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-c</option></term>
+  <listitem>
+<para>Compress output using the fastest method the compression program provides.
+<emphasis remap='B'>Amrestore</emphasis>
+normally writes output files in a format understood by
+<emphasis remap='B'>restore</emphasis>
+or
+<emphasis remap='B'>tar</emphasis>,
+even if the backups on the tape are compressed.
+With the
+<option>-c</option>
+or
+<option>-C</option>
+option,
+<command>amrestore</command>
+writes all files in compressed format,
+even if the backups on the tape are not compressed.
+Output file names will have a
+<markup>.Z</markup>
+or
+<markup>.gz</markup>
+extension depending on whether
+<emphasis remap='B'>compress</emphasis>
+or
+<emphasis remap='B'>gzip</emphasis>
+is the preferred compression program.
+This option is useful when the current directory disk is small.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-C</option></term>
+  <listitem>
+<para>Compress output using the best method the compression program provides
+(may be very CPU intensive).
+See the notes above about the
+<option>-c</option>
+option.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-r</option></term>
+  <listitem>
+<para>Raw output.
+Backup images are output exactly as they are on the tape,
+including the
+<emphasis remap='B'>amdump</emphasis>
+headers.
+Output file names will have a
+<markup>.RAW</markup>
+extension.
+This option is only useful for debugging and other strange circumstances.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-h</option></term>
+  <listitem>
+<para>Header output.
+The tape header block is output at the beginning of each file.
+This is like
+<option>-r</option>
+except
+<option>-c</option>
+or
+<option>-C</option>
+may also be used to compress the result.
+<emphasis remap='B'>Amrecover</emphasis>
+uses the header to determine the restore program to use.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>If a header is written (-r or -h),
+only 32 KBytes are output regardless of the tape blocksize.
+This makes the resulting image usable as a holding file.</para>
+</refsect1>
+
+<refsect1><title>EXAMPLES</title>
+<para>The following does an interactive restore of disk
+<emphasis remap='I'>rz3g</emphasis>
+from host
+<emphasis remap='I'>seine</emphasis>,
+to restore particular files.
+Note the use of the
+<emphasis remap='B'>b</emphasis>
+option to
+<emphasis remap='B'>restore</emphasis>,
+which causes it to read in units of two 512-byte blocks (1 Kbyte)
+at a time.
+This helps keep it from complaining about short reads.</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amrestore -p /dev/nrmt9 seine rz3g | restore -ivbf 2 -
+</literallayout> <!-- .fi -->
+
+<para>The next example extracts all backup images for host
+<emphasis remap='I'>seine</emphasis>.
+This is the usual way to extract all data for a host after a disk crash.</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amrestore /dev/nrmt9 seine
+</literallayout> <!-- .fi -->
+
+<para>If the backup datestamp in the above example is
+<literal>19910125</literal>
+and
+<emphasis remap='I'>seine</emphasis>
+has level 0 backups of disks
+<emphasis remap='I'>rz1a</emphasis>
+and
+<emphasis remap='I'>rz1g</emphasis>
+on the tape,
+these files will be created in the current directory:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+seine.rz1a.19910125.0
+seine.rz1g.19910125.0
+</literallayout> <!-- .fi -->
+
+<para>You may also use
+<command>amrestore</command>
+to extract a backup image from a holding disk
+file that has not yet been flushed to tape:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amrestore -p /amanda/20001119/seine.rz1a.2 | restore -ivbf 2 -
+</literallayout> <!-- .fi -->
+
+<para><emphasis remap='B'>Amrestore</emphasis>
+may be used to generate a listing of images on a tape:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% mt -f /dev/nrmt9 rewind
+% amrestore -p /dev/nrmt9 no-such-host &gt; /dev/null
+</literallayout> <!-- .fi -->
+
+<para>This asks
+<command>amrestore</command>
+to find images for host
+<emphasis remap='B'>no-such-host</emphasis>.
+It will not find any entries that match, but along the way will report
+each image it skips.</para>
+</refsect1>
+
+<refsect1><title>CAVEATS</title>
+<para>&gnutar; must be used to restore files from backup images created with
+the GNUTAR dumptype.
+Vendor tar programs sometimes fail to read GNU tar images.</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds;, University of Maryland,
+College Park: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amflush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>tar</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+<citerefentry><refentrytitle>restore</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amrmtape.8.xml b/man/xml-source/amrmtape.8.xml
new file mode 100644 (file)
index 0000000..8cedae2
--- /dev/null
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amrmtape.8'>
+
+<refmeta>
+<refentrytitle>amrmtape</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amrmtape</refname>
+<refpurpose>remove a tape from the &A; database</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amrmtape</command>    
+    <arg choice='opt'>-n </arg>
+    <arg choice='opt'>-v </arg>
+    <arg choice='opt'>-q </arg>
+    <arg choice='opt'>-d </arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>label</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amrmtape</emphasis>
+invalidates the contents of an existing backup tape
+in the configuration database.
+This is meant as a recovery mechanism when a
+good backup is damaged either by faulty hardware or user error,
+e.g. the tape is eaten by the drive or is overwritten.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-n</option></term>
+  <listitem>
+<para>Generate new
+<emphasis remap='I'>tapelist</emphasis>
+and database files with
+<emphasis remap='I'>label</emphasis>
+removed, but leave them in
+<filename>/tmp</filename>
+and do not update the original copies.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-v</option></term>
+  <listitem>
+<para>List backups of hosts and disks that are being discarded.  Enabled by default.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-q</option></term>
+  <listitem>
+<para>Opposite of
+<option>-v</option>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-d</option></term>
+  <listitem>
+<para>Run in debugging mode so all executed commands are shown.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>Remove tape labeled
+<emphasis remap='I'>DAILY034</emphasis>
+from the
+<emphasis remap='I'>DailySet1</emphasis>
+configuration.</para>
+
+<programlisting>
+# amrmtape DailySet1 DAILY034
+</programlisting>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Adrian T. Filipi-Martin <email>atf3r@cs.virginia.edu</email>: Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amstatus.8.xml b/man/xml-source/amstatus.8.xml
new file mode 100644 (file)
index 0000000..010f599
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+
+<refentry id='amstatus.8'>
+
+<refmeta>
+<refentrytitle>amstatus</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amstatus</refname>
+<refpurpose>display the state of an &A; run</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amstatus</command>    
+    <arg choice='opt'>--config </arg>
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'>--file </arg><arg choice='plain'><replaceable>amdumpfile</replaceable></arg></arg>
+    <arg choice='opt'>--summary </arg>
+    <arg choice='opt'>--dumping </arg>
+    <arg choice='opt'>--waitdumping </arg>
+    <arg choice='opt'>--waittaper </arg>
+    <arg choice='opt'>--dumpingtape </arg>
+    <arg choice='opt'>--writingtape </arg>
+    <arg choice='opt'>--finished </arg>
+    <arg choice='opt'>--failed </arg>
+    <arg choice='opt'>--estimate </arg>
+    <arg choice='opt'>--gestimate </arg>
+    <arg choice='opt'>--stats </arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amstatus</emphasis>
+gives the current state of the &A; run specified by the 
+<emphasis remap='I'>config</emphasis>
+configuration.
+If there is no active &A; running, it summarizes the result of the last run.
+It may also be used to summarize the results of a previous run.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<para>All options may be abbreviated to the shortest non-ambiguous sub-string.
+If no options are given, everything is displayed.</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>[--config] config</emphasis></term>
+  <listitem>
+<para>Specify the &A; configuration you want to display the state for.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--file amdumpfile</option></term>
+  <listitem>
+<para>Specify an alternate file instead of the
+<emphasis remap='I'>amdump</emphasis>
+or
+<emphasis remap='I'>amflush</emphasis>
+file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--summary</option></term>
+  <listitem>
+<para>Display a summary of the state of the run.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--dumping</option></term>
+  <listitem>
+<para>Display all partitions that are dumping.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--waitdumping|wdumping</option></term>
+  <listitem>
+<para>Display all partitions that are waiting to be dumped.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--waittaper|wtaper</option></term>
+  <listitem>
+<para>Display all partitions dumped that are waiting to be written to tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--dumpingtape|dtape</option></term>
+  <listitem>
+<para>Display all partitions that are dumping directly to tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--writingtape|wtape</option></term>
+  <listitem>
+<para>Display all partitions that are writing to tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--finished</option></term>
+  <listitem>
+<para>Display all partitions that are dumped and written to tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--failed|error</option></term>
+  <listitem>
+<para>Display all partitions that failed.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--estimate</option></term>
+  <listitem>
+<para>Display all partitions whose estimate is finished.
+Works only during the estimate phase.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--gestimate|gettingestimate</option></term>
+  <listitem>
+<para>Display all partitions whose estimate is not finished.
+Works only during the estimate phase.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--stats|statistics</option></term>
+  <listitem>
+<para>Display statistics about active-time of taper and dumpers.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amcheck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amadmin</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amtape.8.xml b/man/xml-source/amtape.8.xml
new file mode 100644 (file)
index 0000000..ca07bfe
--- /dev/null
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amtape.8'>
+
+<refmeta>
+<refentrytitle>amtape</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amtape</refname>
+<refpurpose>user interface to &A; tape changer controls</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amtape</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='plain'><replaceable>command</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>command</replaceable></arg><arg choice='plain'><replaceable>options</replaceable></arg></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amtape</emphasis>
+performs tape changer control operations.
+It uses the underlying tape changer script defined by the
+<emphasis remap='B'>tpchanger</emphasis>
+option for a particular &A;
+configuration as specified by the
+<emphasis remap='I'>config</emphasis>
+argument.</para>
+
+<para>Tape changers maintain a notion of the
+<emphasis remap='I'>current</emphasis>
+and
+<emphasis remap='I'>next</emphasis>
+slot for each configuration.
+These may or may not correspond to an actual physical state of the device,
+but do tend to minimize searching through the tape storage slots.
+If the desired tape is in the current slot,
+it is likely the next tape needed is in the next slot
+rather than at some random position in the storage slots.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about &A;.</para>
+</refsect1>
+
+<refsect1><title>COMMANDS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='B'>reset</emphasis></term>
+  <listitem>
+<para>Reset the tape changer to a known state.
+The
+<emphasis remap='I'>current</emphasis>
+slot is set to the
+<emphasis remap='I'>first</emphasis>
+slot.
+Other device-specific side effects may occur.
+Some gravity stackers need to be reset to the top position by hand.
+This command notifies &A; the stacker is back in that position.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>eject</emphasis></term>
+  <listitem>
+<para>If a tape is loaded in the drive, it is ejected and returned to the
+slot from which it was loaded.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>clean</emphasis></term>
+  <listitem>
+<para>If a cleaning tape is defined for the changer,
+it is used to clean the drive.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>show</emphasis></term>
+  <listitem>
+<para>Show the contents of all slots.
+This can be slow.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>label</emphasis> <emphasis remap='I'>label</emphasis></term>
+  <listitem>
+<para>Search for and load the &A; tape with label
+<emphasis remap='I'>label</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>taper</emphasis></term>
+  <listitem>
+<para>Perform the
+<emphasis remap='B'>taper</emphasis>
+scan algorithm.
+Load the next tape in the configuration's tape sequence,
+or a fresh tape with a suitable label.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>device</emphasis></term>
+  <listitem>
+<para>Display the name of the current tape device on
+<emphasis remap='I'>stdout</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>current</emphasis></term>
+  <listitem>
+<para>Display the current slot.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>update</emphasis></term>
+  <listitem>
+<para>Update the changer label database, if it has one,
+to match the tapes now available.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot</emphasis> <emphasis remap='I'>slot</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away,
+then load the tape from slot
+<emphasis remap='I'>slot</emphasis>
+and reset
+<emphasis remap='I'>current</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot current</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away,
+then load the tape from the current slot.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot prev</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away,
+then load the tape from the previous slot and reset
+<emphasis remap='I'>current</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot next</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away,
+then load the tape from the next slot and reset
+<emphasis remap='I'>current</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot first</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away,
+then load the tape from the first slot and reset
+<emphasis remap='I'>current</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot last</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away,
+then load the tape from the last slot and reset
+<emphasis remap='I'>current</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>slot advance</emphasis></term>
+  <listitem>
+<para>Eject any tape in the drive and put it away.
+Advance
+<emphasis remap='I'>current</emphasis>
+to the next tape, but do not load it.</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>This is useful with non-gravity stackers to unload the last tape used
+and set up &A; for the next run.
+If you just use
+<emphasis remap='B'>eject</emphasis>,
+the current tape will be mounted again in the next run,
+where it will be rejected as being still in use,
+ejected and the next tape requested.
+Using
+<emphasis remap='B'>slot next</emphasis>
+followed by
+<emphasis remap='B'>eject</emphasis>
+does an unnecessary mount.</para>
+
+<para>Note: most changers optimize the
+<emphasis remap='B'>slot</emphasis>
+commands to not eject the loaded tape if it is the one being requested.</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>James da Silva, &email.jds; : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amtapetype.8.xml b/man/xml-source/amtapetype.8.xml
new file mode 100644 (file)
index 0000000..6af7479
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amtapetype.8'>
+
+<refmeta>
+<refentrytitle>amtapetype</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amtapetype</refname>
+<refpurpose>generate a tapetype definition.</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amtapetype</command>    
+    <arg choice='opt'>-h </arg>
+    <arg choice='opt'>-c </arg>
+    <arg choice='opt'>-o </arg>
+    <arg choice='opt'>-b <replaceable>blocksize</replaceable></arg>
+    <arg choice='opt'>-e <replaceable>estsize</replaceable></arg>
+    <arg choice='opt'>-f <replaceable>tapedev</replaceable></arg>
+    <arg choice='opt'>-t <replaceable>typename</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>amtapetype</emphasis>
+generates a tapetype entry for &A;.</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-h</option></term>
+  <listitem>
+<para>Display an help message.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-c</option></term>
+  <listitem>
+<para>Run only the hardware compression detection heuristic test and stop.
+This takes a few minutes only.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-o</option></term>
+  <listitem>
+<para>Overwrite the tape, even if it's an &A; tape.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-b</option><replaceable> blocksize</replaceable></term>
+  <listitem>
+<para>record block size (default: 32k)</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-e</option><replaceable> estsize</replaceable></term>
+  <listitem>
+<para>estimated tape size (default: 1g == 1024m)</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-f</option><replaceable> tapedev</replaceable></term>
+  <listitem>
+<para>tape device name (default: $TAPE)
+The device to perform the test.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-t</option><replaceable> typename</replaceable></term>
+  <listitem>
+<para>tapetype name (default: unknown-tapetype)</para>
+<!-- .PD -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>EXAMPLE</title>
+<para>Generate a tapetype definition for your tape device:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+% amtapetype -f /dev/nst0
+</literallayout></refsect1>
+
+<refsect1><title>NOTES</title>
+<para>Hardware compression is detected by measuring
+the writing speed difference of the tape drive
+when writing an amount of compressable and uncompresseable data.
+It does not rely on the status bits of the tape drive or the OS parameters.
+If your tape drive has very large buffers or is very fast, the program
+could fail to detect hardware compression status reliably.</para>
+
+<para>During the first pass, it writes files that are estimated to be 1%
+of the expected tape capacity.  It gets the expected capacity from
+the -e command line flag, or defaults to 1 GByte.  In a perfect world
+(which means there is zero chance of this happening with tapes :-),
+there would be 100 files and 100 file marks.</para>
+
+<para>During the second pass, the file size is cut in half.  In that same
+fairyland world, this means 200 files and 200 file marks.</para>
+
+<para>In both passes the total amount of data written is summed as well as the
+number of file marks written.  At the end of the second pass, quoting
+from the code:</para>
+
+<para>* Compute the size of a filemark as the difference in data written
+between pass 1 and pass 2 divided by the difference in number of
+file marks written between pass 1 and pass 2. ... *</para>
+
+<para>So if we wrote 1.0 GBytes on the first pass and 100 file marks, and
+0.9 GBytes on the second pass with 200 file marks, those additional 100
+file marks in the second pass took 0.1 GBytes and therefor a file mark
+is 0.001 GBytes (1 MByte).</para>
+
+<para>Note that if the estimated capacity is wrong, the only thing that happens
+is a lot more (or less, but unlikely) files, and thus, file marks,
+get written.  But the math still works out the same.  The -e flag is
+there to keep the number of file marks down because they can be slow
+(since they force the drive to flush all its buffers to physical media).</para>
+
+<para>All sorts of things might happen to cause the amount of data
+written to vary enough to generate a big file mark size guess.  A little
+more &quot;shoe shining&quot; because of the additional file marks (and flushes),
+dirt left on the heads from the first pass of a brand new tape, the
+temperature/humidity changed during the multi-hour run, a different amount
+of data was written after the last file mark before EOT was reported, etc.</para>
+
+<para>Note that the file mark size might really be zero for whatever device this
+is, and it was just the measured capacity variation that caused &amtapetype;
+to think those extra file marks in pass 2 actually took up space.</para>
+
+<para>It also explains why &amtapetype; used to sometimes report a negative file
+mark size if the math happened to end up that way.  When that happens
+now we just report it as zero.</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amtoc.8.xml b/man/xml-source/amtoc.8.xml
new file mode 100644 (file)
index 0000000..66b3196
--- /dev/null
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amtoc.8'>
+<refmeta>
+<refentrytitle>amtoc</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amtoc</refname>
+<refpurpose>generate TOC (Table Of Contents) for an &A; run</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amtoc</command>    
+    <arg choice='opt'>-a </arg>
+    <arg choice='opt'>-i </arg>
+    <arg choice='opt'>-t </arg>
+    <arg choice='opt'><arg choice='plain'>-f </arg><arg choice='plain'><replaceable>file</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>-s </arg><arg choice='plain'><replaceable>subs</replaceable></arg></arg>
+    <arg choice='opt'>-w </arg>
+    <arg choice='opt'>-- </arg>
+    <arg choice='plain'><replaceable>logfile</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='I'>Amtoc</emphasis>
+generates a table of contents for an &A; run.
+It's a perl script (if you don't have perl, install it first!).</para>
+</refsect1>
+
+<refsect1><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>-a</option></term>
+  <listitem>
+<para>The output file name will be
+<emphasis remap='I'>label-of-the-tape</emphasis>.toc
+in the same directory as
+<emphasis remap='I'>logfile</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-i</option></term>
+  <listitem>
+<para>Display help about
+<command>amtoc</command>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-t</option></term>
+  <listitem>
+<para>Generate the output in tabular form.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-f file</option></term>
+  <listitem>
+<para>Write the output to a file ('-' for stdout).</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-s subs</option></term>
+  <listitem>
+<para>Evaluate the output file name from
+<emphasis remap='I'>subs</emphasis>,
+with $_ set to
+<emphasis remap='I'>label-of-the-tape</emphasis>.
+The
+<option>-a</option>
+option is equivalent to
+<option>-s</option>
+<replaceable>'s/$_/.toc/'</replaceable>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>-w</option></term>
+  <listitem>
+<para>Separate tapes with form-feeds and display blank lines before totals.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--</option></term>
+  <listitem>
+<para>Marks the last option so the next parameter is the
+<emphasis remap='I'>logfile</emphasis>.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><emphasis remap='B'>logfile</emphasis></term>
+  <listitem>
+<para>(use '-' for stdin)</para>
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>OUTPUT FORMAT</title>
+<para>The standard output has five fields separated by two spaces:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+#  Server:/partition  date  level  size[Kb]
+0  daily-05:  19991005  -  -
+1  cuisun15:/cuisun15/home  19991005  1  96
+2  cuinfs:/export/dentiste  19991005  1  96
+  ...
+103  cuisg11:/  19991005  0  4139136
+103  total:  -  -  16716288
+<!-- .RE -->
+
+</literallayout><para>In tabular format (-t), this would look like:</para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+  #  Server:/partition           date      lev  size[Kb]
+  0  daily-05:                   19991005    -         -
+  1  cuisun15:/cuisun15/home     19991005    1        96
+  2  cuinfs:/export/dentiste     19991005    1        96
+  ...
+103  cuisg11:/                   19991005    0   4139136
+103  total:                      -           -  16716288
+<!-- .RE -->
+</literallayout></refsect1>
+
+<refsect1><title>USAGE</title>
+<para>The easiest way to use it is to run
+<command>amtoc</command>
+right after
+<emphasis remap='I'>amdump</emphasis>
+in the
+<emphasis remap='I'>cron job:</emphasis></para>
+
+<!-- .RS -->
+<literallayout remap='.nf'>
+amdump daily ; logdir=`amgetconf daily logdir` ; log=`ls -1t $logdir/log.*.[0-9] | head -1` ; amtoc -a $log
+</literallayout> <!-- .fi -->
+
+<para>which will generate /usr/local/etc/amanda//daily/<emphasis remap='I'>tape_label</emphasis>.toc.
+You may also want to call
+<command>amtoc</command>
+after an
+<emphasis remap='I'>amflush</emphasis>.</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amdump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amflush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amgetconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+cron,
+perl</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Nicolas Mayencourt <email>Nicolas.Mayencourt@cui.unige.ch</email>, University of Geneva/Switzerland : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amverify.8.xml b/man/xml-source/amverify.8.xml
new file mode 100644 (file)
index 0000000..5667381
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amverify.8'>
+
+<refmeta>
+<refentrytitle>amverify</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amverify</refname>
+<refpurpose>check an Amanda tape for errors</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amverify</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'><replaceable>slot</replaceable></arg><arg choice='opt'><replaceable>runtapes</replaceable></arg></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amverify</emphasis>
+reads an Amanda format tape and makes sure each backup image
+can be processed by
+<emphasis remap='B'>amrestore</emphasis>
+and, if possible, the appropriate restore program (e.g.
+<emphasis remap='B'>tar</emphasis>).</para>
+
+<para><emphasis remap='B'>Amverify</emphasis>
+runs
+<emphasis remap='B'>amrestore</emphasis>
+on each file of the tape and pipes the output
+to a restore program (if available) with an option to create a catalogue
+of the backup.
+The catalogue itself is discarded.
+Only the success or failure of the operation itself is reported.</para>
+
+<para>If the backup image cannot be processed by the restore program,
+e.g. if it was written on a different operating system,
+the image is sent through
+<emphasis remap='B'>dd</emphasis>
+to /dev/null.
+This still determines if the tape is readable,
+but does not do any internal consistency check on the image.</para>
+
+<para>If
+<emphasis remap='I'>config</emphasis>
+is set up to use a tape changer,
+the
+<emphasis remap='I'>slot</emphasis>
+argument may be used to choose the first tape to process.
+Otherwise,
+the
+<emphasis remap='B'>current</emphasis>
+slot is used.</para>
+
+<para>The
+<emphasis remap='B'>runtapes</emphasis>
+configuration parameter determines how many tapes are processed unless
+it is specified on the command line.</para>
+
+<para>See the
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+man page for more details about Amanda.</para>
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>Axel Zinser <email>fifi@icem.de</email> : Original text</para>
+<para>&maintainer.sgw;: XML-conversion</para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amrestore</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amverifyrun</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xml-source/amverifyrun.8.xml b/man/xml-source/amverifyrun.8.xml
new file mode 100644 (file)
index 0000000..69d23ca
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+  <!-- entities files to use -->
+  <!ENTITY % global_entities SYSTEM '../entities/global.entities'>
+  %global_entities;
+]>
+
+<!-- lifted from troff+man by doclifter -->
+<refentry id='amverifyrun.8'>
+<refmeta>
+<refentrytitle>amverifyrun</refentrytitle>
+<manvolnum>8</manvolnum>
+</refmeta>
+<refnamediv>
+<refname>amverifyrun</refname>
+<refpurpose>check the tapes written by the last &A; run</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv>
+<cmdsynopsis>
+  <command>amverifyrun</command>    
+    <arg choice='plain'><replaceable>config</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1><title>DESCRIPTION</title>
+<para><emphasis remap='B'>Amverifyrun</emphasis>
+read the log from the last &A; run to find the slot of the first tape
+used and the number of tapes used.
+It call
+<emphasis remap='B'>amverify</emphasis>
+with these argument.</para>
+
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>amanda</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>amverify</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+</refentry>
+
diff --git a/man/xslt/expand-sambadoc.xsl b/man/xslt/expand-sambadoc.xsl
new file mode 100644 (file)
index 0000000..848502c
--- /dev/null
@@ -0,0 +1,507 @@
+<?xml version='1.0'?>
+<!-- 
+       Samba-documentation specific stylesheets
+       Published under the GNU GPL
+
+       (C) Jelmer Vernooij                                     2002-2004
+       (C) Alexander Bokovoy                                   2002-2004
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+       xmlns:exsl="http://exslt.org/common"
+       xmlns:samba="http://samba.org/common"
+       version="1.1"
+       extension-element-prefixes="exsl">
+
+       <xsl:import href="../settings.xsl"/>
+
+       <xsl:output method="xml" encoding="UTF-8" doctype-public="-//OASIS//DTD DocBook XML V4.2//EN" indent="yes" doctype-system="http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"/>
+
+       <xsl:param name="xmlSambaNsUri" select="'http://samba.org/common'"/>
+
+       <xsl:template match="reference/refentry/refsect1">
+               <xsl:if test="title!='VERSION' and title!='AUTHOR'">
+                       <xsl:element name="refsect1">
+                               <xsl:if test="@id!=''">
+                                       <xsl:attribute name="id">
+                                               <xsl:value-of select="@id"/>
+                                       </xsl:attribute>
+                               </xsl:if>
+                               <xsl:apply-templates/>                  
+                       </xsl:element>
+               </xsl:if>
+       </xsl:template>
+
+       <xsl:template match="translator">
+               <xsl:element name="othercredit">
+                       <xsl:element name="author">
+                               <xsl:apply-templates/>
+                               <xsl:element name="contrib">
+                                       <xsl:text>Translation to </xsl:text><xsl:value-of select="@lang"/>
+                               </xsl:element>
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="reference/refentry">
+               <xsl:element name="section">
+                       <xsl:attribute name="id">
+                               <xsl:value-of select="@id"/>
+                       </xsl:attribute>
+                       <xsl:element name="title">
+                               <xsl:value-of select="refmeta/refentrytitle"/>
+                               <!--                    <xsl:text> (</xsl:text>
+                               <xsl:value-of select="refnamediv/refpurpose"/>
+                               <xsl:text>)</xsl:text>-->
+                       </xsl:element>
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="reference/refentry/refmeta"/>
+
+       <xsl:template match="reference/refentry/refnamediv"/>
+
+       <xsl:template match="reference">
+               <xsl:element name="appendix">
+                       <xsl:attribute name="id">
+                               <xsl:value-of select="@id"/>
+                       </xsl:attribute>
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+
+       <!-- This is needed to copy content unchanged -->
+       <xsl:template match="@*|node()">
+               <xsl:copy>
+                       <xsl:apply-templates select="@*|node()"/>
+               </xsl:copy>
+       </xsl:template>
+
+       <xsl:template match="amconfexample/amconfoption|amconfblock/amconfoption">
+
+               <xsl:element name="member">
+                       <xsl:element name="indexterm">
+                               <xsl:element name="primary">
+                                       <xsl:value-of select="name"/>
+                               </xsl:element>
+                       </xsl:element>
+                       <xsl:element name="parameter">
+                               <xsl:text disable-output-escaping="yes">
+                                       &lt;?latex \hspace{1cm} ?&gt;
+                               </xsl:text>
+                               <xsl:value-of select="name"/>
+                               <xsl:choose>
+                                       <xsl:when test="value != ''">
+                                               <xsl:text> = </xsl:text>
+                                               <xsl:value-of select="value"/>
+                                       </xsl:when>
+                               </xsl:choose>
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfexample/amconfoption|amconfblock/amconfcomment">
+               <xsl:text disable-output-escaping="yes">
+                       &lt;?latex \hspace{1cm} ?&gt;
+               </xsl:text>
+               <xsl:element name="member">
+                       <xsl:text># </xsl:text>
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfexample/amconfoption|amconfblock/amconfsection">
+               <xsl:element name="member">
+                       <xsl:text> </xsl:text>
+               </xsl:element>
+               <xsl:element name="member">
+                       <xsl:element name="parameter">
+                               <xsl:apply-templates/>
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfoption">
+               <!-- Include an index term -->
+               <xsl:element name="indexterm">
+                       <xsl:element name="primary">
+                               <xsl:value-of select="name"/>
+                       </xsl:element>
+               </xsl:element>
+
+               <xsl:variable name="linkcontent">
+                       <xsl:element name="parameter">
+                               <xsl:attribute name="moreinfo">
+                                       <xsl:text>none</xsl:text>
+                               </xsl:attribute>
+                               <xsl:value-of select="name"/>   
+                       </xsl:element>
+
+                       <xsl:choose>
+                               <xsl:when test="value != ''">
+                                       <xsl:text> = </xsl:text>
+                                       <xsl:value-of select="value"/>
+                               </xsl:when>
+                       </xsl:choose>
+               </xsl:variable>
+
+               <xsl:choose>
+                       <xsl:when test="$noreference = 1">
+                               <xsl:value-of select="$linkcontent"/>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <xsl:element name="link">
+                                       <xsl:attribute name="linkend">
+                                               <xsl:value-of select="translate(translate(string(name),' ',''),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
+                                       </xsl:attribute>
+                                       <xsl:value-of select="$linkcontent"/>
+                               </xsl:element>
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+
+       <!-- FIXME: Needs extension sometime -->
+       <xsl:template match="ntgroup|ntuser">
+               <xsl:element name="emphasis">
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfexample">
+               <xsl:choose>
+                       <xsl:when test="title = ''">
+                               <xsl:message>
+                                       <xsl:text>Warning: amconfexample does not have title!</xsl:text>
+                               </xsl:message>
+                       </xsl:when>
+               </xsl:choose>
+               <xsl:element name="example">
+                       <xsl:choose>
+                               <xsl:when test="@id != ''">
+                                       <xsl:attribute name="id">
+                                               <xsl:value-of select="@id"/>
+                                       </xsl:attribute>
+                               </xsl:when>
+                       </xsl:choose>
+
+                       <xsl:element name="title">
+                               <xsl:value-of select="title"/>
+                       </xsl:element>
+                       <xsl:element name="simplelist">
+                               <xsl:apply-templates/>
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfexample/title">
+       </xsl:template>
+
+       <xsl:template match="amconfblock">
+               <xsl:element name="simplelist">
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfsection">
+               <xsl:element name="parameter">
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="amconfcomment">
+               <xsl:text># </xsl:text>
+               <xsl:apply-templates/>
+       </xsl:template>
+
+       <xsl:template match="smbfile">
+               <xsl:apply-templates/>
+       </xsl:template>
+
+       <xsl:template match="image">
+               <xsl:element name="figure">
+                       <xsl:attribute name="id">
+                               <xsl:choose>
+                                       <xsl:when test="@id != ''">
+                                               <xsl:value-of select="@id"/>
+                                       </xsl:when>
+                                       <xsl:otherwise>
+                                               <xsl:value-of select="imagefile"/>
+                                       </xsl:otherwise>
+                               </xsl:choose>
+                       </xsl:attribute>
+
+                       <xsl:element name="title">
+                               <xsl:value-of select="imagedescription"/>
+                       </xsl:element>
+                       <xsl:element name="mediaobject">
+                               <xsl:element name="imageobject">
+                                       <xsl:attribute name="role"><xsl:text>latex</xsl:text></xsl:attribute>
+                                       <xsl:element name="imagedata">
+                                               <xsl:attribute name="fileref">
+                                                       <xsl:value-of select="$imagedir"/><xsl:value-of select="imagefile"/></xsl:attribute>
+                                               <xsl:attribute name="scale">
+                                                       <xsl:choose>
+                                                               <xsl:when test="@scale != ''">
+                                                                       <xsl:value-of select="@scale"/>
+                                                               </xsl:when>
+
+                                                               <xsl:otherwise>
+                                                                       <xsl:text>50</xsl:text>
+                                                               </xsl:otherwise>
+                                                       </xsl:choose>
+                                               </xsl:attribute>
+                                               <xsl:attribute name="scalefit"><xsl:text>1</xsl:text></xsl:attribute>
+                                       </xsl:element>
+                               </xsl:element>
+                               <xsl:element name="imageobject">
+                                       <xsl:attribute name="role"><xsl:text>html</xsl:text></xsl:attribute>
+                                       <xsl:element name="imagedata">
+                                               <xsl:attribute name="fileref">
+                                                       <xsl:text>images/</xsl:text><xsl:value-of select="imagefile"/><xsl:text>.png</xsl:text></xsl:attribute>
+                                               <xsl:attribute name="scale"><xsl:text>50</xsl:text></xsl:attribute>
+                                               <xsl:attribute name="scalefit"><xsl:text>1</xsl:text></xsl:attribute>
+                                       </xsl:element>
+                               </xsl:element>
+                               <xsl:element name="imageobject">
+                                       <xsl:element name="imagedata">
+                                               <xsl:attribute name="fileref">
+                                                       <xsl:text>images/</xsl:text><xsl:value-of select="imagefile"/><xsl:text>.png</xsl:text></xsl:attribute>
+                                               <xsl:attribute name="scale"><xsl:text>50</xsl:text></xsl:attribute>
+                                               <xsl:attribute name="scalefit"><xsl:text>1</xsl:text></xsl:attribute>
+                                       </xsl:element>
+                               </xsl:element>
+
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="description"><xsl:apply-templates/></xsl:template>
+
+       <xsl:template match="value"><xsl:apply-templates/></xsl:template>
+
+       <xsl:template match="synonym"><xsl:apply-templates/></xsl:template>
+
+       <xsl:template match="related"><xsl:apply-templates/></xsl:template>
+
+       <xsl:template match="filterline">
+               <xsl:element name="programlisting">
+                       <xsl:apply-templates/>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="//samba:parameterlist">
+               <xsl:apply-templates>
+                       <xsl:sort select="varlistentry/term/anchor"/>
+               </xsl:apply-templates>
+       </xsl:template>
+
+       <xsl:template match="value/comment">
+               <xsl:text>&#10;# </xsl:text>
+               <xsl:apply-templates/>
+       </xsl:template>
+
+       <xsl:template match="//samba:parameter">
+               <!-- reconstruct varlistentry - not all of them will go into separate files
+               and also we must repair the main varlistentry itself.
+               -->
+               <xsl:variable name="cname"><xsl:value-of select="translate(translate(string(@name),' ',''),
+                               'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
+               </xsl:variable>
+
+               <xsl:variable name="name"><xsl:value-of select="@name"/></xsl:variable>
+
+               <xsl:variable name="anchor">
+                       <xsl:element name="anchor">
+                               <xsl:attribute name="id">
+                                       <xsl:value-of select="$cname"/>
+                               </xsl:attribute>
+                       </xsl:element>
+               </xsl:variable>
+
+               <xsl:variable name="context">
+                       <xsl:text> (</xsl:text>
+                       <xsl:value-of select="@context"/>
+                       <xsl:text>)</xsl:text>
+               </xsl:variable>
+
+               <xsl:variable name="term">
+                       <xsl:element name="term">
+                               <xsl:copy-of select="$anchor"/>
+                               <xsl:value-of select="@name"/>
+                               <xsl:value-of select="$context"/>
+                       </xsl:element>
+               </xsl:variable>
+
+
+               <!-- Generate list of examples -->
+               <xsl:variable name="examples">
+                       <xsl:for-each select="value">
+                               <xsl:if test="@type = 'example'">
+                                       <xsl:element name="para">
+                                               <xsl:text>Example: </xsl:text>
+                                               <xsl:element name="emphasis">
+                                                       <xsl:element name="parameter">
+                                                               <xsl:copy-of select="$name"/>
+                                                       </xsl:element>
+                                                       <xsl:text> = </xsl:text>
+                                                       <xsl:apply-templates select="."/>
+                                                       <xsl:text>&#10;</xsl:text>
+                                               </xsl:element>
+                                               <xsl:text>&#10;</xsl:text>
+                                       </xsl:element>
+                               </xsl:if>
+                       </xsl:for-each>
+               </xsl:variable>
+
+               <xsl:variable name="tdefault">
+                       <xsl:for-each select="value">
+                               <xsl:if test="@type = 'default'">
+                                       <xsl:element name="para">
+                                               <xsl:text>Default: </xsl:text>
+                                               <xsl:element name="emphasis">
+                                                       <xsl:element name="parameter">
+                                                               <xsl:copy-of select="$name"/>
+                                                       </xsl:element>
+                                                       <xsl:text> = </xsl:text>
+                                                       <xsl:apply-templates select="."/>
+                                                       <xsl:text>&#10;</xsl:text>
+                                               </xsl:element>
+                                               <xsl:text>&#10;</xsl:text>
+                                       </xsl:element>
+                               </xsl:if>
+                       </xsl:for-each>
+               </xsl:variable>
+
+               <xsl:variable name="default">
+                       <xsl:choose>
+                               <xsl:when test="$tdefault = ''">
+                                       <xsl:element name="para">
+                                               <xsl:element name="emphasis">
+                                                       <xsl:text>No default</xsl:text>
+                                               </xsl:element>  
+                                       </xsl:element>
+                               </xsl:when>
+                               <xsl:otherwise>
+                                       <xsl:copy-of select="$tdefault"/>
+                               </xsl:otherwise>
+                       </xsl:choose>
+               </xsl:variable>
+
+               <xsl:variable name="content">
+                       <xsl:apply-templates select="description"/>
+               </xsl:variable>
+
+               <xsl:for-each select="synonym">
+                       <xsl:element name="varlistentry">
+                               <xsl:text>&#10;</xsl:text>     
+                               <xsl:element name="indexterm">
+                                       <xsl:attribute name="significance">
+                                               <xsl:text>preferred</xsl:text>
+                                       </xsl:attribute>
+                                       <xsl:element name="primary">
+                                               <xsl:value-of select="."/>
+                                       </xsl:element>
+                                       <xsl:element name="see">
+                                               <xsl:value-of select="$name"/>
+                                       </xsl:element>
+                               </xsl:element>
+
+                               <xsl:element name="term">
+                                       <xsl:element name="anchor">
+                                               <xsl:attribute name="id">
+                                                       <xsl:value-of select="translate(translate(string(.),' ',''), 'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
+                                               </xsl:attribute>
+                                       </xsl:element>
+                                       <xsl:value-of select="."/>
+                               </xsl:element>
+
+                               <xsl:element name="listitem">
+                                       <xsl:element name="para"><xsl:text>This parameter is a synonym for </xsl:text><xsl:copy-of select="$name"/><xsl:text>.</xsl:text></xsl:element>
+                               </xsl:element>
+                       </xsl:element>
+               </xsl:for-each>
+
+               <xsl:element name="varlistentry">
+                       <xsl:text>&#10;</xsl:text>     
+                       <xsl:element name="indexterm">
+                               <xsl:attribute name="significance">
+                                       <xsl:text>preferred</xsl:text>
+                               </xsl:attribute>
+                               <xsl:element name="primary">
+                                       <xsl:value-of select="@name"/>
+                               </xsl:element>
+                       </xsl:element>
+                       <xsl:copy-of select="$term"/>
+                       <xsl:element name="listitem">
+                               <xsl:copy-of select="$content"/> <xsl:text>&#10;</xsl:text>     
+                               <xsl:copy-of select="$default"/> <xsl:text>&#10;</xsl:text>     
+                               <xsl:copy-of select="$examples"/> <xsl:text>&#10;</xsl:text>     
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <xsl:template match="ulink">
+               <xsl:element name="ulink">
+                       <xsl:attribute name="url">
+                               <xsl:value-of select="@url"/>
+                       </xsl:attribute>
+
+                       <xsl:apply-templates/>
+                       <xsl:if test="contains(@url,'http://') or contains(@url,'ftp://')">
+                               <xsl:if test="$duplicate_ulinks='brackets'">
+                                       <xsl:text> (</xsl:text>
+                                       <xsl:value-of select="@url"/>
+                                       <xsl:text>)</xsl:text>
+                               </xsl:if>
+                               <xsl:if test="$duplicate_ulinks='footnote'">
+                                       <xsl:element name="footnote">
+                                               <xsl:element name="para">
+                                                       <xsl:value-of select="@url"/>
+                                               </xsl:element>
+                                       </xsl:element>
+                               </xsl:if>
+                       </xsl:if>
+               </xsl:element>
+       </xsl:template>
+
+       <!-- Just ignore these -->
+       <xsl:template match="smbfile">
+               <xsl:apply-templates/>
+       </xsl:template>
+
+       <xsl:template match="quote">
+               <xsl:element name="quote">
+                       <xsl:element name="emphasis">
+                               <xsl:apply-templates/>
+                       </xsl:element>
+               </xsl:element>
+       </xsl:template>
+
+       <!-- New chapter-template for displaying html-urls -->
+
+
+<xsl:template match="chapter">
+       <xsl:copy>
+               <xsl:element name="para">
+               <xsl:element name="note">
+                       <xsl:text>Refer to </xsl:text>
+                       <xsl:element name="ulink">
+                               <xsl:attribute name="url">
+                                       <xsl:text>http://www.amanda.org/docs/</xsl:text>
+                                       <xsl:value-of select="@id"/>
+                                       <xsl:text>.html</xsl:text>
+                               </xsl:attribute>
+                               <xsl:text>http://www.amanda.org/docs/</xsl:text>
+                               <xsl:value-of select="@id"/>
+                               <xsl:text>.html</xsl:text>
+                       </xsl:element>
+                       <xsl:text> for the current version of this
+                       document.</xsl:text>
+               </xsl:element>
+               </xsl:element>
+               <xsl:apply-templates select="@*|node()"/>
+       </xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/man/xslt/man.xsl b/man/xslt/man.xsl
new file mode 100644 (file)
index 0000000..f7a7d4e
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version='1.0'?>
+<!-- vim:set sts=2 shiftwidth=2 syntax=xml: -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'>
+
+<xsl:import href="settings.xsl"/>
+
+<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"/>
+
+<xsl:param name="chunk.section.depth" select="0"/>
+<xsl:param name="chunk.first.sections" select="1"/>
+<xsl:param name="use.id.as.filename" select="1"/>
+
+<!-- 
+    Our ulink stylesheet omits @url part if content was specified
+-->
+<xsl:template match="ulink">
+  <xsl:variable name="content">
+    <xsl:apply-templates/>
+  </xsl:variable>
+  <xsl:if test="$content = ''">
+    <xsl:text>: </xsl:text>
+  </xsl:if>
+  <xsl:if test="$content != ''">
+    <xsl:value-of select="$content" />
+  </xsl:if>
+  <xsl:if test="$content = ''">
+    <xsl:apply-templates mode="italic" select="@url" />
+  </xsl:if>
+</xsl:template>
+
+<xsl:template match="refentry">
+
+  <xsl:variable name="section" select="refmeta/manvolnum"/>
+  <xsl:variable name="name" select="refnamediv/refname[1]"/>
+  <xsl:variable name="base.dir" select="$base.dir"/>
+  <!-- standard man page width is 64 chars; 6 chars needed for the two
+       (x) volume numbers, and 2 spaces, leaves 56 -->
+  <xsl:variable name="twidth" select="(74 - string-length(refmeta/refentrytitle)) div 2"/>
+
+  <xsl:variable name="reftitle" 
+               select="substring(refmeta/refentrytitle, 1, $twidth)"/>
+
+  <xsl:variable name="title">
+    <xsl:choose>
+      <xsl:when test="refentryinfo/title">
+        <xsl:value-of select="refentryinfo/title"/>
+      </xsl:when>
+      <xsl:when test="../referenceinfo/title">
+        <xsl:value-of select="../referenceinfo/title"/>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:variable name="date">
+    <xsl:choose>
+      <xsl:when test="refentryinfo/date">
+        <xsl:value-of select="refentryinfo/date"/>
+      </xsl:when>
+      <xsl:when test="../referenceinfo/date">
+        <xsl:value-of select="../referenceinfo/date"/>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:variable name="productname">
+    <xsl:choose>
+      <xsl:when test="refentryinfo/productname">
+        <xsl:value-of select="refentryinfo/productname"/>
+      </xsl:when>
+      <xsl:when test="../referenceinfo/productname">
+        <xsl:value-of select="../referenceinfo/productname"/>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:call-template name="write.text.chunk">
+    <xsl:with-param name="filename"
+                   select="concat($base.dir, normalize-space ($name), '.', $section)"/>
+    <xsl:with-param name="content">
+      <xsl:text>.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "</xsl:text>
+      <xsl:value-of select="translate($reftitle,'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
+      <xsl:text>" </xsl:text>
+      <xsl:value-of select="refmeta/manvolnum[1]"/>
+      <xsl:text> "</xsl:text>
+      <xsl:value-of select="normalize-space($date)"/>
+      <xsl:text>" "</xsl:text>
+      <xsl:value-of select="normalize-space($productname)"/>
+      <xsl:text>" "</xsl:text>
+      <xsl:value-of select="$title"/>
+      <xsl:text>"
+</xsl:text>
+      <xsl:apply-templates/>
+      <xsl:text>&#10;</xsl:text>
+
+      <!-- Author section -->
+      <xsl:choose>
+        <xsl:when test="refentryinfo//author">
+          <xsl:apply-templates select="refentryinfo" mode="authorsect"/>
+        </xsl:when>
+      </xsl:choose>
+    </xsl:with-param>
+  </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="informalexample|screen|programlisting">
+  <xsl:text>.nf&#10;</xsl:text>
+  <xsl:apply-templates/>
+  <xsl:text>.fi&#10;</xsl:text>
+</xsl:template>
+
+<xsl:template match="//emphasis">
+  <xsl:text>\fB</xsl:text>
+  <xsl:apply-templates/>
+  <xsl:text>\fR</xsl:text>
+</xsl:template>
+
+<xsl:template match="para|simpara|remark" mode="list">
+  <xsl:variable name="foo">
+    <xsl:apply-templates/>
+  </xsl:variable>
+  <xsl:choose match="node()">
+    <!-- Don't normalize-space() for verbatim paragraphs        -->
+    <xsl:when test="informalexample|screen|programlisting">
+      <xsl:value-of select="$foo"/>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="normalize-space($foo)"/>
+      <xsl:text>&#10;</xsl:text>
+    </xsl:otherwise>
+  </xsl:choose>
+  <xsl:text>&#10;</xsl:text>
+  <xsl:if test="following-sibling::para or following-sibling::simpara or
+               following-sibling::remark">
+    <!-- Make sure multiple paragraphs within a list item don't -->
+    <!-- merge together.                                        -->
+    <xsl:text>&#10;</xsl:text>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template match="refsect3">
+  <xsl:text>&#10;.SS "</xsl:text>
+  <xsl:value-of select="title[1]"/>
+  <xsl:text>"&#10;</xsl:text>
+  <xsl:apply-templates/>
+</xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/man/xslt/settings.xsl b/man/xslt/settings.xsl
new file mode 100644 (file)
index 0000000..054ee47
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:exsl="http://exslt.org/common"
+                xmlns:samba="http://samba.org/common"
+                               version="1.1">
+
+<xsl:param name="papersize"><xsl:text>a4paper</xsl:text></xsl:param>
+<xsl:param name="docrop"><xsl:text>0</xsl:text></xsl:param>
+<xsl:param name="duplicate_ulinks"><xsl:text></xsl:text></xsl:param>
+<xsl:param name="fontsize"><xsl:text>10.5</xsl:text></xsl:param>
+</xsl:stylesheet>
index 0a554da48d69106dc1f624e6541744afe64ac4f4..a1631da29184df5ba9b159c90e86c898da5f4a3f 100644 (file)
@@ -8,6 +8,8 @@ The others fix an estimate problem in GNUTAR on SunOS 4.1.3, HP/UX and
 other systems whose C libraries do not support "%lld" in printf format
 strings for printing long long integers.
 
+Patch follows.
+
 --- tar-1.12/src/create.c      Mon Dec 15 17:26:47 1997
 +++ tar-1.12/src/create.c      Mon Dec 15 17:50:48 1997
 @@ -1048,7 +1048,7 @@
index 042feba69cd943d5a8dd4fa89e9aaa967013ad06..364f6dedbc6b784b8e52cab24657060f6fff4f35 100644 (file)
@@ -1,7 +1,9 @@
 # Makefile for Amanda file recovery programs.
 
-INCLUDES =             -I$(top_srcdir)/common-src -I$(top_srcdir)/client-src \
-                       -I$(top_srcdir)/tape-src
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/client-src   \
+               -I$(top_srcdir)/tape-src
 
 LIB_EXTENSION = la
 
@@ -20,8 +22,11 @@ endif
 
 LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
        @LEXLIB@ \
-       ../client-src/libamclient.$(LIB_EXTENSION) \
-       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../client-src/libamclient.$(LIB_EXTENSION)
+if WANT_SERVER
+LDADD += ../tape-src/libamtape.$(LIB_EXTENSION)
+endif
+LDADD += ../common-src/libamanda.$(LIB_EXTENSION) \
        $(READLINE_LIBS)
 
 amrecover_SOURCES =    amrecover.c                                     \
@@ -47,4 +52,4 @@ install-exec-hook:
 
 # so that uscan.c is never generated before uparse.h
 # otherwise we might have makedepend problems
-$(srcdir)/uscan.c: $(srcdir)/uparse.h
+uscan.c: uparse.h
index 167f607716f0b4bce8375807d1a41963e5903202..0d8d213f1709554fbf3be8b3f988da7542869481 100644 (file)
@@ -43,6 +43,7 @@ build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
 sbin_PROGRAMS = amrecover$(EXEEXT)
+@WANT_SERVER_TRUE@am__append_1 = ../tape-src/libamtape.$(LIB_EXTENSION)
 subdir = recover-src
 DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in uparse.c uparse.h uscan.c
@@ -62,10 +63,13 @@ am_amrecover_OBJECTS = amrecover.$(OBJEXT) display_commands.$(OBJEXT) \
        uparse.$(OBJEXT) uscan.$(OBJEXT)
 amrecover_OBJECTS = $(am_amrecover_OBJECTS)
 amrecover_LDADD = $(LDADD)
-am__DEPENDENCIES_1 =
+@WANT_SERVER_TRUE@am__DEPENDENCIES_1 =  \
+@WANT_SERVER_TRUE@     ../tape-src/libamtape.$(LIB_EXTENSION)
+am__DEPENDENCIES_2 =
 amrecover_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        ../client-src/libamclient.$(LIB_EXTENSION) \
-       ../common-src/libamanda.$(LIB_EXTENSION) $(am__DEPENDENCIES_1)
+       $(am__DEPENDENCIES_1) ../common-src/libamanda.$(LIB_EXTENSION) \
+       $(am__DEPENDENCIES_2)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
 depcomp = $(SHELL) $(top_srcdir)/config/depcomp
 am__depfiles_maybe = depfiles
@@ -135,7 +139,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -147,9 +153,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -162,6 +171,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -224,10 +234,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -278,8 +291,10 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-INCLUDES = -I$(top_srcdir)/common-src -I$(top_srcdir)/client-src \
-                       -I$(top_srcdir)/tape-src
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/client-src   \
+               -I$(top_srcdir)/tape-src
 
 LIB_EXTENSION = la
 @WANT_RUNTIME_PSEUDO_RELOC_TRUE@AM_LDFLAGS = -Wl,-enable-runtime-pseudo-reloc
@@ -290,12 +305,9 @@ LIB_EXTENSION = la
 # need to list libamanda twice here, first to override the system library
 # routines, and second to pick up any references in the other libraries.
 ###
-LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-       @LEXLIB@ \
-       ../client-src/libamclient.$(LIB_EXTENSION) \
-       ../common-src/libamanda.$(LIB_EXTENSION) \
-       $(READLINE_LIBS)
-
+LDADD = ../common-src/libamanda.$(LIB_EXTENSION) @LEXLIB@ \
+       ../client-src/libamclient.$(LIB_EXTENSION) $(am__append_1) \
+       ../common-src/libamanda.$(LIB_EXTENSION) $(READLINE_LIBS)
 amrecover_SOURCES = amrecover.c                                        \
                        display_commands.c              extract_list.c  \
                        help.c                          set_commands.c  \
@@ -634,7 +646,7 @@ install-exec-hook:
 
 # so that uscan.c is never generated before uparse.h
 # otherwise we might have makedepend problems
-$(srcdir)/uscan.c: $(srcdir)/uparse.h
+uscan.c: uparse.h
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index 4e2776a60356bf01fff2416d71ad02363e7adab7..a4fe069f59a5a5eddca41749ce97f164481dd65b 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amrecover.c,v 1.29.4.7.4.6.2.7.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amrecover.c,v 1.52 2006/01/14 04:37:19 paddy_s Exp $
  *
  * an interactive program for recovering backed-up files
  */
 #include "amrecover.h"
 #include "getfsent.h"
 #include "dgram.h"
-
-#if defined(KRB4_SECURITY)
-#include "krb4-security.h"
-#endif
 #include "util.h"
 
 #ifdef HAVE_LIBREADLINE
@@ -87,7 +83,8 @@ char *tape_server_name = NULL;
 int tape_server_socket;
 char *tape_device_name = NULL;
 am_feature_t *our_features = NULL;
-am_feature_t *their_features = NULL;
+am_feature_t *indexsrv_features = NULL;
+am_feature_t *tapesrv_features = NULL;
 
 
 #ifndef HAVE_LIBREADLINE
@@ -212,28 +209,25 @@ int server_happy ()
 int send_command(cmd)
 char *cmd;
 {
-    size_t l, n;
-    ssize_t s;
-    char *end;
-
     /*
      * NOTE: this routine is called from sigint_handler, so we must be
      * **very** careful about what we do since there is no way to know
      * our state at the time the interrupt happened.  For instance,
-     * do not use any stdio routines here.
+     * do not use any stdio or malloc routines here.
      */
-    for (l = 0, n = strlen(cmd); l < n; l += s)
-       if ((s = write(server_socket, cmd + l, n - l)) < 0) {
-           perror("amrecover: Error writing to server");
-           return -1;
-       }
-    end = "\r\n";
-    for (l = 0, n = strlen(end); l < n; l += s)
-       if ((s = write(server_socket, end + l, n - l)) < 0) {
-           perror("amrecover: Error writing to server");
-           return -1;
-       }
-    return 0;
+    struct iovec msg[2];
+    ssize_t bytes;
+
+    msg[0].iov_base = cmd;
+    msg[0].iov_len = strlen(msg[0].iov_base);
+    msg[1].iov_base = "\r\n";
+    msg[1].iov_len = strlen(msg[1].iov_base);
+    bytes = msg[0].iov_len + msg[1].iov_len;
+
+    if (writev(server_socket, msg, 2) < bytes) {
+       return -1;
+    }
+    return (0);
 }
 
 
@@ -428,6 +422,10 @@ char **argv;
     safe_fd(-1, 0);
 
     set_pname("amrecover");
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     dbopen();
 
 #ifndef IGNORE_UID_CHECK
@@ -507,6 +505,9 @@ char **argv;
     amfree(disk_path);
     dump_date[0] = '\0';
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     /* set up signal handler */
     act.sa_handler = sigint_handler;
     sigemptyset(&act.sa_mask);
@@ -529,7 +530,8 @@ char **argv;
                                             ntohs(sp->s_port),
                                             -1,
                                             -1,
-                                            &my_port);
+                                            &my_port,
+                                            0);
     if (server_socket < 0)
     {
        error("cannot connect to %s: %s", server_name, strerror(errno));
@@ -560,17 +562,7 @@ char **argv;
     }
 
     /* do the security thing */
-#if defined(KRB4_SECURITY)
-#if 0 /* not yet implemented */
-    if(krb4_auth)
-    {
-       line = get_krb_security();
-    } else
-#endif /* 0 */
-#endif
-    {
-       line = get_bsd_security();
-    }
+    line = get_security();
     if (converse(line) == -1)
        exit(1);
     if (!server_happy())
@@ -578,7 +570,7 @@ char **argv;
     memset(line, '\0', strlen(line));
     amfree(line);
 
-    /* try to get the features form the server */
+    /* try to get the features from the server */
     {
        char *our_feature_string = NULL;
        char *their_feature_string = NULL;
@@ -588,10 +580,10 @@ char **argv;
        line = stralloc2("FEATURES ", our_feature_string);
        if(exchange(line) == 0) {
            their_feature_string = stralloc(server_line+13);
-           their_features = am_string_to_feature(their_feature_string);
+           indexsrv_features = am_string_to_feature(their_feature_string);
        }
        else {
-           their_features = am_set_default_feature_set();
+           indexsrv_features = am_set_default_feature_set();
         }
        amfree(our_feature_string);
        amfree(their_feature_string);
@@ -675,3 +667,13 @@ char **argv;
     aclose(server_socket);
     return 0;
 }
+
+char *
+get_security()
+{
+    struct passwd *pwptr;
+
+    if((pwptr = getpwuid(getuid())) == NULL)
+       error("can't get login name for my uid %ld", (long)getuid());
+    return stralloc2("SECURITY USER ", pwptr->pw_name);
+}
index eb937f80f648d17843aa6e13a53d442a399f627c..52c964e5e53426e2a0aa68e7f65ba514db0cc0bf 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amrecover.h,v 1.8.4.2.4.1.2.3 2002/10/27 21:13:25 martinea Exp $
+ * $Id: amrecover.h,v 1.17 2005/12/31 00:02:10 paddy_s Exp $
  *
  * data structures and declarations for amrecover
  */
 
 typedef struct DIR_ITEM
 {
-    char date[11];
+    char *date;
     int  level;
-    char tape[256];
-    char path[1024];
+    char *tape;
+    char *path;
     int  fileno;
 
     struct DIR_ITEM *next;
@@ -56,9 +56,12 @@ extern int quit_prog;                        /* set when time to exit parser */
 extern char *tape_server_name;
 extern char *tape_device_name;
 extern am_feature_t *our_features;
-extern am_feature_t *their_features;
+extern am_feature_t *indexsrv_features;
+extern am_feature_t *tapesrv_features;
 extern pid_t extract_restore_child_pid;
 
+extern void free_dir_item P((DIR_ITEM *item));
+
 extern int converse P((char *cmd));
 extern int exchange P((char *cmd));
 extern int server_happy P((void));
@@ -106,3 +109,5 @@ extern void extract_files P((void));
 #define SAMBA_SMBCLIENT 0
 #define SAMBA_TAR       1
 #endif
+
+extern char *get_security P((void));
index 1797db5307ffeafcc83f8a34e5e98bd130eabc27..88c0cea74846d91006cb2cb67c2e8bf15f72025d 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: display_commands.c,v 1.12.4.1.6.3 2002/10/27 21:13:25 martinea Exp $
+ * $Id: display_commands.c,v 1.19 2006/03/09 20:06:11 johnfranks Exp $
  *
  * implements the directory-display related commands in amrecover
  */
@@ -48,16 +48,21 @@ DIR_ITEM *this;
 
 void clear_dir_list P((void))
 {
-    DIR_ITEM *this;
+    free_dir_item(dir_list); /* Frees all items from dir_list to end of list */
+    dir_list = NULL;
+}
 
-    if (dir_list == NULL)
-       return;
-    do
-    {
-       this = dir_list;
-       dir_list = dir_list->next;
-       amfree(this);
-    } while (dir_list != NULL);
+void free_dir_item P((DIR_ITEM *item)) {
+    DIR_ITEM *next;
+
+    while (item != NULL) {
+       next = item->next;
+        amfree(item->date);
+        amfree(item->tape);
+        amfree(item->path);
+        amfree(item);
+       item = next;
+    }
 }
 
 /* add item to list if path not already on list */
@@ -68,43 +73,22 @@ char *tape;
 int fileno;
 char *path;
 {
-    DIR_ITEM *last;
+    DIR_ITEM *next;
 
     dbprintf(("add_dir_list_item: Adding \"%s\" \"%d\" \"%s\" \"%d\" \"%s\"\n",
              date, level, tape, fileno, path));
 
-    if (dir_list == NULL)
-    {
-       dir_list = (DIR_ITEM *)alloc(sizeof(DIR_ITEM));
-       dir_list->next = NULL;
-       strncpy(dir_list->date, date, sizeof(dir_list->date)-1);
-       dir_list->date[sizeof(dir_list->date)-1] = '\0';
-       dir_list->level = level;
-       strncpy(dir_list->tape, tape, sizeof(dir_list->tape)-1);
-       dir_list->tape[sizeof(dir_list->tape)-1] = '\0';
-       dir_list->fileno = fileno;
-       strncpy(dir_list->path, path, sizeof(dir_list->path)-1);
-       dir_list->path[sizeof(dir_list->path)-1] = '\0';
-
-       return 0;
-    }
+    next = (DIR_ITEM *)alloc(sizeof(DIR_ITEM));
+    memset(next, 0, sizeof(DIR_ITEM));
 
-    last = dir_list;
-    while (last->next != NULL)
-    {
-       last = last->next;
-    }
+    next->date = stralloc(date);
+    next->level = level;
+    next->tape = stralloc(tape);
+    next->fileno = fileno;
+    next->path = stralloc(path);
 
-    last->next = (DIR_ITEM *)alloc(sizeof(DIR_ITEM));
-    last->next->next = NULL;
-    strncpy(last->next->date, date, sizeof(last->next->date)-1);
-    last->next->date[sizeof(last->next->date)-1] = '\0';
-    last->next->level = level;
-    strncpy(last->next->tape, tape, sizeof(last->next->tape)-1);
-    last->next->tape[sizeof(last->next->tape)-1] = '\0';
-    last->next->fileno = fileno;
-    strncpy(last->next->path, path, sizeof(last->next->path)-1);
-    last->next->path[sizeof(last->next->path)-1] = '\0';
+    next->next = dir_list;
+    dir_list = next;
 
     return 0;
 }
@@ -126,7 +110,7 @@ void suck_dir_list_from_server P((void))
     char *date, *date_undo, date_undo_ch = '\0';
     int level, fileno;
     char *tape, *tape_undo, tape_undo_ch = '\0';
-    char *dir, *dir_undo, dir_undo_ch = '\0';
+    char *dir;
     char *disk_path_slash = NULL;
     char *disk_path_slash_dot = NULL;
     char *s;
@@ -165,7 +149,7 @@ void suck_dir_list_from_server P((void))
     disk_path_slash_dot = stralloc2(disk_path_slash, ".");
     amfree(cmd);
     amfree(err);
-    date_undo = tape_undo = dir_undo = NULL;
+    date_undo = tape_undo = NULL;
     /* skip the last line -- duplicate of the preamble */
     while ((i = get_reply_line()) != 0)
     {
@@ -177,8 +161,7 @@ void suck_dir_list_from_server P((void))
        if(err) {
            if(cmd == NULL) {
                if(tape_undo) *tape_undo = tape_undo_ch;
-               if(dir_undo) *dir_undo = dir_undo_ch;
-               date_undo = tape_undo = dir_undo = NULL;
+               date_undo = tape_undo = NULL;
                cmd = stralloc(l);      /* save for the error report */
            }
            continue;                   /* throw the rest of the lines away */
@@ -226,7 +209,7 @@ void suck_dir_list_from_server P((void))
        tape_undo_ch = *tape_undo;
        *tape_undo = '\0';
 
-       if(am_has_feature(their_features, fe_amindexd_fileno_in_OLSD)) {
+       if(am_has_feature(indexsrv_features, fe_amindexd_fileno_in_OLSD)) {
            skip_whitespace(s, ch);
            if(ch == '\0' || sscanf(s - 1, "%d", &fileno) != 1) {
                err = "bad reply: cannot parse fileno field";
index a38eec912a9c9e90e1dcc23f892947aae83ab547..72b37c52bc0a86ced1762a1d084ff68b5b1c94e1 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: extract_list.c,v 1.43.2.13.4.6.2.19 2003/03/04 21:13:58 martinea Exp $
+ * $Id: extract_list.c,v 1.97 2006/03/09 16:51:41 martinea Exp $
  *
  * implements the "extract" command in amrecover
  */
 #include "fileheader.h"
 #include "dgram.h"
 #include "stream.h"
+#include "tapelist.h"
 #ifdef SAMBA_CLIENT
 #include "findpass.h"
 #endif
-
-#if defined(KRB4_SECURITY)
-#include "krb4-security.h"
-#endif
 #include "util.h"
 
 typedef struct EXTRACT_LIST_ITEM
 {
-    char path[1024];
+    char *path;
 
     struct EXTRACT_LIST_ITEM *next;
 }
@@ -54,9 +51,9 @@ EXTRACT_LIST_ITEM;
 
 typedef struct EXTRACT_LIST
 {
-    char date[11];                     /* date tape created */
+    char *date;                        /* date tape created */
     int  level;                                /* level of dump */
-    char tape[256];                    /* tape label */
+    char *tape;                        /* tape label */
     int fileno;                                /* fileno on tape */
     EXTRACT_LIST_ITEM *files;          /* files to get off tape */
 
@@ -74,8 +71,9 @@ extern char *localhost;
 /* global pid storage for interrupt handler */
 pid_t extract_restore_child_pid = -1;
 
-
 static EXTRACT_LIST *extract_list = NULL;
+static int tape_control_sock = -1;
+static int tape_data_sock = -1;
 
 #ifdef SAMBA_CLIENT
 unsigned short samba_extract_method = SAMBA_TAR;
@@ -84,19 +82,42 @@ unsigned short samba_extract_method = SAMBA_TAR;
 #define READ_TIMEOUT   240*60
 
 static int okay_to_continue P((int, int,  int));
+void writer_intermediary P((int ctl_fd, int data_fd, EXTRACT_LIST *elist));
+
+
+/*
+ * Function:  ssize_t read_buffer(datafd, buffer, buflen, timeout_s)
+ *
+ * Description:
+ *     read data from input file desciptor waiting up to timeout_s
+ *     seconds before returning data.
+ *
+ * Inputs:
+ *     datafd    - File descriptor to read from.
+ *     buffer    - Buffer to read into.
+ *     buflen    - Maximum number of bytes to read into buffer.
+ *     timeout_s - Seconds to wait before returning what was already read.
+ *
+ * Returns:
+ *      >0       - Number of data bytes in buffer.
+ *       0       - EOF
+ *      -1        - errno == ETIMEDOUT if no data available in specified time.
+ *                  errno == ENFILE if datafd is invalid.
+ *                  otherwise errno is set by select or read..
+ */
 
-ssize_t read_buffer(datafd, buffer, buflen)
+static ssize_t
+read_buffer(datafd, buffer, buflen, timeout_s)
 int datafd;
 char *buffer;
 size_t buflen;
 {
-    int maxfd, nfound = 0;
     ssize_t size = 0;
-    fd_set readset, selectset;
+    fd_set readset;
     struct timeval timeout;
     char *dataptr;
     size_t spaceleft;
-    int eof;
+    int nfound;
 
     if(datafd < 0 || datafd >= FD_SETSIZE) {
        errno = EMFILE;                                 /* out of range */
@@ -106,60 +127,55 @@ size_t buflen;
     dataptr = buffer;
     spaceleft = buflen;
 
-    maxfd = datafd + 1;
-    eof = 0;
-
-    FD_ZERO(&readset);
-    FD_SET(datafd, &readset);
-
     do {
+        FD_ZERO(&readset);
+        FD_SET(datafd, &readset);
+        timeout.tv_sec = timeout_s;
+        timeout.tv_usec = 0;
+        nfound = select(datafd+1, &readset, NULL, NULL, &timeout);
+        if(nfound < 0 ) {
+            /* Select returned an error. */
+           fprintf(stderr,"select error: %s\n", strerror(errno));
+            size = -1;
+           break;
+        }
+
+       if (nfound == 0) {
+            /* Select timed out. */
+            if (timeout_s != 0)  {
+                /* Not polling: a real read timeout */
+                fprintf(stderr,"timeout waiting for restore\n");
+                fprintf(stderr,"increase READ_TIMEOUT in recover-src/extract_list.c if your tape is slow\n");
+            }
+            errno = ETIMEDOUT;
+            size = -1;
+           break;
+        }
 
-       timeout.tv_sec = READ_TIMEOUT;
-       timeout.tv_usec = 0;
-       memcpy(&selectset, &readset, sizeof(fd_set));
-
-       nfound = select(maxfd, (SELECT_ARG_TYPE *)(&selectset), NULL, NULL, &timeout);
-
-       /* check for errors or timeout */
-
-       if(nfound == 0)  {
-           size=-2;
-           fprintf(stderr,"timeout waiting for amrestore\n");
-           fprintf(stderr,"increase READ_TIMEOUT in recover-src/extract_list.c if your tape is slow\n");
-       }
-       if(nfound == -1) {
-           size=-3;
-           fprintf(stderr,"nfound == -1\n");
-       }
+       if(!FD_ISSET(datafd, &readset))
+           continue;
 
-       /* read any data */
-
-       if(FD_ISSET(datafd, &selectset)) {
-           size = read(datafd, dataptr, spaceleft);
-           switch(size) {
-           case -1:
-               break;
-           case 0:
-               spaceleft -= size;
-               dataptr += size;
-               fprintf(stderr,
-                       "EOF, check amidxtaped.<timestamp>.debug file on %s.\n",
-                       tape_server_name);
-               break;
-           default:
-               spaceleft -= size;
-               dataptr += size;
-               break;
+        /* Select says data is available, so read it.  */
+        size = read(datafd, dataptr, spaceleft);
+        if (size < 0) {
+           if ((errno == EINTR) || (errno == EAGAIN)) {
+               continue;
            }
+           if (errno != EPIPE) {
+               fprintf(stderr, "read_buffer: read error - %s",
+                   strerror(errno));
+               break;
+           }
+           size = 0;
        }
-    } while (spaceleft>0 && size>0);
+        spaceleft -= size;
+        dataptr += size;
+    } while ((size > 0) && (spaceleft > 0));
 
-    if(size<0) {
-       return -1;
-    }
-    return (ssize_t)(buflen-spaceleft);
+    return (((buflen-spaceleft) > 0) ? (buflen-spaceleft) : size);
 }
 
+
 EXTRACT_LIST *first_tape_list P((void))
 {
     return extract_list;
@@ -177,12 +193,14 @@ static void clear_tape_list(tape_list)
 EXTRACT_LIST *tape_list;
 {
     EXTRACT_LIST_ITEM *this, *next;
+    
 
     this = tape_list->files;
     while (this != NULL)
     {
        next = this->next;
-       free(this);
+        amfree(this->path);
+        amfree(this);
        this = next;
     }
     tape_list->files = NULL;
@@ -196,11 +214,16 @@ EXTRACT_LIST *tape_list;
 {
     EXTRACT_LIST *this, *prev;
 
+    if (tape_list == NULL)
+        return;
+
     /* is it first on the list? */
     if (tape_list == extract_list)
     {
-       clear_tape_list(tape_list);
        extract_list = tape_list->next;
+       clear_tape_list(tape_list);
+        amfree(tape_list->date);
+        amfree(tape_list->tape);
        amfree(tape_list);
        return;
     }
@@ -212,8 +235,10 @@ EXTRACT_LIST *tape_list;
     {
        if (this == tape_list)
        {
-           clear_tape_list(tape_list);
            prev->next = tape_list->next;
+           clear_tape_list(tape_list);
+            amfree(tape_list->date);
+            amfree(tape_list->tape);
            amfree(tape_list);
            return;
        }
@@ -275,8 +300,7 @@ DIR_ITEM *ditem;
                curr=curr->next;
            }
            that = (EXTRACT_LIST_ITEM *)alloc(sizeof(EXTRACT_LIST_ITEM));
-           strncpy(that->path, ditem_path, sizeof(that->path)-1);
-           that->path[sizeof(that->path)-1] = '\0';
+            that->path = stralloc(ditem_path);
            that->next = this->files;
            this->files = that;         /* add at front since easiest */
            amfree(ditem_path);
@@ -286,15 +310,12 @@ DIR_ITEM *ditem;
 
     /* so this is the first time we have seen this tape */
     this = (EXTRACT_LIST *)alloc(sizeof(EXTRACT_LIST));
-    strncpy(this->tape, ditem->tape, sizeof(this->tape)-1);
-    this->tape[sizeof(this->tape)-1] ='\0';
+    this->tape = stralloc(ditem->tape);
     this->level = ditem->level;
     this->fileno = ditem->fileno;
-    strncpy(this->date, ditem->date, sizeof(this->date)-1);
-    this->date[sizeof(this->date)-1] = '\0';
+    this->date = stralloc(ditem->date);
     that = (EXTRACT_LIST_ITEM *)alloc(sizeof(EXTRACT_LIST_ITEM));
-    strncpy(that->path, ditem_path, sizeof(that->path)-1);
-    that->path[sizeof(that->path)-1] = '\0';
+    that->path = stralloc(ditem_path);
     that->next = NULL;
     this->files = that;
 
@@ -351,6 +372,7 @@ DIR_ITEM *ditem;
            {
                /* first on list */
                this->files = that->next;
+                amfree(that->path);
                amfree(that);
                /* if list empty delete it */
                if (this->files == NULL)
@@ -365,6 +387,7 @@ DIR_ITEM *ditem;
                if (strcmp(that->path, ditem_path) == 0)
                {
                    prev->next = that->next;
+                    amfree(that->path);
                    amfree(that);
                    amfree(ditem_path);
                    return 0;
@@ -447,6 +470,7 @@ char *regex;
        printf("Must select directory before adding files\n");
        return;
     }
+    memset(&lditem, 0, sizeof(lditem)); /* Prevent use of bogus data... */
 
     dbprintf(("add_file: Looking for \"%s\"\n", regex));
 
@@ -455,9 +479,20 @@ char *regex;
     while(j >= 0 && regex[j] == '/') regex[j--] = '\0';
 
     /* convert path (assumed in cwd) to one on disk */
-    if (strcmp(disk_path, "/") == 0)
-       path_on_disk = stralloc2("/", regex);
-    else {
+    if (strcmp(disk_path, "/") == 0) {
+        if (*regex == '/') {
+           if (strcmp(regex, "/[/]*$") == 0) {
+               /* We want '/' to match everything in directory... */
+               path_on_disk = stralloc("/[^/]*[/]*$");
+           } else {
+               /* No mods needed if already starts with '/' */
+               path_on_disk = stralloc(regex);
+           }
+       } else {
+           /* Prepend '/' */
+           path_on_disk = stralloc2("/", regex);
+       }
+    } else {
        char *clean_disk_path = clean_regex(disk_path);
        path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
        amfree(clean_disk_path);
@@ -493,6 +528,7 @@ char *regex;
                    exit(1);
                }
                amfree(cmd);
+               cmd = NULL;
                /* skip preamble */
                if ((i = get_reply_line()) == -1) {
                    amfree(ditem_path);
@@ -509,11 +545,9 @@ char *regex;
                    printf("%s\n", l);
                    return;
                }
-               amfree(err);
                dir_undo = NULL;
                added=0;
-               strncpy(lditem.path, ditem_path, sizeof(lditem.path)-1);
-               lditem.path[sizeof(lditem.path)-1] = '\0';
+                lditem.path = newstralloc(lditem.path, ditem->path);
                /* skip the last line -- duplicate of the preamble */
                while ((i = get_reply_line()) != 0)
                {
@@ -550,11 +584,11 @@ char *regex;
                        err = "bad reply: missing date field";
                        continue;
                    }
-                   copy_string(s, ch, lditem.date, sizeof(lditem.date), fp);
-                   if(fp == NULL) {
-                       err = "bad reply: date field too large";
-                       continue;
-                   }
+                    fp = s-1;
+                    skip_non_whitespace(s, ch);
+                    s[-1] = '\0';
+                    lditem.date = newstralloc(lditem.date, fp);
+                    s[-1] = ch;
 
                    skip_whitespace(s, ch);
                    if(ch == '\0' || sscanf(s - 1, "%d", &lditem.level) != 1) {
@@ -568,13 +602,13 @@ char *regex;
                        err = "bad reply: missing tape field";
                        continue;
                    }
-                   copy_string(s, ch, lditem.tape, sizeof(lditem.tape), fp);
-                   if(fp == NULL) {
-                       err = "bad reply: tape field too large";
-                       continue;
-                   }
+                    fp = s-1;
+                    skip_non_whitespace(s, ch);
+                    s[-1] = '\0';
+                    lditem.tape = newstralloc(lditem.tape, fp);
+                    s[-1] = ch;
 
-                   if(am_has_feature(their_features, fe_amindexd_fileno_in_ORLD)) {
+                   if(am_has_feature(indexsrv_features, fe_amindexd_fileno_in_ORLD)) {
                        skip_whitespace(s, ch);
                        if(ch == '\0' || sscanf(s - 1, "%d", &lditem.fileno) != 1) {
                            err = "bad reply: cannot parse fileno field";
@@ -613,9 +647,7 @@ char *regex;
                if(!server_happy()) {
                    puts(reply_line());
                } else if(err) {
-                   if(*err) {
-                       puts(err);
-                   }
+                   puts(err);
                    puts(cmd);
                } else if(added == 0) {
                    printf("dir %s already added\n", ditem_path);
@@ -643,7 +675,8 @@ char *regex;
            }
        }
     }
-    amfree(cmd);
+    if (cmd != NULL)
+       amfree(cmd);
     amfree(ditem_path);
     amfree(path_on_disk);
     amfree(path_on_disk_slash);
@@ -724,6 +757,7 @@ char *regex;
        printf("Must select directory before deleting files\n");
        return;
     }
+    memset(&lditem, 0, sizeof(lditem)); /* Prevent use of bogus data... */
 
     dbprintf(("delete_file: Looking for \"%s\"\n", path));
     /* remove "/" at the end of the path */
@@ -784,10 +818,8 @@ char *regex;
                    return;
                }
                deleted=0;
-               strncpy(lditem.path, ditem->path, sizeof(lditem.path)-1);
-               lditem.path[sizeof(lditem.path)-1] = '\0';
+                lditem.path = newstralloc(lditem.path, ditem->path);
                amfree(cmd);
-               amfree(err);
                date_undo = tape_undo = dir_undo = NULL;
                /* skip the last line -- duplicate of the preamble */
                while ((i = get_reply_line()) != 0)
@@ -849,7 +881,7 @@ char *regex;
                    tape_undo_ch = *tape_undo;
                    *tape_undo = '\0';
 
-                   if(am_has_feature(their_features, fe_amindexd_fileno_in_ORLD)) {
+                   if(am_has_feature(indexsrv_features, fe_amindexd_fileno_in_ORLD)) {
                        skip_whitespace(s, ch);
                        if(ch == '\0' || sscanf(s - 1, "%d", &fileno) != 1) {
                            err = "bad reply: cannot parse fileno field";
@@ -869,11 +901,9 @@ char *regex;
                    dir_undo_ch = *dir_undo;
                    *dir_undo = '\0';
 
-                   strncpy(lditem.date, date, sizeof(lditem.date)-1);
-                   lditem.date[sizeof(lditem.date)-1] = '\0';
+                    lditem.date = newstralloc(lditem.date, date);
                    lditem.level=level;
-                   strncpy(lditem.tape, tape, sizeof(lditem.tape)-1);
-                   lditem.tape[sizeof(lditem.tape)-1] = '\0';
+                    lditem.tape = newstralloc(lditem.tape, tape);
                    switch(delete_extract_item(&lditem)) {
                    case -1:
                        printf("System error\n");
@@ -1080,23 +1110,14 @@ static void send_to_tape_server(tss, cmd)
 int tss;
 char *cmd;
 {
-    size_t l, n;
-    ssize_t s;
-    char *end;
+    char *msg = stralloc2(cmd, "\r\n");
 
-    for (l = 0, n = strlen(cmd); l < n; l += s)
-       if ((s = write(tss, cmd + l, n - l)) < 0)
-       {
-           perror("Error writing to tape server");
-           exit(101);
-       }
-    end = "\r\n";
-    for (l = 0, n = strlen(end); l < n; l += s)
-       if ((s = write(tss, end + l, n - l)) < 0)
-       {
-           perror("Error writing to tape server");
-           exit(101);
-       }
+    if (fullwrite(tss, msg, strlen(msg)) < 0)
+    {
+       error("Error writing to tape server");
+       exit(101);
+    }
+    amfree(msg);
 }
 
 
@@ -1108,13 +1129,14 @@ char *label;
 int fsf;
 {
     struct servent *sp;
-    int my_port;
-    int tape_server_socket;
+    int my_port, my_data_port;
     char *disk_regex = NULL;
     char *host_regex = NULL;
     char *service_name = NULL;
     char *line = NULL;
     char *clean_datestamp, *ch, *ch1;
+    char *our_feature_string = NULL;
+    char *tt = NULL;
 
     service_name = stralloc2("amidxtape", SERVICE_SUFFIX);
 
@@ -1128,37 +1150,29 @@ int fsf;
     amfree(service_name);
     seteuid(0);                                        /* it either works ... */
     setegid(0);
-    tape_server_socket = stream_client_privileged(tape_server_name,
+    tape_control_sock = stream_client_privileged(tape_server_name,
                                                  ntohs(sp->s_port),
                                                  -1,
                                                  STREAM_BUFSIZE,
-                                                 &my_port);
-    if (tape_server_socket < 0)
+                                                 &my_port,
+                                                 0);
+    if (tape_control_sock < 0)
     {
        printf("cannot connect to %s: %s\n", tape_server_name, strerror(errno));
        return -1;
     }
     if (my_port >= IPPORT_RESERVED) {
-       aclose(tape_server_socket);
+       aclose(tape_control_sock);
        printf("did not get a reserved port: %d\n", my_port);
        return -1;
     }
     setegid(getgid());
     seteuid(getuid());                         /* put it back */
 
     /* do the security thing */
-#if defined(KRB4_SECURITY)
-#if 0 /* not yet implemented */
-    if(krb4_auth)
-    {
-       line = get_krb_security();
-    }
-#endif /* 0 */
-#endif
-    {
-       line = get_bsd_security();
-    }
-    send_to_tape_server(tape_server_socket, line);
+    line = get_security();
+    send_to_tape_server(tape_control_sock, line);
     memset(line, '\0', strlen(line));
     amfree(line);
 
@@ -1219,45 +1233,58 @@ int fsf;
     }
     *ch = '\0';
 
-    if(am_has_feature(their_features, fe_amidxtaped_header) &&
-       am_has_feature(their_features, fe_amidxtaped_device) &&
-       am_has_feature(their_features, fe_amidxtaped_host) &&
-       am_has_feature(their_features, fe_amidxtaped_disk) &&
-       am_has_feature(their_features, fe_amidxtaped_datestamp)) {
+    /* push our feature list off to the tape server */
+    /* XXX assumes that index server and tape server are equivalent, ew */
+    if(am_has_feature(indexsrv_features, fe_amidxtaped_exchange_features)){
+       char buffer[32768] = "\0";
+
+       our_feature_string = am_feature_to_string(our_features);
+       tt = newstralloc2(tt, "FEATURES=", our_feature_string);
+       send_to_tape_server(tape_control_sock, tt);
+       if (read(tape_control_sock, buffer, sizeof(buffer)) <= 0) {
+           error("Could not read features from control socket\n");
+           /* NOTREACHED */
+       }
+       
+       tapesrv_features = am_string_to_feature(buffer);
+       amfree(our_feature_string);
+    }
+
 
-       char *tt = NULL;
+    if(am_has_feature(indexsrv_features, fe_amidxtaped_header) &&
+       am_has_feature(indexsrv_features, fe_amidxtaped_device) &&
+       am_has_feature(indexsrv_features, fe_amidxtaped_host) &&
+       am_has_feature(indexsrv_features, fe_amidxtaped_disk) &&
+       am_has_feature(indexsrv_features, fe_amidxtaped_datestamp)) {
 
-       if(am_has_feature(their_features, fe_amidxtaped_config)) {
+       if(am_has_feature(indexsrv_features, fe_amidxtaped_config)) {
            tt = newstralloc2(tt, "CONFIG=", config);
-           send_to_tape_server(tape_server_socket, tt);
+           send_to_tape_server(tape_control_sock, tt);
        }
-       if(am_has_feature(their_features, fe_amidxtaped_label) &&
+       if(am_has_feature(indexsrv_features, fe_amidxtaped_label) &&
           label && label[0] != '/') {
            tt = newstralloc2(tt,"LABEL=",label);
-           send_to_tape_server(tape_server_socket, tt);
+           send_to_tape_server(tape_control_sock, tt);
        }
-       if(am_has_feature(their_features, fe_amidxtaped_fsf)) {
+       if(am_has_feature(indexsrv_features, fe_amidxtaped_fsf)) {
            char v_fsf[100];
-           ap_snprintf(v_fsf, 99, "%d", fsf);
+           snprintf(v_fsf, 99, "%d", fsf);
            tt = newstralloc2(tt, "FSF=",v_fsf);
-           send_to_tape_server(tape_server_socket, tt);
+           send_to_tape_server(tape_control_sock, tt);
        }
-       send_to_tape_server(tape_server_socket, "HEADER");
+       send_to_tape_server(tape_control_sock, "HEADER");
        tt = newstralloc2(tt, "DEVICE=", dump_device_name);
-       send_to_tape_server(tape_server_socket, tt);
+       send_to_tape_server(tape_control_sock, tt);
        tt = newstralloc2(tt, "HOST=", host_regex);
-       send_to_tape_server(tape_server_socket, tt);
+       send_to_tape_server(tape_control_sock, tt);
        tt = newstralloc2(tt, "DISK=", disk_regex);
-       send_to_tape_server(tape_server_socket, tt);
+       send_to_tape_server(tape_control_sock, tt);
        tt = newstralloc2(tt, "DATESTAMP=", clean_datestamp);
-       send_to_tape_server(tape_server_socket, tt);
-       send_to_tape_server(tape_server_socket, "END");
+       send_to_tape_server(tape_control_sock, tt);
+       send_to_tape_server(tape_control_sock, "END");
        amfree(tt);
     }
-    else if(1 /* am_has_feature(their_features, fe_amidxtaped_nargs) */) {
-       /* 2.4.3 doesn't set fe_amidxtaped_nargs but support it */
-       /* must be supported without test until 2005 */
-
+    else if(am_has_feature(indexsrv_features, fe_amidxtaped_nargs)) {
        /* send to the tape server what tape file we want */
        /* 6 args:
         *   "-h"
@@ -1267,27 +1294,74 @@ int fsf;
         *   "diskname"
         *   "datestamp"
         */
-       send_to_tape_server(tape_server_socket, "6");
-       send_to_tape_server(tape_server_socket, "-h");
-       send_to_tape_server(tape_server_socket, "-p");
-       send_to_tape_server(tape_server_socket, dump_device_name);
-       send_to_tape_server(tape_server_socket, host_regex);
-       send_to_tape_server(tape_server_socket, disk_regex);
-       send_to_tape_server(tape_server_socket, clean_datestamp);
+       send_to_tape_server(tape_control_sock, "6");
+       send_to_tape_server(tape_control_sock, "-h");
+       send_to_tape_server(tape_control_sock, "-p");
+       send_to_tape_server(tape_control_sock, dump_device_name);
+       send_to_tape_server(tape_control_sock, host_regex);
+       send_to_tape_server(tape_control_sock, disk_regex);
+       send_to_tape_server(tape_control_sock, clean_datestamp);
 
        dbprintf(("Started amidxtaped with arguments \"6 -h -p %s %s %s %s\"\n",
                  dump_device_name, host_regex, disk_regex, clean_datestamp));
     }
 
+    /*
+     * split-restoring amidxtaped versions will expect to set up a data
+     * connection for dumpfile data, distinct from the socket we're already
+     * using for control data
+     */
+
+    if(am_has_feature(tapesrv_features, fe_recover_splits)){
+       char buffer[32768];
+       int data_port = -1;
+        int nread;
+
+        nread = read(tape_control_sock, buffer, sizeof(buffer));
+
+       if (nread <= 0) {
+           error("Could not read from control socket: %s\n", 
+                  strerror(errno));
+           /* NOTREACHED */
+        }
+
+       buffer[nread] = '\0';
+        if (sscanf(buffer, "CONNECT %d\n", &data_port) != 1) {
+           error("Recieved invalid port number message from control socket: %s\n",
+                  buffer);
+           /* NOTREACHED */
+        }      
+
+       tape_data_sock = stream_client_privileged(server_name,
+                                                 data_port,
+                                                 -1,
+                                                 STREAM_BUFSIZE,
+                                                 &my_data_port,
+                                                 0);
+       if(tape_data_sock == -1){
+           error("Unable to make data connection to server: %s\n",
+                     strerror(errno));
+           /* NOTREACHED */
+       }
+
+       amfree(our_feature_string);
+    
+       line = get_security();
+
+       send_to_tape_server(tape_data_sock, line);
+       memset(line, '\0', strlen(line));
+       amfree(line);
+    }
+
     amfree(disk_regex);
     amfree(host_regex);
     amfree(clean_datestamp);
 
-    return tape_server_socket;
+    return tape_control_sock;
 }
 
 
-size_t read_file_header(buffer, file, buflen, tapedev)
+void read_file_header(buffer, file, buflen, tapedev)
 char *buffer;
 dumpfile_t *file;
 size_t buflen;
@@ -1297,25 +1371,28 @@ int tapedev;
  */
 {
     ssize_t bytes_read;
-    bytes_read=read_buffer(tapedev,buffer,buflen);
+
+    bytes_read = read_buffer(tapedev, buffer, buflen, READ_TIMEOUT);
     if(bytes_read < 0) {
-       error("error reading tape: %s", strerror(errno));
+       error("error reading header (%s), check amidxtaped.*.debug on server",
+             strerror(errno));
+       /* NOTREACHED */
     }
-    else if((size_t)bytes_read < buflen) {
+
+    if((size_t)bytes_read < buflen) {
        fprintf(stderr, "%s: short block %d byte%s\n",
                get_pname(), (int)bytes_read, (bytes_read == 1) ? "" : "s");
        print_header(stdout, file);
        error("Can't read file header");
+       /* NOTREACHED */
     }
-    else { /* bytes_read == buflen */
-       parse_file_header(buffer, file, bytes_read);
-    }
-    return((size_t)bytes_read);
+
+    /* bytes_read == buflen */
+    parse_file_header(buffer, file, bytes_read);
 }
 
 enum dumptypes {IS_UNKNOWN, IS_DUMP, IS_GNUTAR, IS_TAR, IS_SAMBA, IS_SAMBA_TAR};
 
-/* exec restore to do the actual restoration */
 static void extract_files_child(in_fd, elist)
     int in_fd;
     EXTRACT_LIST *elist;
@@ -1329,7 +1406,6 @@ static void extract_files_child(in_fd, elist)
     enum dumptypes dumptype = IS_UNKNOWN;
     char buffer[DISK_BLOCK_BYTES];
     dumpfile_t file;
-    size_t buflen;
     size_t len_program;
     char *cmd = NULL;
     int passwd_field = -1;
@@ -1343,17 +1419,18 @@ static void extract_files_child(in_fd, elist)
     /* make in_fd be our stdin */
     if (dup2(in_fd, STDIN_FILENO) == -1)
     {
-       perror("extract_list - extract files client");
-       exit(1);
+       error("dup2 failed in extract_files_child: %s", strerror(errno));
+       /* NOTREACHED */
     }
 
     /* read the file header */
     fh_init(&file);
-    buflen=read_file_header(buffer, &file, sizeof(buffer), STDIN_FILENO);
+    read_file_header(buffer, &file, sizeof(buffer), STDIN_FILENO);
 
-    if(buflen == 0 || file.type != F_DUMPFILE) {
+    if(file.type != F_DUMPFILE) {
        print_header(stdout, &file);
        error("bad header");
+       /* NOTREACHED */
     }
 
     if (file.program != NULL) {
@@ -1389,6 +1466,8 @@ static void extract_files_child(in_fd, elist)
 #endif
     case IS_TAR:
     case IS_GNUTAR:
+        extra_params = 4;
+        break;
     case IS_SAMBA_TAR:
         extra_params = 3;
         break;
@@ -1436,6 +1515,7 @@ static void extract_files_child(in_fd, elist)
     case IS_TAR:
     case IS_GNUTAR:
        restore_args[j++] = stralloc("tar");
+       restore_args[j++] = stralloc("--numeric-owner");
        restore_args[j++] = stralloc("-xpGvf");
        restore_args[j++] = stralloc("-");      /* data on stdin */
        break;
@@ -1477,7 +1557,10 @@ static void extract_files_child(in_fd, elist)
        case IS_GNUTAR:
        case IS_SAMBA_TAR:
        case IS_SAMBA:
-           restore_args[j++] = stralloc2(".", fn->path);
+           if (strcmp(fn->path, "/") == 0)
+               restore_args[j++] = stralloc(".");
+           else
+               restore_args[j++] = stralloc2(".", fn->path);
            break;
        case IS_UNKNOWN:
        case IS_DUMP:
@@ -1575,6 +1658,189 @@ static void extract_files_child(in_fd, elist)
     /*NOT REACHED */
 }
 
+/*
+ * Interpose something between the process writing out the dump (writing it to
+ * some extraction program, really) and the socket from which we're reading, so
+ * that we can do things like prompt for human interaction for multiple tapes.
+ */
+void writer_intermediary(ctl_fd, data_fd, elist)
+    int ctl_fd, data_fd;
+    EXTRACT_LIST *elist;
+{
+    int child_pipe[2];
+    pid_t pid;
+    char buffer[DISK_BLOCK_BYTES];
+    ssize_t s;
+    ssize_t bytes_read;
+    amwait_t extractor_status;
+    int max_fd, nfound;
+    fd_set readset, selectset;
+    struct timeval timeout;
+
+    /*
+     * If there's no distinct data channel (such as if we're talking to an
+     * older server), don't bother doing anything complicated.  Just run the
+     * extraction.
+     */
+    if(data_fd == -1){
+       extract_files_child(ctl_fd, elist);
+       /* NOTREACHED */
+    }
+
+    if(pipe(child_pipe) == -1) {
+       error("extract_list - error setting up pipe to extractor: %s\n",
+           strerror(errno));
+       /* NOTREACHED */
+    }
+
+    /* okay, ready to extract. fork a child to do the actual work */
+    if ((pid = fork()) == 0) {
+       /* this is the child process */
+       /* never gets out of this clause */
+       aclose(child_pipe[1]);
+        extract_files_child(child_pipe[0], elist);
+       /* NOTREACHED */
+    }
+
+    /* This is the parent */
+    if (pid == -1) {
+       error("writer_intermediary - error forking child");
+       /* NOTREACHED */
+    }
+
+    aclose(child_pipe[0]);
+
+    if(data_fd > ctl_fd) max_fd = data_fd+1;
+                    else max_fd = ctl_fd+1;
+    FD_ZERO(&readset);
+    FD_SET(data_fd, &readset);
+    FD_SET(ctl_fd, &readset);
+
+    do {
+       timeout.tv_sec = READ_TIMEOUT;
+       timeout.tv_usec = 0;
+       FD_COPY(&readset, &selectset);
+        
+       nfound = select(max_fd, (SELECT_ARG_TYPE *)(&selectset), NULL, NULL,
+                       &timeout);
+       if(nfound < 0) {
+           fprintf(stderr,"select error: %s\n", strerror(errno));
+           break;
+       }
+        
+       if (nfound == 0) { /* timeout */
+           fprintf(stderr, "timeout waiting %d seconds for restore\n",
+                   READ_TIMEOUT);
+           fprintf(stderr, "increase READ_TIMEOUT in recover-src/extract_list.c if your tape is slow\n");
+           break;
+       }
+        
+       if(FD_ISSET(ctl_fd, &selectset)) {
+           bytes_read = read(ctl_fd, buffer, sizeof(buffer)-1);
+           switch(bytes_read) {
+            case -1:
+                if ((errno != EINTR) && (errno != EAGAIN)) {
+                    if (errno != EPIPE) {
+                        fprintf(stderr,"writer ctl fd read error: %s",
+                                strerror(errno));
+                    }
+                    FD_CLR(ctl_fd, &readset);
+                }
+                break;
+                
+            case  0:
+                FD_CLR(ctl_fd, &readset);
+                break;
+                
+            default: {
+                char desired_tape[MAX_TAPE_LABEL_BUF];
+                
+                buffer[bytes_read] = '\0';
+                /* if prompted for a tape, relay said prompt to the user */
+                if(sscanf(buffer, "FEEDME %s\n", desired_tape) == 1) {
+                    int done = 0;
+                    while (!done) {
+                        char *input = NULL;
+                        printf("Please insert tape %s. Continue? [Y|n]: ",
+                               desired_tape);
+                        fflush(stdout);
+                        
+                        input = agets(stdin); /* strips \n */
+                        if (strcasecmp("", input) == 0|| 
+                            strcasecmp("y", input) == 0|| 
+                            strcasecmp("yes", input) == 0) {
+                            send_to_tape_server(tape_control_sock, "OK");
+                            done = 1;
+                        } else if (strcasecmp("n", input) == 0|| 
+                                   strcasecmp("no", input) == 0) {
+                            send_to_tape_server(tape_control_sock, "ERROR");
+                            /* Abort!
+                               We are the middle process, so just die. */
+                            exit(EXIT_FAILURE);
+                        }
+                        amfree(input);
+                    }
+                } else {
+                    fprintf(stderr, "Strange message from tape server: %s", buffer);
+                    
+                   break;
+               }
+           }
+            }
+        }
+            
+        /* now read some dump data */
+        if(FD_ISSET(data_fd, &selectset)) {
+            bytes_read = read(data_fd, buffer, sizeof(buffer)-1);
+            switch(bytes_read) {
+            case -1:
+                if ((errno != EINTR) && (errno != EAGAIN)) {
+                    if (errno != EPIPE) {
+                        fprintf(stderr,"writer data fd read error: %s",
+                                strerror(errno));
+                    }
+                    FD_CLR(data_fd, &readset);
+                }
+                break;
+                
+            case  0:
+                FD_CLR(data_fd, &readset);
+                break;
+                
+            default:
+                /*
+                 * spit what we got from the server to the child
+                 *  process handling actual dumpfile extraction
+                 */
+                if((s = fullwrite(child_pipe[1], buffer, bytes_read)) < 0){
+                    if(errno == EPIPE) {
+                        error("%s: pipe data reader has quit: %s\n",
+                              get_pname(), strerror(errno));
+                        /* NOTREACHED */
+                    }
+                    error("Write error to extract child: %s\n",
+                          strerror(errno));
+                    /* NOTREACHED */
+                }
+                break;
+           }
+       }
+    } while(FD_ISSET(ctl_fd, &readset) || FD_ISSET(data_fd, &readset));
+
+    aclose(child_pipe[1]);
+
+    waitpid(pid, &extractor_status, 0);
+    if(WEXITSTATUS(extractor_status) != 0){
+       int ret = WEXITSTATUS(extractor_status);
+        if(ret == 255) ret = -1;
+       error("Extractor child exited with status %d\n", ret);
+       /* NOTREACHED */
+    }
+
+    exit(0);
+}
+
+/* exec restore to do the actual restoration */
 
 /* does the actual extraction of files */
 /* The original design had the dump image being returned exactly as it
@@ -1598,9 +1864,9 @@ void extract_files P((void))
     amwait_t child_stat;
     char buf[STR_SIZE];
     char *l;
-    int tape_server_socket;
     int first;
     int otc;
+    tapelist_t *tlist = NULL;
 
     if (!is_extract_list_nonempty())
     {
@@ -1644,7 +1910,11 @@ void extract_files P((void))
            }
            else
                printf("                               ");
-           printf(" %s\n", elist->tape);
+           tlist = unmarshal_tapelist_str(elist->tape); 
+           for( ; tlist != NULL; tlist = tlist->next)
+               printf(" %s", tlist->label);
+           printf("\n");
+           amfree(tlist);
        }
     first=1;
     for (elist = first_tape_list(); elist != NULL; elist = next_tape_list(elist))
@@ -1657,7 +1927,11 @@ void extract_files P((void))
            }
            else
                printf("                               ");
-           printf(" %s\n", elist->tape);
+           tlist = unmarshal_tapelist_str(elist->tape); 
+           for( ; tlist != NULL; tlist = tlist->next)
+               printf(" %s", tlist->label);
+           printf("\n");
+           amfree(tlist);
        }
     printf("\n");
     getcwd(buf, sizeof(buf));
@@ -1674,12 +1948,19 @@ void extract_files P((void))
     {
        if(elist->tape[0]=='/') {
            dump_device_name = newstralloc(dump_device_name, elist->tape);
-           printf("Extracting from file %s\n",dump_device_name);
+           printf("Extracting from file ");
+           tlist = unmarshal_tapelist_str(dump_device_name); 
+           for( ; tlist != NULL; tlist = tlist->next)
+               printf(" %s", tlist->label);
+           printf("\n");
+           amfree(tlist);
        }
        else {
            printf("Extracting files using tape drive %s on host %s.\n",
                   tape_device_name, tape_server_name);
-           printf("Load tape %s now\n", elist->tape);
+           tlist = unmarshal_tapelist_str(elist->tape); 
+           printf("Load tape %s now\n", tlist->label);
+           amfree(tlist);
            otc = okay_to_continue(1,1,0);
            if (otc == 0)
                return;
@@ -1692,7 +1973,7 @@ void extract_files P((void))
        dump_datestamp = newstralloc(dump_datestamp, elist->date);
 
        /* connect to the tape handler daemon on the tape drive server */
-       if ((tape_server_socket = extract_files_setup(elist->tape, elist->fileno)) == -1)
+       if ((tape_control_sock = extract_files_setup(elist->tape, elist->fileno)) == -1)
        {
            fprintf(stderr, "amrecover - can't talk to tape server\n");
            return;
@@ -1703,7 +1984,7 @@ void extract_files P((void))
        {
            /* this is the child process */
            /* never gets out of this clause */
-           extract_files_child(tape_server_socket, elist);
+           writer_intermediary(tape_control_sock, tape_data_sock, elist);
            /*NOT REACHED*/
        }
        /* this is the parent */
@@ -1716,14 +1997,17 @@ void extract_files P((void))
        /* store the child pid globally so that it can be killed on intr */
        extract_restore_child_pid = pid;
 
-       aclose(tape_server_socket);
-
        /* wait for the child process to finish */
        if ((pid = waitpid(-1, &child_stat, 0)) == (pid_t)-1)
        {
            perror("extract_list - error waiting for child");
            exit(1);
        }
+
+       if(tape_data_sock != -1) {
+           aclose(tape_data_sock);
+       }
+
        if (pid == extract_restore_child_pid)
        {
            extract_restore_child_pid = -1;
index 92d3faaee91446d559c894d050b948f7fb3d8fde..a89759b971a6dd08719ffbbc2d044eb2a62b7500 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: help.c,v 1.4.4.2.4.1.2.1 2002/03/06 19:23:32 martinea Exp $
+ * $Id: help.c,v 1.8 2002/03/06 19:23:20 martinea Exp $
  *
  * implements the "help" command in amrecover
  */
index a7498df54c34c19c051fb28a1286bc79a1645648..65163a7450134b090bfacd3fa0ed5410c29d835e 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: set_commands.c,v 1.11.2.3.4.2.2.5.2.2 2004/02/11 13:15:24 martinea Exp $
+ * $Id: set_commands.c,v 1.23 2004/02/11 13:15:18 martinea Exp $
  *
  * implements the "set" commands in amrecover
  */
index 3624cce669447c63f62c346bde13e3038540643d..872d0b65adda6793766a626ca878eb1d3aa4235b 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: uparse.y,v 1.5.4.2.4.1.2.3 2003/01/01 23:28:52 martinea Exp $
+ * $Id: uparse.y,v 1.11 2003/01/01 23:28:17 martinea Exp $
  *
  * parser for amrecover interactive language
  */
index 40e1075dbd9e33f59a0d5165f668e7da3572abed..efabc189a241e6fd3292332d1e7f19cc6611b112 100644 (file)
@@ -1,4 +1,4 @@
-/* A lexical scanner generated by flex */
+/* A lexical scanner generated by flex*/
 
 /* Scanner skeleton version:
  * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
@@ -134,6 +134,15 @@ extern FILE *yyin, *yyout;
 
 #define unput(c) yyunput( c, yytext_ptr )
 
+/* Some routines like yy_flex_realloc() are emitted as static but are
+   not called by all lexers. This generates warnings in some compilers,
+   notably GCC. Arrange to suppress these. */
+#ifdef __GNUC__
+#define YY_MAY_BE_UNUSED __attribute__((unused))
+#else
+#define YY_MAY_BE_UNUSED
+#endif
+
 /* The following is because we cannot portably get our hands on size_t
  * (without autoconf's help, which isn't available because we want
  * flex-generated scanners to compile on their own).
@@ -240,7 +249,7 @@ YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
 YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
 
 static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED;
 static void yy_flex_free YY_PROTO(( void * ));
 
 #define yy_new_buffer yy_create_buffer
@@ -461,7 +470,7 @@ char *yytext;
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: uscan.l,v 1.14.2.3.4.1.2.2.2.1 2004/02/11 13:03:38 martinea Exp $
+ * $Id: uscan.l,v 1.22 2004/02/11 13:03:29 martinea Exp $
  *
  * lexer for amrecover interactive language
  */
@@ -481,7 +490,7 @@ static int  ll_parse_date P((int type, char *text));
 
 #line 48 "uscan.l"
 static char *string_buf = NULL;
-#line 485 "uscan.c"
+#line 494 "uscan.c"
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -639,7 +648,7 @@ YY_DECL
     /* literal keyword tokens */
 
 
-#line 643 "uscan.c"
+#line 652 "uscan.c"
 
        if ( yy_init )
                {
@@ -951,7 +960,7 @@ YY_RULE_SETUP
 #line 148 "uscan.l"
 ECHO;
        YY_BREAK
-#line 955 "uscan.c"
+#line 964 "uscan.c"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(quotedstring):
        yyterminate();
@@ -1884,7 +1893,7 @@ char *text;
        yyerror("invalid day");
     } else {
        yylval.strval = alloc(DATE_ALLOC_SIZE);
-       ap_snprintf(yylval.strval, DATE_ALLOC_SIZE, "%04d-%02d-%02d", y, m, d);
+       snprintf(yylval.strval, DATE_ALLOC_SIZE, "%04d-%02d-%02d", y, m, d);
        ret = DATE;
     }
     return ret;
index 510d4965e00004a75dd0e7cbca57d816f16ca6c0..66624ae090e53848b7acca0296b066dca908f732 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: uscan.l,v 1.14.2.3.4.1.2.2.2.1 2004/02/11 13:03:38 martinea Exp $
+ * $Id: uscan.l,v 1.22 2004/02/11 13:03:29 martinea Exp $
  *
  * lexer for amrecover interactive language
  */
@@ -194,7 +194,7 @@ char *text;
        yyerror("invalid day");
     } else {
        yylval.strval = alloc(DATE_ALLOC_SIZE);
-       ap_snprintf(yylval.strval, DATE_ALLOC_SIZE, "%04d-%02d-%02d", y, m, d);
+       snprintf(yylval.strval, DATE_ALLOC_SIZE, "%04d-%02d-%02d", y, m, d);
        ret = DATE;
     }
     return ret;
index 0c293028e9d52ecc2c88d20348a5141be2f4a8d8..017b43ddced090840c58bc8f31a8655f9c2ac86c 100644 (file)
@@ -4,28 +4,42 @@ static struct cclass {
        char *chars;
        char *multis;
 } cclasses[] = {
-       "alnum",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789",                           "",
-       "alpha",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
-                                       "",
-       "blank",        " \t",          "",
-       "cntrl",        "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
-\25\26\27\30\31\32\33\34\35\36\37\177",        "",
-       "digit",        "0123456789",   "",
-       "graph",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-                                       "",
-       "lower",        "abcdefghijklmnopqrstuvwxyz",
-                                       "",
-       "print",        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
-                                       "",
-       "punct",        "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-                                       "",
-       "space",        "\t\n\v\f\r ",  "",
-       "upper",        "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
-                                       "",
-       "xdigit",       "0123456789ABCDEFabcdef",
-                                       "",
-       NULL,           0,              ""
+    {
+       "alnum",
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+       ""
+    }, {
+       "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", ""
+    }, {
+       "blank", " \t", ""
+    }, {
+       "cntrl",
+       "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\25\26\27"
+         "\30\31\32\33\34\35\36\37\177",
+       ""
+    }, {
+       "digit", "0123456789", ""
+    }, {
+       "graph",
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+       ""
+    }, {
+       "lower", "abcdefghijklmnopqrstuvwxyz", ""
+    }, {
+       "print",
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
+       ""
+    }, {
+       "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ""
+    }, {
+       "space", "\t\n\v\f\r ", ""
+    }, {
+       "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", ""
+    }, {
+       "xdigit", "0123456789ABCDEFabcdef", ""
+    }, {
+       NULL, NULL, ""
+    }
 };
index 02e86e912e3d7ece4ca8995bcb3e7366208b43f9..a33a8af2a7804bcb12369bd448d7c986d9c12419 100644 (file)
@@ -3,100 +3,100 @@ static struct cname {
        char *name;
        char code;
 } cnames[] = {
-       "NUL",  '\0',
-       "SOH",  '\001',
-       "STX",  '\002',
-       "ETX",  '\003',
-       "EOT",  '\004',
-       "ENQ",  '\005',
-       "ACK",  '\006',
-       "BEL",  '\007',
-       "alert",        '\007',
-       "BS",           '\010',
-       "backspace",    '\b',
-       "HT",           '\011',
-       "tab",          '\t',
-       "LF",           '\012',
-       "newline",      '\n',
-       "VT",           '\013',
-       "vertical-tab", '\v',
-       "FF",           '\014',
-       "form-feed",    '\f',
-       "CR",           '\015',
-       "carriage-return",      '\r',
-       "SO",   '\016',
-       "SI",   '\017',
-       "DLE",  '\020',
-       "DC1",  '\021',
-       "DC2",  '\022',
-       "DC3",  '\023',
-       "DC4",  '\024',
-       "NAK",  '\025',
-       "SYN",  '\026',
-       "ETB",  '\027',
-       "CAN",  '\030',
-       "EM",   '\031',
-       "SUB",  '\032',
-       "ESC",  '\033',
-       "IS4",  '\034',
-       "FS",   '\034',
-       "IS3",  '\035',
-       "GS",   '\035',
-       "IS2",  '\036',
-       "RS",   '\036',
-       "IS1",  '\037',
-       "US",   '\037',
-       "space",                ' ',
-       "exclamation-mark",     '!',
-       "quotation-mark",       '"',
-       "number-sign",          '#',
-       "dollar-sign",          '$',
-       "percent-sign",         '%',
-       "ampersand",            '&',
-       "apostrophe",           '\'',
-       "left-parenthesis",     '(',
-       "right-parenthesis",    ')',
-       "asterisk",     '*',
-       "plus-sign",    '+',
-       "comma",        ',',
-       "hyphen",       '-',
-       "hyphen-minus", '-',
-       "period",       '.',
-       "full-stop",    '.',
-       "slash",        '/',
-       "solidus",      '/',
-       "zero",         '0',
-       "one",          '1',
-       "two",          '2',
-       "three",        '3',
-       "four",         '4',
-       "five",         '5',
-       "six",          '6',
-       "seven",        '7',
-       "eight",        '8',
-       "nine",         '9',
-       "colon",        ':',
-       "semicolon",    ';',
-       "less-than-sign",       '<',
-       "equals-sign",          '=',
-       "greater-than-sign",    '>',
-       "question-mark",        '?',
-       "commercial-at",        '@',
-       "left-square-bracket",  '[',
-       "backslash",            '\\',
-       "reverse-solidus",      '\\',
-       "right-square-bracket", ']',
-       "circumflex",           '^',
-       "circumflex-accent",    '^',
-       "underscore",           '_',
-       "low-line",             '_',
-       "grave-accent",         '`',
-       "left-brace",           '{',
-       "left-curly-bracket",   '{',
-       "vertical-line",        '|',
-       "right-brace",          '}',
-       "right-curly-bracket",  '}',
-       "tilde",                '~',
-       "DEL",  '\177',
-       NULL,   0,
+       { "NUL",                        '\0' },
+       { "SOH",                        '\001' },
+       { "STX",                        '\002' },
+       { "ETX",                        '\003' },
+       { "EOT",                        '\004' },
+       { "ENQ",                        '\005' },
+       { "ACK",                        '\006' },
+       { "BEL",                        '\007' },
+       { "alert",                      '\007' },
+       { "BS",                         '\010' },
+       { "backspace",                  '\b' },
+       { "HT",                         '\011' },
+       { "tab",                        '\t' },
+       { "LF",                         '\012' },
+       { "newline",                    '\n' },
+       { "VT",                         '\013' },
+       { "vertical-tab",               '\v' },
+       { "FF",                         '\014' },
+       { "form-feed",                  '\f' },
+       { "CR",                         '\015' },
+       { "carriage-return",            '\r' },
+       { "SO",                         '\016' },
+       { "SI",                         '\017' },
+       { "DLE",                        '\020' },
+       { "DC1",                        '\021' },
+       { "DC2",                        '\022' },
+       { "DC3",                        '\023' },
+       { "DC4",                        '\024' },
+       { "NAK",                        '\025' },
+       { "SYN",                        '\026' },
+       { "ETB",                        '\027' },
+       { "CAN",                        '\030' },
+       { "EM",                         '\031' },
+       { "SUB",                        '\032' },
+       { "ESC",                        '\033' },
+       { "IS4",                        '\034' },
+       { "FS",                         '\034' },
+       { "IS3",                        '\035' },
+       { "GS",                         '\035' },
+       { "IS2",                        '\036' },
+       { "RS",                         '\036' },
+       { "IS1",                        '\037' },
+       { "US",                         '\037' },
+       { "space",                      ' ' },
+       { "exclamation-mark",           '!' },
+       { "quotation-mark",             '"' },
+       { "number-sign",                '#' },
+       { "dollar-sign",                '$' },
+       { "percent-sign",               '%' },
+       { "ampersand",                  '&' },
+       { "apostrophe",                 '\'' },
+       { "left-parenthesis",           '(' },
+       { "right-parenthesis",          ')' },
+       { "asterisk",                   '*' },
+       { "plus-sign",                  '+' },
+       { "comma",                      ',' },
+       { "hyphen",                     '-' },
+       { "hyphen-minus",               '-' },
+       { "period",                     '.' },
+       { "full-stop",                  '.' },
+       { "slash",                      '/' },
+       { "solidus",                    '/' },
+       { "zero",                       '0' },
+       { "one",                        '1' },
+       { "two",                        '2' },
+       { "three",                      '3' },
+       { "four",                       '4' },
+       { "five",                       '5' },
+       { "six",                        '6' },
+       { "seven",                      '7' },
+       { "eight",                      '8' },
+       { "nine",                       '9' },
+       { "colon",                      ':' },
+       { "semicolon",                  ';' },
+       { "less-than-sign",             '<' },
+       { "equals-sign",                '=' },
+       { "greater-than-sign",          '>' },
+       { "question-mark",              '?' },
+       { "commercial-at",              '@' },
+       { "left-square-bracket",        '[' },
+       { "backslash",                  '\\' },
+       { "reverse-solidus",            '\\' },
+       { "right-square-bracket",       ']' },
+       { "circumflex",                 '^' },
+       { "circumflex-accent",          '^' },
+       { "underscore",                 '_' },
+       { "low-line",                   '_' },
+       { "grave-accent",               '`' },
+       { "left-brace",                 '{' },
+       { "left-curly-bracket",         '{' },
+       { "vertical-line",              '|' },
+       { "right-brace",                '}' },
+       { "right-curly-bracket",        '}' },
+       { "tilde",                      '~' },
+       { "DEL",                        '\177' },
+       { NULL,                         0 }
 };
index d4736827d79289b02b80a32af32446ad8338605f..638bf5ac913d76d719b7403ba7a1cc5db28b0619 100644 (file)
@@ -235,8 +235,8 @@ int ch;
        static char buf[10];
 
        if (isprint(ch) || ch == ' ')
-               ap_snprintf(buf, sizeof(buf), "%c", ch);
+               snprintf(buf, sizeof(buf), "%c", ch);
        else
-               ap_snprintf(buf, sizeof(buf), "\\%o", ch);
+               snprintf(buf, sizeof(buf), "\\%o", ch);
        return(buf);
 }
index 1739cd504c81083670a69029e847017d8373980c..304369eb293cb868e9a1be2f8bb723848b4e93e2 100644 (file)
@@ -33,11 +33,11 @@ struct match {
        struct re_guts *g;
        int eflags;
        regmatch_t *pmatch;     /* [nsub+1] (0 element unused) */
-       char *offp;             /* offsets work from here */
-       char *beginp;           /* start of string -- virtual NUL precedes */
-       char *endp;             /* end of string -- virtual NUL here */
-       char *coldp;            /* can be no match starting before here */
-       char **lastpos;         /* [nplus+1] */
+       const char *offp;       /* offsets work from here */
+       const char *beginp;     /* start of string -- virtual NUL precedes */
+       const char *endp;       /* end of string -- virtual NUL here */
+       const char *coldp;      /* can be no match starting before here */
+       const char **lastpos;   /* [nplus+1] */
        STATEVARS;
        states st;              /* current states */
        states fresh;           /* states for a fresh start */
@@ -59,26 +59,26 @@ struct match {
 
 /*
  - matcher - the actual matching engine
- == static int matcher(register struct re_guts *g, char *string, \
+ == static int matcher(register struct re_guts *g, const char *string, \
  ==    size_t nmatch, regmatch_t pmatch[], int eflags);
  */
 static int                     /* 0 success, REG_NOMATCH failure */
 matcher(g, string, nmatch, pmatch, eflags)
 register struct re_guts *g;
-char *string;
+const char *string;
 size_t nmatch;
 regmatch_t pmatch[];
 int eflags;
 {
-       register char *endp;
+       register const char *endp;
        register int i;
        struct match mv;
        register struct match *m = &mv;
-       register char *dp;
+       register const char *dp;
        const register sopno gf = g->firststate+1;      /* +1 for OEND */
        const register sopno gl = g->laststate;
-       char *start;
-       char *stop;
+       const char *start;
+       const char *stop;
 
        /* simplify the situation where possible */
        if (g->cflags&REG_NOSUB)
@@ -156,8 +156,8 @@ int eflags;
                        dp = dissect(m, m->coldp, endp, gf, gl);
                } else {
                        if (g->nplus > 0 && m->lastpos == NULL)
-                               m->lastpos = (char **)malloc((g->nplus+1) *
-                                                       sizeof(char *));
+                               m->lastpos = (const char **)malloc((g->nplus+1) *
+                                                       sizeof(const char *));
                        if (g->nplus > 0 && m->lastpos == NULL) {
                                free(m->pmatch);
                                STATETEARDOWN(m);
@@ -216,39 +216,39 @@ int eflags;
        }
 
        if (m->pmatch != NULL)
-               free((char *)m->pmatch);
+               free((void *)m->pmatch);
        if (m->lastpos != NULL)
-               free((char *)m->lastpos);
+               free((void *)m->lastpos);
        STATETEARDOWN(m);
        return(0);
 }
 
 /*
  - dissect - figure out what matched what, no back references
- == static char *dissect(register struct match *m, char *start, \
+ == static const char *dissect(register struct match *m, char *start, \
  ==    char *stop, sopno startst, sopno stopst);
  */
-static char *                  /* == stop (success) always */
+static const char *                    /* == stop (success) always */
 dissect(m, start, stop, startst, stopst)
 register struct match *m;
-char *start;
-char *stop;
+const char *start;
+const char *stop;
 sopno startst;
 sopno stopst;
 {
        register int i;
        register sopno ss;      /* start sop of current subRE */
        register sopno es;      /* end sop of current subRE */
-       register char *sp;      /* start of string matched by it */
-       register char *stp;     /* string matched by it cannot pass here */
-       register char *rest;    /* start of rest of string */
-       register char *tail;    /* string unmatched by rest of RE */
+       register const char *sp;        /* start of string matched by it */
+       register const char *stp;       /* string matched by it cannot pass here */
+       register const char *rest;      /* start of rest of string */
+       register const char *tail;      /* string unmatched by rest of RE */
        register sopno ssub;    /* start sop of subsubRE */
        register sopno esub;    /* end sop of subsubRE */
-       register char *ssp;     /* start of string matched by subsubRE */
-       register char *sep;     /* end of string matched by subsubRE */
-       register char *oldssp;  /* previous ssp */
-       register char *dp;
+       register const char *ssp;       /* start of string matched by subsubRE */
+       register const char *sep;       /* end of string matched by subsubRE */
+       register const char *oldssp;    /* previous ssp */
+       register const char *dp;
 
        AT("diss", start, stop, startst, stopst);
        sp = start;
@@ -413,25 +413,25 @@ sopno stopst;
 
 /*
  - backref - figure out what matched what, figuring in back references
- == static char *backref(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst, sopno lev);
+ == static const char *backref(register struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst, sopno lev);
  */
-static char *                  /* == stop (success) or NULL (failure) */
+static const char *            /* == stop (success) or NULL (failure) */
 backref(m, start, stop, startst, stopst, lev)
 register struct match *m;
-char *start;
-char *stop;
+const char *start;
+const char *stop;
 sopno startst;
 sopno stopst;
 sopno lev;                     /* PLUS nesting level */
 {
        register int i;
        register sopno ss;      /* start sop of current subRE */
-       register char *sp;      /* start of string matched by it */
+       register const char *sp;/* start of string matched by it */
        register sopno ssub;    /* start sop of subsubRE */
        register sopno esub;    /* end sop of subsubRE */
-       register char *ssp;     /* start of string matched by subsubRE */
-       register char *dp;
+       register const char *ssp;/* start of string matched by subsubRE */
+       register const char *dp;
        register size_t len;
        register int hard;
        register sop s;
@@ -613,31 +613,31 @@ sopno lev;                        /* PLUS nesting level */
        /* "can't happen" */
        assert(nope);
        /* NOTREACHED */
-       return((char *)NULL);   /* dummy */
+       return((const char *)NULL);     /* dummy */
 }
 
 /*
  - fast - step through the string at top speed
- == static char *fast(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst);
+ == static const char *fast(register struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst);
  */
-static char *                  /* where tentative match ended, or NULL */
+static const char *                    /* where tentative match ended, or NULL */
 fast(m, start, stop, startst, stopst)
 register struct match *m;
-char *start;
-char *stop;
+const char *start;
+const char *stop;
 sopno startst;
 sopno stopst;
 {
        register states st = m->st;
        register states fresh = m->fresh;
        register states tmp = m->tmp;
-       register char *p = start;
+       register const char *p = start;
        register int c = (start == m->beginp) ? OUT : *(start-1);
        register int lastc;     /* previous c */
        register int flagch;
        register int i;
-       register char *coldp;   /* last p after which no match was underway */
+       register const char *coldp;/* last p after which no match was underway */
 
        CLEAR(st);
        SET1(st, startst);
@@ -709,26 +709,26 @@ sopno stopst;
 
 /*
  - slow - step through the string more deliberately
- == static char *slow(register struct match *m, char *start, \
- ==    char *stop, sopno startst, sopno stopst);
+ == static const char *slow(register struct match *m, const char *start, \
+ ==    const char *stop, sopno startst, sopno stopst);
  */
-static char *                  /* where it ended */
+static const char *                    /* where it ended */
 slow(m, start, stop, startst, stopst)
 register struct match *m;
-char *start;
-char *stop;
+const char *start;
+const char *stop;
 sopno startst;
 sopno stopst;
 {
        register states st = m->st;
        register states empty = m->empty;
        register states tmp = m->tmp;
-       register char *p = start;
+       register const char *p = start;
        register int c = (start == m->beginp) ? OUT : *(start-1);
        register int lastc;     /* previous c */
        register int flagch;
        register int i;
-       register char *matchp;  /* last p at which a match ended */
+       register const char *matchp;    /* last p at which a match ended */
 
        AT("slow", start, stop, startst, stopst);
        CLEAR(st);
@@ -959,16 +959,16 @@ FILE *d;
 /* 
  - at - print current situation
  == #ifdef REDEBUG
- == static void at(struct match *m, char *title, char *start, char *stop, \
- ==                                            sopno startst, sopno stopst);
+ == static void at(struct match *m, char *title, const char *start, \
+ ==                    const char *stop, sopno startst, sopno stopst);
  == #endif
  */
 static void
 at(m, title, start, stop, startst, stopst)
 struct match *m;
-char *title;
-char *start;
-char *stop;
+const char *title;
+const char *start;
+const char *stop;
 sopno startst;
 sopno stopst;
 {
@@ -1000,9 +1000,9 @@ int ch;
        static char pbuf[10];
 
        if (isprint(ch) || ch == ' ')
-               ap_snprintf(pbuf, sizeof(pbuf), "%c", ch);
+               snprintf(pbuf, sizeof(pbuf), "%c", ch);
        else
-               ap_snprintf(pbuf, sizeof(pbuf), "\\%o", ch);
+               snprintf(pbuf, sizeof(pbuf), "\\%o", ch);
        return(pbuf);
 }
 #endif
index 1785df36788ca39fe454fc15c450fd0292dc1abf..9105cc5e8750bf866c80bb3d353eaf88b0cc1602 100644 (file)
@@ -427,7 +427,7 @@ char *should;
                                (sub.rm_so != -1 && sub.rm_eo == -1) ||
                                (sub.rm_so != -1 && sub.rm_so < 0) ||
                                (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
-               ap_snprintf(grump, sizeof(grump),
+               snprintf(grump, sizeof(grump),
                            "start %ld end %ld", (long)sub.rm_so,
                            (long)sub.rm_eo);
                return(grump);
@@ -441,7 +441,7 @@ char *should;
 
        /* check for in range */
        if (sub.rm_eo > strlen(str)) {
-               ap_snprintf(grump, sizeof(grump),
+               snprintf(grump, sizeof(grump),
                            "start %ld end %ld, past end of string",
                            (long)sub.rm_so, (long)sub.rm_eo);
                return(grump);
@@ -453,13 +453,13 @@ char *should;
 
        /* check for not supposed to match */
        if (should == NULL) {
-               ap_snprintf(grump, sizeof(grump), "matched `%.*s'", len, p);
+               snprintf(grump, sizeof(grump), "matched `%.*s'", len, p);
                return(grump);
        }
 
        /* check for wrong match */
        if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
-               ap_snprintf(grump, sizeof(grump),
+               snprintf(grump, sizeof(grump),
                            "matched `%.*s' instead", len, p);
                return(grump);
        }
@@ -473,7 +473,7 @@ char *should;
        if (shlen == 0)
                shlen = 1;      /* force check for end-of-string */
        if (strncmp(p, at, shlen) != 0) {
-               ap_snprintf(grump, sizeof(grump), "matched null at `%.20s'", p);
+               snprintf(grump, sizeof(grump), "matched null at `%.20s'", p);
                return(grump);
        }
        return(NULL);
@@ -507,7 +507,7 @@ char *name;
        size_t n;
        regex_t re;
 
-       ap_snprintf(efbuf, sizeof(efbuf), "REG_%s", name);
+       snprintf(efbuf, sizeof(efbuf), "REG_%s", name);
        assert(strlen(efbuf) < sizeof(efbuf));
        re.re_endp = efbuf;
        (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
index 42c3b8654873f3165562b3b8e3c32b92c9143399..08e8a9fcf4acce40b497f88e6b25f1fed7a61046 100644 (file)
@@ -192,8 +192,8 @@ register struct parse *p;
 int stop;                      /* character this ERE should end at */
 {
        register char c;
-       register sopno prevback;
-       register sopno prevfwd;
+       register sopno prevback = 0;
+       register sopno prevfwd = 0;
        register sopno conc;
        register int first = 1;         /* is this the first alternative? */
 
@@ -1169,9 +1169,10 @@ register char *cp;
        cs->multis[cs->smultis - 1] = '\0';
 }
 
+#if 0
 /*
- - mcsub - subtract a collating element from a cset
- == static void mcsub(register cset *cs, register char *cp);
- mcsub - subtract a collating element from a cset
== static void mcsub(register cset *cs, register char *cp);
  */
 static void
 mcsub(cs, cp)
@@ -1197,8 +1198,8 @@ register char *cp;
 }
 
 /*
- - mcin - is a collating element in a cset?
- == static int mcin(register cset *cs, register char *cp);
- mcin - is a collating element in a cset?
== static int mcin(register cset *cs, register char *cp);
  */
 static int
 mcin(cs, cp)
@@ -1209,8 +1210,8 @@ register char *cp;
 }
 
 /*
- - mcfind - find a collating element in a cset
- == static char *mcfind(register cset *cs, register char *cp);
- mcfind - find a collating element in a cset
== static char *mcfind(register cset *cs, register char *cp);
  */
 static char *
 mcfind(cs, cp)
@@ -1226,6 +1227,7 @@ register char *cp;
                        return(p);
        return(NULL);
 }
+#endif /* 0 */
 
 /*
  - mcinvert - invert the list of collating elements in a cset
@@ -1496,7 +1498,7 @@ register struct re_guts *g;
 {
        register sop *scan;
        sop *start;
-       register sop *newstart;
+       register sop *newstart = NULL;
        register sopno newlen;
        register sop s;
        register char *cp;
@@ -1508,7 +1510,7 @@ register struct re_guts *g;
 
        /* find the longest OCHAR sequence in strip */
        newlen = 0;
-       scan = g->strip + 1;
+       start = scan = g->strip + 1;
        do {
                s = *scan++;
                switch (OP(s)) {
index ee27c6a1fdd4da862c697615ef9d8ae05ca619bf..35cc1eba131a24c827725b5599d23e32eebf05be 100644 (file)
@@ -35,24 +35,24 @@ static struct rerr {
        char *name;
        char *explain;
 } rerrs[] = {
-       REG_OKAY,       "REG_OKAY",     "no errors detected",
-       REG_NOMATCH,    "REG_NOMATCH",  "regexec() failed to match",
-       REG_BADPAT,     "REG_BADPAT",   "invalid regular expression",
-       REG_ECOLLATE,   "REG_ECOLLATE", "invalid collating element",
-       REG_ECTYPE,     "REG_ECTYPE",   "invalid character class",
-       REG_EESCAPE,    "REG_EESCAPE",  "trailing backslash (\\)",
-       REG_ESUBREG,    "REG_ESUBREG",  "invalid backreference number",
-       REG_EBRACK,     "REG_EBRACK",   "brackets ([ ]) not balanced",
-       REG_EPAREN,     "REG_EPAREN",   "parentheses not balanced",
-       REG_EBRACE,     "REG_EBRACE",   "braces not balanced",
-       REG_BADBR,      "REG_BADBR",    "invalid repetition count(s)",
-       REG_ERANGE,     "REG_ERANGE",   "invalid character range",
-       REG_ESPACE,     "REG_ESPACE",   "out of memory",
-       REG_BADRPT,     "REG_BADRPT",   "repetition-operator operand invalid",
-       REG_EMPTY,      "REG_EMPTY",    "empty (sub)expression",
-       REG_ASSERT,     "REG_ASSERT",   "\"can't happen\" -- you found a bug",
-       REG_INVARG,     "REG_INVARG",   "invalid argument to regex routine",
-       -1,             "",             "*** unknown regexp error code ***",
+       { REG_OKAY,     "REG_OKAY",     "no errors detected"},
+       { REG_NOMATCH,  "REG_NOMATCH",  "regexec() failed to match"},
+       { REG_BADPAT,   "REG_BADPAT",   "invalid regular expression"},
+       { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
+       { REG_ECTYPE,   "REG_ECTYPE",   "invalid character class"},
+       { REG_EESCAPE,  "REG_EESCAPE",  "trailing backslash (\\)"},
+       { REG_ESUBREG,  "REG_ESUBREG",  "invalid backreference number"},
+       { REG_EBRACK,   "REG_EBRACK",   "brackets ([ ]) not balanced"},
+       { REG_EPAREN,   "REG_EPAREN",   "parentheses not balanced"},
+       { REG_EBRACE,   "REG_EBRACE",   "braces not balanced"},
+       { REG_BADBR,    "REG_BADBR",    "invalid repetition count(s)"},
+       { REG_ERANGE,   "REG_ERANGE",   "invalid character range"},
+       { REG_ESPACE,   "REG_ESPACE",   "out of memory"},
+       { REG_BADRPT,   "REG_BADRPT",   "repetition-operator operand invalid"},
+       { REG_EMPTY,    "REG_EMPTY",    "empty (sub)expression"},
+       { REG_ASSERT,   "REG_ASSERT",   "\"can't happen\" -- you found a bug"},
+       { REG_INVARG,   "REG_INVARG",   "invalid argument to regex routine"},
+       { -1,           "",             "*** unknown regexp error code ***"}
 };
 
 /*
@@ -85,7 +85,7 @@ size_t errbuf_size;
                                strncpy(convbuf, r->name, sizeof(convbuf)-1);
                                convbuf[sizeof(convbuf)-1] = '\0';
                        } else {
-                               ap_snprintf(convbuf, sizeof(convbuf),
+                               snprintf(convbuf, sizeof(convbuf),
                                            "REG_0x%x", target);
                        }
                        assert(strlen(convbuf) < sizeof(convbuf));
@@ -125,6 +125,6 @@ int buflen;
        if (r->code < 0)
                return("0");
 
-       ap_snprintf(localbuf, buflen, "%d", r->code);
+       snprintf(localbuf, buflen, "%d", r->code);
        return(localbuf);
 }
index 71c6d3abe0c8aa3251c512b3d04289760dafe2a3..0e86b37312c6c779ae8bdb6bbe2ed839096b984f 100644 (file)
@@ -16,7 +16,9 @@
 #include "utils.h"
 #include "regex2.h"
 
+#ifndef NDEBUG
 static int nope = 0;           /* for use in asserts; shuts lint up */
+#endif
 
 /* macros for manipulating states, small version */
 #define        states  long
@@ -132,7 +134,7 @@ int eflags;
        eflags = GOODFLAGS(eflags);
 
        if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
-               return(smatcher(g, (char *)string, nmatch, pmatch, eflags));
+               return(smatcher(g, string, nmatch, pmatch, eflags));
        else
-               return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));
+               return(lmatcher(g, string, nmatch, pmatch, eflags));
 }
index c6886294fc8ce482c76dda27905e5a2a3040426a..ac4ee903decb687a7ee16a60874c2011a8c3c2ad 100644 (file)
@@ -1,10 +1,14 @@
 # Makefile for Amanda restore programs.
 
-INCLUDES =             -I$(top_srcdir)/common-src -I$(top_srcdir)/tape-src -I$(top_srcdir)/server-src
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/tape-src     \
+               -I$(top_srcdir)/server-src
 
+lib_LTLIBRARIES =      librestore.la
 LIB_EXTENSION = la
 
-sbin_PROGRAMS =        amrestore
+sbin_PROGRAMS =        amrestore amfetchdump
 
 libexec_PROGRAMS =     amidxtaped
 
@@ -15,15 +19,20 @@ libexec_PROGRAMS =  amidxtaped
 # routines, and second to pick up any references in the other libraries.
 ###
 
-LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-       ../tape-src/libamtape.$(LIB_EXTENSION) \
+LDADD = librestore.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 
 amidxtaped_SOURCES =   amidxtaped.c
-amidxtaped_LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-                   ../server-src/libamserver.$(LIB_EXTENSION) \
+
+amfetchdump_SOURCES =  amfetchdump.c
+
+librestore_la_SOURCES  =       restore.c
+librestore_la_LDFLAGS  =       -release $(VERSION)
+librestore_la_LIBADD   =       ../common-src/libamanda.$(LIB_EXTENSION) \
                    ../tape-src/libamtape.$(LIB_EXTENSION) \
-                   ../common-src/libamanda.$(LIB_EXTENSION)
+                  ../server-src/libamserver.$(LIB_EXTENSION)
+
+noinst_HEADERS = restore.h
 
 install-exec-hook:
        @list="$(sbin_PROGRAMS)"; \
index a5f06980c969bf37c181f2b50a81c6129ffe9d54..e75b7f75a4f676da373a4d7362f71cadbcdb7824 100644 (file)
@@ -16,7 +16,9 @@
 
 # Makefile for Amanda restore programs.
 
-SOURCES = $(amidxtaped_SOURCES) amrestore.c
+
+
+SOURCES = $(librestore_la_SOURCES) $(amfetchdump_SOURCES) $(amidxtaped_SOURCES) amrestore.c
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -41,10 +43,11 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-sbin_PROGRAMS = amrestore$(EXEEXT)
+sbin_PROGRAMS = amrestore$(EXEEXT) amfetchdump$(EXEEXT)
 libexec_PROGRAMS = amidxtaped$(EXEEXT)
 subdir = restore-src
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
        $(top_srcdir)/configure.in
@@ -53,21 +56,38 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/config/config.h
 CONFIG_CLEAN_FILES =
-am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)"
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" \
+       "$(DESTDIR)$(sbindir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+librestore_la_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../server-src/libamserver.$(LIB_EXTENSION)
+am_librestore_la_OBJECTS = restore.lo
+librestore_la_OBJECTS = $(am_librestore_la_OBJECTS)
 libexecPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(libexec_PROGRAMS) $(sbin_PROGRAMS)
+am_amfetchdump_OBJECTS = amfetchdump.$(OBJEXT)
+amfetchdump_OBJECTS = $(am_amfetchdump_OBJECTS)
+amfetchdump_LDADD = $(LDADD)
+amfetchdump_DEPENDENCIES = librestore.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION)
 am_amidxtaped_OBJECTS = amidxtaped.$(OBJEXT)
 amidxtaped_OBJECTS = $(am_amidxtaped_OBJECTS)
-amidxtaped_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       ../server-src/libamserver.$(LIB_EXTENSION) \
-       ../tape-src/libamtape.$(LIB_EXTENSION) \
+amidxtaped_LDADD = $(LDADD)
+amidxtaped_DEPENDENCIES = librestore.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amrestore_SOURCES = amrestore.c
 amrestore_OBJECTS = amrestore.$(OBJEXT)
 amrestore_LDADD = $(LDADD)
-amrestore_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
-       ../tape-src/libamtape.$(LIB_EXTENSION) \
+amrestore_DEPENDENCIES = librestore.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
 depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -80,8 +100,11 @@ LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
 CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
        $(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(amidxtaped_SOURCES) amrestore.c
-DIST_SOURCES = $(amidxtaped_SOURCES) amrestore.c
+SOURCES = $(librestore_la_SOURCES) $(amfetchdump_SOURCES) \
+       $(amidxtaped_SOURCES) amrestore.c
+DIST_SOURCES = $(librestore_la_SOURCES) $(amfetchdump_SOURCES) \
+       $(amidxtaped_SOURCES) amrestore.c
+HEADERS = $(noinst_HEADERS)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -132,7 +155,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -144,9 +169,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -159,6 +187,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -221,10 +250,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -275,7 +307,12 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-INCLUDES = -I$(top_srcdir)/common-src -I$(top_srcdir)/tape-src -I$(top_srcdir)/server-src
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/tape-src     \
+               -I$(top_srcdir)/server-src
+
+lib_LTLIBRARIES = librestore.la
 LIB_EXTENSION = la
 
 ###
@@ -284,16 +321,18 @@ LIB_EXTENSION = la
 # need to list libamanda twice here, first to override the system library
 # routines, and second to pick up any references in the other libraries.
 ###
-LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-       ../tape-src/libamtape.$(LIB_EXTENSION) \
+LDADD = librestore.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 
 amidxtaped_SOURCES = amidxtaped.c
-amidxtaped_LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
-                   ../server-src/libamserver.$(LIB_EXTENSION) \
+amfetchdump_SOURCES = amfetchdump.c
+librestore_la_SOURCES = restore.c
+librestore_la_LDFLAGS = -release $(VERSION)
+librestore_la_LIBADD = ../common-src/libamanda.$(LIB_EXTENSION) \
                    ../tape-src/libamtape.$(LIB_EXTENSION) \
-                   ../common-src/libamanda.$(LIB_EXTENSION)
+                  ../server-src/libamserver.$(LIB_EXTENSION)
 
+noinst_HEADERS = restore.h
 all: all-am
 
 .SUFFIXES:
@@ -327,6 +366,35 @@ $(top_srcdir)/configure:  $(am__configure_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+           $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+         $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+librestore.la: $(librestore_la_OBJECTS) $(librestore_la_DEPENDENCIES) 
+       $(LINK) -rpath $(libdir) $(librestore_la_LDFLAGS) $(librestore_la_OBJECTS) $(librestore_la_LIBADD) $(LIBS)
 install-libexecPROGRAMS: $(libexec_PROGRAMS)
        @$(NORMAL_INSTALL)
        test -z "$(libexecdir)" || $(mkdir_p) "$(DESTDIR)$(libexecdir)"
@@ -383,6 +451,9 @@ clean-sbinPROGRAMS:
          echo " rm -f $$p $$f"; \
          rm -f $$p $$f ; \
        done
+amfetchdump$(EXEEXT): $(amfetchdump_OBJECTS) $(amfetchdump_DEPENDENCIES) 
+       @rm -f amfetchdump$(EXEEXT)
+       $(LINK) $(amfetchdump_LDFLAGS) $(amfetchdump_OBJECTS) $(amfetchdump_LDADD) $(LIBS)
 amidxtaped$(EXEEXT): $(amidxtaped_OBJECTS) $(amidxtaped_DEPENDENCIES) 
        @rm -f amidxtaped$(EXEEXT)
        $(LINK) $(amidxtaped_LDFLAGS) $(amidxtaped_OBJECTS) $(amidxtaped_LDADD) $(LIBS)
@@ -396,8 +467,10 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfetchdump.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amidxtaped.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amrestore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/restore.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@@ -507,9 +580,9 @@ distdir: $(DISTFILES)
        done
 check-am: all-am
 check: check-am
-all-am: Makefile $(PROGRAMS)
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
 installdirs:
-       for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)"; do \
+       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)"; do \
          test -z "$$dir" || $(mkdir_p) "$$dir"; \
        done
 install: install-am
@@ -538,8 +611,8 @@ maintainer-clean-generic:
        @echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \
-       clean-sbinPROGRAMS mostlyclean-am
+clean-am: clean-generic clean-libLTLIBRARIES clean-libexecPROGRAMS \
+       clean-libtool clean-sbinPROGRAMS mostlyclean-am
 
 distclean: distclean-am
        -rm -rf ./$(DEPDIR)
@@ -559,7 +632,8 @@ info-am:
 
 install-data-am:
 
-install-exec-am: install-libexecPROGRAMS install-sbinPROGRAMS
+install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS \
+       install-sbinPROGRAMS
        @$(NORMAL_INSTALL)
        $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
 
@@ -587,22 +661,24 @@ ps: ps-am
 
 ps-am:
 
-uninstall-am: uninstall-info-am uninstall-libexecPROGRAMS \
-       uninstall-sbinPROGRAMS
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
+       uninstall-libexecPROGRAMS uninstall-sbinPROGRAMS
 
 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-       clean-libexecPROGRAMS clean-libtool clean-sbinPROGRAMS ctags \
-       distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-exec install-exec-am install-exec-hook \
-       install-info install-info-am install-libexecPROGRAMS \
-       install-man install-sbinPROGRAMS install-strip installcheck \
+       clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \
+       clean-sbinPROGRAMS ctags distclean distclean-compile \
+       distclean-generic distclean-libtool distclean-tags distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-exec install-exec-am \
+       install-exec-hook install-info install-info-am \
+       install-libLTLIBRARIES install-libexecPROGRAMS install-man \
+       install-sbinPROGRAMS install-strip installcheck \
        installcheck-am installdirs maintainer-clean \
        maintainer-clean-generic mostlyclean mostlyclean-compile \
        mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
        tags uninstall uninstall-am uninstall-info-am \
-       uninstall-libexecPROGRAMS uninstall-sbinPROGRAMS
+       uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \
+       uninstall-sbinPROGRAMS
 
 
 install-exec-hook:
diff --git a/restore-src/amfetchdump.c b/restore-src/amfetchdump.c
new file mode 100644 (file)
index 0000000..e94ce29
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1998 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: amfetchdump.c,v 1.7 2006/03/14 13:12:01 martinea Exp $
+ *
+ * retrieves specific dumps from a set of amanda tapes
+ */
+
+#include "amanda.h"
+#include "tapeio.h"
+#include "fileheader.h"
+#include "util.h"
+#include "restore.h"
+#include "diskfile.h"
+#include "tapefile.h"
+#include "find.h"
+#include "changer.h"
+#include "logfile.h"
+
+#define CREAT_MODE     0640
+
+extern char *rst_conf_logdir;
+extern char *rst_conf_logfile;
+extern char *config_dir;
+int get_lock = 0;
+
+typedef struct needed_tapes_s {
+    char *label;
+    int isafile;
+    find_result_t *files;
+    struct needed_tapes_s *next;
+    struct needed_tapes_s *prev;
+} needed_tape_t;
+
+/* local functions */
+
+void errexit P((void));
+void handle_sigpipe P((int sig));
+tapelist_t *list_needed_tapes P((match_list_t *match_list));
+void usage P((void));
+int main P((int argc, char **argv));
+
+/* exit routine */
+static int parent_pid = -1;
+static void cleanup P((void));
+
+void errexit()
+/*
+ * Do exit(2) after an error, rather than exit(1).
+ */
+{
+    exit(2);
+}
+
+
+void usage()
+/*
+ * Print usage message and terminate.
+ */
+{
+    fprintf(stderr, "Usage: amfetchdump [options] config hostname [diskname [datestamp [level [hostname [diskname [datestamp [level ... ]]]]]]]\n\n");
+    fprintf(stderr, "Goes and grabs a dump from tape, moving tapes around and assembling parts as\n");
+    fprintf(stderr, "necessary.  Files are restored to the current directory, unless otherwise\nspecified.\n\n");
+    fprintf(stderr, "  -p Pipe exactly *one* complete dumpfile to stdout, instead of to disk.\n");
+    fprintf(stderr, "  -o <output dir> Restore files to this directory.\n");
+    fprintf(stderr, "  -d <device> Force restoration from a particular tape device.\n");
+    fprintf(stderr, "  -c Compress output, fastest method available.\n");
+    fprintf(stderr, "  -C Compress output, best filesize method available.\n");
+    fprintf(stderr, "  -l Leave dumps (un)compressed, whichever way they were originally on tape.\n");
+    fprintf(stderr, "  -a Assume all tapes are available via changer, do not prompt for initial load.\n");
+    fprintf(stderr, "  -i <dst_file> Search through tapes and write out an inventory while we\n     restore.  Useful only if normal logs are unavailable.\n");
+    fprintf(stderr, "  -w Wait to put split dumps together until all chunks have been restored.\n");
+    fprintf(stderr, "  -n Do not reassemble split dumpfiles.\n");
+    fprintf(stderr, "  -k Skip the rewind/label read when reading a new tape.\n");
+    fprintf(stderr, "  -s Do not use fast forward to skip files we won't restore.  Use only if fsf\n     causes your tapes to skip too far.\n");
+    fprintf(stderr, "  -b <blocksize> Force a particular block size (default is 32kb).\n");
+    exit(1);
+}
+
+/*
+ * Build the list of tapes we'll be wanting, and include data about the
+ * files we want from said tapes while we're at it (the whole find_result
+ * should do fine)
+ */
+tapelist_t *list_needed_tapes(match_list)
+match_list_t *match_list;
+{
+    needed_tape_t *needed_tapes = NULL, *curtape = NULL;
+    disklist_t diskqp;
+    match_list_t *me = NULL;
+    find_result_t *alldumps = NULL;
+    tapelist_t *tapes = NULL;
+    int numtapes = 0;
+    char *conf_diskfile, *conf_tapelist;
+
+    /* For disks and tape lists */
+    conf_diskfile = getconf_str(CNF_DISKFILE);
+    conf_tapelist = getconf_str(CNF_TAPELIST);
+    if (*conf_diskfile == '/') {
+        conf_diskfile = stralloc(conf_diskfile);
+    } else {
+        conf_diskfile = stralloc2(config_dir, conf_diskfile);
+    }
+    if(read_diskfile(conf_diskfile, &diskqp) != 0) {
+        error("could not load disklist \"%s\"", conf_diskfile);
+    }
+    if (*conf_tapelist == '/') {
+        conf_tapelist = stralloc(conf_tapelist);
+    } else {
+        conf_tapelist = stralloc2(config_dir, conf_tapelist);
+    }
+    if(read_tapelist(conf_tapelist)) {
+        error("could not load tapelist \"%s\"", conf_tapelist);
+    }
+    amfree(conf_diskfile);
+    amfree(conf_tapelist);
+
+    /* Grab a find_output_t of all logged dumps */
+    alldumps = find_dump(1, &diskqp); 
+    free_disklist(&diskqp);
+    if(alldumps == NULL){
+        fprintf(stderr, "No dump records found\n");
+        exit(1);
+    }
+    /* Compare all known dumps to our match list, note what we'll need */
+    for(me = match_list; me; me = me->next) {
+       find_result_t *curmatch = NULL; 
+       find_result_t *matches = NULL;  
+
+       matches = dumps_match(alldumps, me->hostname, me->diskname,
+                                me->datestamp, me->level, 1);
+       sort_find_result("Dhklp", &matches);
+       for(curmatch = matches; curmatch; curmatch = curmatch->next){
+           int havetape = 0;
+           if(strcmp("OK", curmatch->status)){
+               fprintf(stderr,"Dump %d %s %s %d had status '%s', skipping\n",
+                                curmatch->datestamp, curmatch->hostname,
+                                curmatch->diskname, curmatch->level,
+                                curmatch->status);
+               continue;
+           }
+           for(curtape = needed_tapes; curtape; curtape = curtape->next) {
+               if(!strcmp(curtape->label, curmatch->label)){
+                   find_result_t *rsttemp = NULL;
+                   find_result_t *rstfile = alloc(sizeof(find_result_t));
+                   int keep = 1;
+
+                   memcpy(rstfile, curmatch, sizeof(find_result_t));
+
+                   havetape = 1;
+
+                   for(rsttemp = curtape->files;
+                           rsttemp;
+                           rsttemp=rsttemp->next){
+                       if(rstfile->filenum == rsttemp->filenum){
+                           fprintf(stderr, "Seeing multiple entries for tape %s file %d, using most recent\n", curtape->label, rstfile->filenum);
+                           keep = 0;
+                       }
+                   }
+                   if(!keep){
+                       amfree(rstfile);
+                       break;
+                   }
+                   rstfile->next = curtape->files;
+
+                   if(curmatch->filenum < 1) curtape->isafile = 1;
+                   else curtape->isafile = 0;
+                   curtape->files = rstfile;
+                   break;
+               }
+           }
+           if(!havetape){
+               find_result_t *rstfile = alloc(sizeof(find_result_t));
+               needed_tape_t *newtape =
+                                         alloc(sizeof(needed_tape_t));
+               memcpy(rstfile, curmatch, sizeof(find_result_t));
+               rstfile->next = NULL;
+               newtape->files = rstfile;
+               if(curmatch->filenum < 1) newtape->isafile = 1;
+               else newtape->isafile = 0;
+               newtape->label = curmatch->label;
+               if(needed_tapes){
+                   needed_tapes->prev->next = newtape;
+                   newtape->prev = needed_tapes->prev;
+                   needed_tapes->prev = newtape;
+               }
+               else{
+                   needed_tapes = newtape;
+                   needed_tapes->prev = needed_tapes;
+               }
+               newtape->next = NULL;
+               numtapes++;
+#if 0
+//             free_find_result(rstfile);
+#endif
+           } /* if(!havetape) */
+
+       } /* for(curmatch = matches ... */
+    } /* for(me = match_list ... */
+
+    if(numtapes == 0){
+      fprintf(stderr, "No matching dumps found\n");
+      exit(1);
+    }
+
+    /* stick that list in a structure that librestore will understand */
+    for(curtape = needed_tapes; curtape; curtape = curtape->next) {
+       find_result_t *curfind = NULL;
+       for(curfind = curtape->files; curfind; curfind = curfind->next) {
+           tapes = append_to_tapelist(tapes, curtape->label,
+                                      curfind->filenum, curtape->isafile);
+       }
+    }
+
+    fprintf(stderr, "%d tape(s) needed for restoration\n", numtapes);
+    return(tapes);
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+/*
+ * Parses command line, then loops through all files on tape, restoring
+ * files that match the command line criteria.
+ */
+{
+    extern int optind;
+    int opt;
+    char *errstr;
+    match_list_t *match_list = NULL;
+    match_list_t *me = NULL;
+    int fd;
+    char *config_name = NULL;
+    char *conffile = NULL;
+    tapelist_t *needed_tapes = NULL;
+    char *e;
+    int arg_state;
+    rst_flags_t *rst_flags;
+    struct passwd *pwent;
+
+    for(fd = 3; fd < FD_SETSIZE; fd++) {
+       /*
+        * Make sure nobody spoofs us with a lot of extra open files
+        * that would cause an open we do to get a very high file
+        * descriptor, which in turn might be used as an index into
+        * an array (e.g. an fd_set).
+        */
+       close(fd);
+    }
+
+    set_pname("amfetchdump");
+
+#ifdef FORCE_USERID
+
+    /* we'd rather not run as root */
+
+    if(client_uid == (uid_t) -1 && (pwent = getpwnam(CLIENT_LOGIN)) != NULL) {
+       client_uid = pwent->pw_uid;
+       client_gid = pwent->pw_gid;
+       endpwent();
+    }
+    if(geteuid() == 0) {
+       if(client_uid == (uid_t) -1) {
+           error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN);
+       }
+
+       initgroups(CLIENT_LOGIN, client_gid);
+       setgid(client_gid);
+       setuid(client_uid);
+    }
+
+#endif /* FORCE_USERID */
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    erroutput_type = ERR_INTERACTIVE;
+
+    onerror(errexit);
+
+    if(argc <= 1) usage();
+
+    rst_flags = new_rst_flags();
+    rst_flags->wait_tape_prompt = 1;
+    
+    /* handle options */
+    while( (opt = getopt(argc, argv, "alht:scCpb:nwi:d:o:")) != -1) {
+       switch(opt) {
+       case 'b': rst_flags->compress = 1; break;
+            rst_flags->blocksize = strtol(optarg, &e, 10);
+            if(*e == 'k' || *e == 'K') {
+               rst_flags->blocksize *= 1024;
+           } else if(*e == 'm' || *e == 'M') {
+               rst_flags->blocksize *= 1024 * 1024;
+           } else if(*e != '\0') {
+               error("invalid blocksize value \"%s\"", optarg);
+           }
+           if(rst_flags->blocksize < DISK_BLOCK_BYTES) {
+               error("minimum block size is %dk", DISK_BLOCK_BYTES / 1024);
+           }
+           break;
+       case 'c': rst_flags->compress = 1; break;
+       case 'o': rst_flags->restore_dir = stralloc(optarg) ; break;
+       case 'd': rst_flags->alt_tapedev = stralloc(optarg) ; break;
+       case 'C':
+           rst_flags->compress = 1;
+           rst_flags->comp_type = COMPRESS_BEST_OPT;
+           break;
+       case 'p': rst_flags->pipe_to_fd = fileno(stdout); break;
+       case 's': rst_flags->fsf = 0; break;
+       case 'l': rst_flags->leave_comp = 1; break;
+       case 'i': rst_flags->inventory_log = stralloc(optarg); break;
+       case 'n': rst_flags->inline_assemble = 0; break;
+       case 'w': rst_flags->delay_assemble = 1; break;
+       case 'a': rst_flags->wait_tape_prompt = 0; break;
+       case 'h': rst_flags->headers = 1; break;
+       default:
+           usage();
+       }
+    }
+
+    /* Check some flags that affect inventorying */
+    if(rst_flags->inventory_log){
+       if(rst_flags->inline_assemble) rst_flags->delay_assemble = 1;
+       rst_flags->inline_assemble = 0;
+       rst_flags->leave_comp = 1;
+       if(rst_flags->compress){
+           error("Cannot force compression when doing inventory/search");
+       }
+       fprintf(stderr, "Doing inventory/search, dumps will not be uncompressed or assembled on-the-fly.\n");
+    }
+    else{
+       if(rst_flags->delay_assemble){
+           fprintf(stderr, "Using -w, split dumpfiles will *not* be automatically uncompressed.\n");
+       }
+    }
+
+    /* make sure our options all make sense otherwise */
+    if(check_rst_flags(rst_flags) == -1) usage();
+
+    config_name = argv[optind++];
+    config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
+    conffile = stralloc2(config_dir, CONFFILE_NAME);
+    if (read_conffile(conffile)) {
+       error("errors processing config file \"%s\"", conffile);
+    }
+    amfree(conffile);
+
+
+    if((argc - optind) < 1 && !rst_flags->inventory_log){
+       fprintf(stderr, "Not enough arguments\n\n");
+       usage();
+    }
+
+#define ARG_GET_HOST 0
+#define ARG_GET_DISK 1
+#define ARG_GET_DATE 2
+#define ARG_GET_LEVL 3
+
+    arg_state = ARG_GET_HOST;
+    while(optind < argc) {
+        switch(arg_state) {
+        case ARG_GET_HOST:
+            /*
+             * New host/disk/date/level set, so allocate a match_list.
+             */
+            me = alloc(sizeof(*me));
+            me->hostname = argv[optind++];
+            me->diskname = "";
+            me->datestamp = "";
+            me->level = "";
+            me->next = match_list;
+            match_list = me;
+            if(me->hostname[0] != '\0'
+               && (errstr=validate_regexp(me->hostname)) != NULL) {
+                fprintf(stderr, "%s: bad hostname regex \"%s\": %s\n",
+                        get_pname(), me->hostname, errstr);
+                usage();
+            }
+            arg_state = ARG_GET_DISK;
+            break;
+        case ARG_GET_DISK:
+            me->diskname = argv[optind++];
+            if(me->diskname[0] != '\0'
+               && (errstr=validate_regexp(me->diskname)) != NULL) {
+                fprintf(stderr, "%s: bad diskname regex \"%s\": %s\n",
+                        get_pname(), me->diskname, errstr);
+                usage();
+            }
+            arg_state = ARG_GET_DATE;
+            break;
+        case ARG_GET_DATE:
+            me->datestamp = argv[optind++];
+            if(me->datestamp[0] != '\0'
+               && (errstr=validate_regexp(me->datestamp)) != NULL) {
+                fprintf(stderr, "%s: bad datestamp regex \"%s\": %s\n",
+                        get_pname(), me->datestamp, errstr);
+                usage();
+            }
+            arg_state = ARG_GET_LEVL;
+            break;
+        case ARG_GET_LEVL:
+            me->level = argv[optind++];
+            if(me->level[0] != '\0'
+               && (errstr=validate_regexp(me->level)) != NULL) {
+                fprintf(stderr, "%s: bad level regex \"%s\": %s\n",
+                        get_pname(), me->level, errstr);
+                usage();
+            }
+        }
+    }
+
+    /* XXX I don't think this can happen */
+    if(match_list == NULL && !rst_flags->inventory_log) {
+        match_list = alloc(sizeof(*match_list));
+        match_list->hostname = "";
+        match_list->diskname = "";
+        match_list->datestamp = "";
+        match_list->level = "";
+        match_list->next = NULL;
+    }
+
+    /*
+     * We've been told explicitly to go and search through the tapes the hard
+     * way.
+     */
+    if(rst_flags->inventory_log){
+       fprintf(stderr, "Beginning tape-by-tape search.\n");
+       search_tapes(stderr, 1, NULL, match_list, rst_flags, NULL);
+       exit(0);
+    }
+
+
+    /* Decide what tapes we'll need */
+    needed_tapes = list_needed_tapes(match_list);
+    
+    parent_pid = getpid();
+    atexit(cleanup);
+    get_lock = lock_logfile(); /* config is loaded, should be ok here */
+    search_tapes(NULL, 1, needed_tapes, match_list, rst_flags, NULL);
+    cleanup();
+
+    free_match_list(match_list);
+
+    if(rst_flags->inline_assemble || rst_flags->delay_assemble)
+       flush_open_outputs(1, NULL);
+    else flush_open_outputs(0, NULL);
+
+    free_rst_flags(rst_flags);
+
+    return(0);
+}
+
+static void
+cleanup(void)
+{
+    if(parent_pid == getpid()) {
+       if(get_lock) unlink(rst_conf_logfile);
+    }
+}
+
index 4c672721be956aba82360b31e0a908b77c19f54b..a3a27f8057a12a1c5c3b87e64d2a58b1882cf014 100644 (file)
@@ -23,7 +23,7 @@
  * Authors: the Amanda Development Team.  Its members are listed in a
  * file named AUTHORS, in the root directory of this distribution.
  */
-/* $Id: amidxtaped.c,v 1.25.2.3.4.1.2.11.2.2 2005/10/02 13:48:42 martinea Exp $
+/* $Id: amidxtaped.c,v 1.58 2006/03/14 13:12:01 martinea Exp $
  *
  * This daemon extracts a dump image off a tape for amrecover and
  * returns it over the network. It basically, reads a number of
  */
 
 #include "amanda.h"
-#include "clock.h"
 #include "version.h"
+#include "clock.h"
+#include "restore.h"
 
 #include "changer.h"
 #include "tapeio.h"
 #include "conffile.h"
 #include "logfile.h"
+#include "amfeatures.h"
+#include "stream.h"
+
+#define TIMEOUT 30
 
 static char *pgm = "amidxtaped";       /* in case argv[0] is not set */
 
-char *conf_logdir = NULL;
-char *conf_logfile = NULL;
-int get_lock = 0;
-char *found_device = NULL;
+extern char *rst_conf_logdir;
+extern char *rst_conf_logfile;
+extern char *config_dir;
+
+static int get_lock = 0;
+
+static am_feature_t *our_features = NULL;
+static am_feature_t *their_features = NULL;
 
 static char *get_client_line P((void));
+static char *get_client_line_fd P((int));
+static void check_security_buffer P((char*));
+
+/* exit routine */
+static int parent_pid = -1;
+static void cleanup P((void));
 
 /* get a line from client - line terminated by \r\n */
 static char *
@@ -75,9 +90,6 @@ get_client_line()
            }
            amfree(line);
            amfree(part);
-           if(get_lock) {
-               unlink(conf_logfile);
-           }
            dbclose();
            exit(1);
            /* NOTREACHED */
@@ -104,119 +116,128 @@ get_client_line()
     return line;
 }
 
-int found = 0;
-char *searchlabel = NULL;
-int nslots, backwards;
-
-int scan_init(rc, ns, bk)
-int rc, ns, bk;
-{
-    if(rc) {
-       if(get_lock) {
-           unlink(conf_logfile);
-       }
-        error("could not get changer info: %s", changer_resultstr);
-    }
-    nslots = ns;
-    backwards = bk;
-
-    return 0;
-}
-
-
-int taperscan_slot(rc, slotstr, device)
-int rc;
-char *slotstr;
-char *device;
+/* get a line from client - line terminated by \r\n */
+static char *
+get_client_line_fd(fd)
+int fd;
 {
-    char *errstr;
-    char *datestamp = NULL, *label = NULL;
+    static char *line = NULL;
+    static int line_size = 0;
+    char *s = line;
+    int len = 0;
+    char c;
+    int nb;
 
-    if(rc == 2) {
-       dbprintf(("%s: fatal slot %s: %s\n", debug_prefix_time(NULL),
-                 slotstr, changer_resultstr));
-        return 1;
-    }
-    else if(rc == 1) {
-       dbprintf(("%s: slot %s: %s\n", debug_prefix_time(NULL),
-                 slotstr, changer_resultstr));
-        return 0;
+    if(line == NULL) { /* first time only, allocate initial buffer */
+       s = line = malloc(128);
+       line_size = 128;
     }
-    else {
-        if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
-           dbprintf(("%s: slot %s: %s\n", debug_prefix_time(NULL),
-                     slotstr, errstr));
-        } else {
-            /* got an amanda tape */
-           dbprintf(("%s: slot %s: date %-8s label %s",
-                     debug_prefix_time(NULL), slotstr, datestamp, label));
-            if(strcmp(label, FAKE_LABEL) == 0 ||
-               strcmp(label, searchlabel) == 0) {
-                /* it's the one we are looking for, stop here */
-               found_device = newstralloc(found_device,device);
-               dbprintf((" (exact label match)\n"));
-                found = 1;
-                return 1;
-            }
-            else {
-               dbprintf((" (no match)\n"));
-            }
-        }
+    while(1) {
+       nb = read(fd, &c, 1);
+       if (nb <= 0) {
+           /* EOF or error */
+           if ((nb <= 0) && ((errno == EINTR) || (errno == EAGAIN))) {
+               /* Keep looping if failure is temporary */
+               continue;
+           }
+           dbprintf(("%s: Control pipe read error - %s\n",
+               pgm, strerror(errno)));
+           break;
+       }
+
+       if(len >= line_size-1) { /* increase buffer size */
+           line_size *= 2;
+           line = realloc(line, line_size);
+           if (line == NULL) {
+               error("Memory reallocation failure");
+               /* NOTREACHED */
+           }
+           s = &line[len];
+       }
+       *s = c;
+       if(c == '\n') {
+           if(len > 0 && *(s-1) == '\r') { /* remove '\r' */
+               s--;
+               len--;
+           }
+           *s = '\0';
+           return line;
+       }
+       s++;
+       len++;
     }
-    return 0;
+    line[len] = '\0';
+    return line;
 }
 
 
-int lock_logfile()
+void check_security_buffer(buffer)
+     char *buffer;
 {
-    conf_logdir = getconf_str(CNF_LOGDIR);
-    if (*conf_logdir == '/') {
-        conf_logdir = stralloc(conf_logdir);
-    } else {
-        conf_logdir = stralloc2(config_dir, conf_logdir);
-    }
-    conf_logfile = vstralloc(conf_logdir, "/log", NULL);
-    if (access(conf_logfile, F_OK) == 0) {
-        error("%s exists: amdump or amflush is already running, or you must run amcleanup", conf_logfile);
-    }
-    log_add(L_INFO, "amidxtaped");
-    return 1;
+    socklen_t i;
+    struct sockaddr_in addr;
+    char *s, *fp, ch;
+    char *errstr = NULL;
+    
+     i = sizeof (addr);
+     if (getpeername(0, (struct sockaddr *)&addr, &i) == -1)
+        error("getpeername: %s", strerror(errno));
+     if (addr.sin_family != AF_INET || ntohs(addr.sin_port) == 20) {
+       error("connection rejected from %s family %d port %d",
+             inet_ntoa(addr.sin_addr), addr.sin_family, htons(addr.sin_port));
+     }
+     
+     /* do the security thing */
+     s = buffer;
+     ch = *s++;
+
+     skip_whitespace(s, ch);
+     if (ch == '\0') {
+            error("cannot parse SECURITY line");
+     }
+     fp = s-1;
+     skip_non_whitespace(s, ch);
+     s[-1] = '\0';
+     if (strcmp(fp, "SECURITY") != 0) {
+        error("cannot parse SECURITY line");
+     }
+     skip_whitespace(s, ch);
+     if (!check_security(&addr, s-1, 0, &errstr)) {
+        error("security check failed: %s", errstr);
+     }
 }
 
-
 int main(argc, argv)
 int argc;
 char **argv;
 {
-    int amrestore_nargs;
-    char **amrestore_args;
     char *buf = NULL;
-    int i;
+    int data_sock = -1, data_port = -1;
     socklen_t socklen;
-    char *amrestore_path;
-    pid_t pid;
-    int isafile;
-    struct stat stat_tape;
-    char *tapename = NULL;
-    char *s, *fp;
-    int ch;
-    char *errstr = NULL;
     struct sockaddr_in addr;
-    amwait_t status;
-
-    int re_header = 0;
+    match_list_t *match_list;
+    tapelist_t *tapes = NULL;
+    char *their_feature_string = NULL;
+    rst_flags_t *rst_flags;
+    int use_changer = 0;
+    FILE *prompt_stream = NULL;
     int re_end = 0;
-    char *re_label = NULL;
-    char *re_fsf = NULL;
-    char *re_device = NULL;
-    char *re_host = NULL;
-    char *re_disk = NULL;
-    char *re_datestamp = NULL;
     char *re_config = NULL;
+    char *conf_tapetype;
+    tapetype_t *tape;
 
     safe_fd(-1, 0);
     safe_cd();
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    rst_flags = new_rst_flags();
+    rst_flags->mask_splits = 1; /* for older clients */
+    rst_flags->amidxtaped = 1;
+    our_features = am_init_feature_set();
+    their_features = am_set_default_feature_set();
+
     /*
      * When called via inetd, it is not uncommon to forget to put the
      * argv[0] value on the config line.  On some systems (e.g. Solaris)
@@ -294,54 +315,50 @@ char **argv;
     /* do the security thing */
     amfree(buf);
     buf = stralloc(get_client_line());
-    s = buf;
-    ch = *s++;
-
-    skip_whitespace(s, ch);
-    if (ch == '\0')
-    {
-       error("cannot parse SECURITY line");
-    }
-    fp = s-1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    if (strcmp(fp, "SECURITY") != 0)
-    {
-       error("cannot parse SECURITY line");
-    }
-    skip_whitespace(s, ch);
-    if (!security_ok(&addr, s-1, 0, &errstr)) {
-       error("security check failed: %s", errstr);
-    }
+    check_security_buffer(buf);
 
     /* get the number of arguments */
-    amrestore_nargs = 0;
-    do {
+    match_list = alloc(sizeof(match_list_t));
+    match_list->next = NULL;
+    match_list->hostname = "";
+    match_list->datestamp = "";
+    match_list->level = "";
+    match_list->diskname = "";
+
+   do {
        amfree(buf);
        buf = stralloc(get_client_line());
        if(strncmp(buf, "LABEL=", 6) == 0) {
-           re_label = stralloc(buf+6);
+           tapes = unmarshal_tapelist_str(buf+6);
        }
        else if(strncmp(buf, "FSF=", 4) == 0) {
-           int fsf = atoi(buf+4);
-           if(fsf > 0) {
-               re_fsf = stralloc(buf+4);
-           }
+           rst_flags->fsf = atoi(buf + 4);
        }
        else if(strncmp(buf, "HEADER", 6) == 0) {
-           re_header = 1;
+           rst_flags->headers = 1;
+       }
+       else if(strncmp(buf, "FEATURES=", 9) == 0) {
+           char *our_feature_string = NULL;
+           their_feature_string = stralloc(buf+9);
+           am_release_feature_set(their_features);
+           their_features = am_string_to_feature(their_feature_string);
+           amfree(their_feature_string);
+           our_feature_string = am_feature_to_string(our_features);
+           printf("%s", our_feature_string);
+           fflush(stdout);
+           amfree(our_feature_string);
        }
        else if(strncmp(buf, "DEVICE=", 7) == 0) {
-           re_device = stralloc(buf+7);
+           rst_flags->alt_tapedev= stralloc(buf+7);
        }
        else if(strncmp(buf, "HOST=", 5) == 0) {
-           re_host = stralloc(buf+5);
+           match_list->hostname = stralloc(buf+5);
        }
        else if(strncmp(buf, "DISK=", 5) == 0) {
-           re_disk = stralloc(buf+5);
+           match_list->diskname = stralloc(buf+5);
        }
        else if(strncmp(buf, "DATESTAMP=", 10) == 0) {
-           re_datestamp = stralloc(buf+10);
+           match_list->datestamp = stralloc(buf+10);
        }
        else if(strncmp(buf, "END", 3) == 0) {
            re_end = 1;
@@ -350,12 +367,21 @@ char **argv;
            re_config = stralloc(buf+7);
        }
        else if(buf[0] != '\0' && buf[0] >= '0' && buf[0] <= '9') {
-           amrestore_nargs = atoi(buf);
+/* XXX does nothing?     amrestore_nargs = atoi(buf); */
            re_end = 1;
        }
        else {
        }
     } while (re_end == 0);
+    amfree(buf);
+
+    if(!tapes && rst_flags->alt_tapedev){
+       dbprintf(("%s: Looks like we're restoring from a holding file...\n", debug_prefix_time(NULL)));
+        tapes = unmarshal_tapelist_str(rst_flags->alt_tapedev);
+       tapes->isafile = 1;
+       amfree(rst_flags->alt_tapedev);
+       rst_flags->alt_tapedev = NULL;
+    }
 
     if(re_config) {
        char *conffile;
@@ -364,196 +390,129 @@ char **argv;
        if (read_conffile(conffile)) {
            dbprintf(("%s: config '%s' not found\n",
                      debug_prefix_time(NULL), re_config));
-           amfree(re_fsf);
-           amfree(re_label);
            amfree(re_config);
+           re_config = NULL;
        }
-    }
-    else {
-       amfree(re_fsf);
-       amfree(re_label);
-    }
-
-    if(re_device && re_config &&
-       strcmp(re_device, getconf_str(CNF_TAPEDEV)) == 0) {
+       amfree(conffile);
+    }
+
+    if(tapes && 
+       (!rst_flags->alt_tapedev  ||
+        (re_config && ( strcmp(rst_flags->alt_tapedev,
+                               getconf_str(CNF_AMRECOVER_CHANGER)) == 0 ||
+                        strcmp(rst_flags->alt_tapedev,
+                               getconf_str(CNF_TPCHANGER)) == 0 ) ) ) ) {
+       /* We need certain options, if restoring from more than one tape */
+        if(tapes->next && !am_has_feature(their_features, fe_recover_splits)) {
+            error("%s: Client must support split dumps to restore requested data.",  get_pname());
+            /* NOTREACHED */
+        }
+       dbprintf(("%s: Restoring from changer, checking labels\n", get_pname()));
+       rst_flags->check_labels = 1;
+       use_changer = 1;
+    }
+
+    /* If we'll be stepping on the tape server's devices, lock them. */
+    if(re_config  &&
+       (use_changer || (rst_flags->alt_tapedev &&
+                        strcmp(rst_flags->alt_tapedev,
+                               getconf_str(CNF_TAPEDEV)) == 0) ) ) {
+       dbprintf(("%s: Locking devices\n", get_pname()));
+       parent_pid = getpid();
+       atexit(cleanup);
        get_lock = lock_logfile();
     }
 
-    if(re_label && re_config &&
-       strcmp(re_device, getconf_str(CNF_AMRECOVER_CHANGER)) == 0) {
-
-       if(changer_init() == 0) {
-           dbprintf(("%s: No changer available\n",
-                      debug_prefix_time(NULL)));
-       }
-       else {
-           searchlabel = stralloc(re_label);
-           changer_find(scan_init, taperscan_slot, searchlabel);
-           if(found == 0) {
-               dbprintf(("%s: Can't find label \"%s\"\n",
-                         debug_prefix_time(NULL), searchlabel));
-               if(get_lock) {
-                   unlink(conf_logfile);
-               }
-               dbclose();
-               exit(1);
-           }
-           else {
-                    re_device=stralloc(found_device);
-               dbprintf(("%s: label \"%s\" found\n",
-                         debug_prefix_time(NULL), searchlabel));
-           }
-       }
+    /* Init the tape changer */
+    if(tapes && use_changer && changer_init() == 0) {
+       dbprintf(("%s: No changer available\n", debug_prefix_time(NULL)));
     }
 
-    if(re_fsf && re_config && getconf_int(CNF_AMRECOVER_DO_FSF) == 0) {
-       amfree(re_fsf);
-    }
-    if(re_label && re_config && getconf_int(CNF_AMRECOVER_CHECK_LABEL) == 0) {
-       amfree(re_label);
+    /* Read the default block size from the tape type */
+    if(re_config && (conf_tapetype = getconf_str(CNF_TAPETYPE)) != NULL) {
+       tape = lookup_tapetype(conf_tapetype);
+       rst_flags->blocksize = tape->blocksize * 1024;
     }
 
-    dbprintf(("%s: amrestore_nargs=%d\n",
-             debug_prefix_time(NULL),
-             amrestore_nargs));
-
-    amrestore_args = (char **)alloc((amrestore_nargs+12)*sizeof(char *));
-    i = 0;
-    amrestore_args[i++] = "amrestore";
-    if(re_header || re_device || re_host || re_disk || re_datestamp ||
-       re_label || re_fsf) {
-
-       amrestore_args[i++] = "-p";
-       if(re_header) amrestore_args[i++] = "-h";
-       if(re_label) {
-           amrestore_args[i++] = "-l";
-           amrestore_args[i++] = re_label;
-       }
-       if(re_fsf) {
-           amrestore_args[i++] = "-f";
-           amrestore_args[i++] = re_fsf;
-       }
-       if(re_device) amrestore_args[i++] = re_device;
-       if(re_host) amrestore_args[i++] = re_host;
-       if(re_disk) amrestore_args[i++] = re_disk;
-       if(re_datestamp) amrestore_args[i++] = re_datestamp;
+    if(rst_flags->fsf && re_config && 
+       getconf_int(CNF_AMRECOVER_DO_FSF) == 0) {
+       rst_flags->fsf = 0;
     }
-    else { /* fe_amidxtaped_nargs */
-       while (i <= amrestore_nargs) {
-           amrestore_args[i++] = stralloc(get_client_line());
-       }
-    }
-    amrestore_args[i] = NULL;
-
-    amrestore_path = vstralloc(sbindir, "/", "amrestore", NULL);
 
-    /* so got all the arguments, now ready to execv */
-    dbprintf(("%s: Ready to execv amrestore with:\n", debug_prefix_time(NULL)));
-    dbprintf(("path = %s\n", amrestore_path));
-    for (i = 0; amrestore_args[i] != NULL; i++)
-    {
-       dbprintf(("argv[%d] = \"%s\"\n", i, amrestore_args[i]));
-    }
-
-    if ((pid = fork()) == 0)
-    {
-       /* child */
-       (void)execv(amrestore_path, amrestore_args);
-
-       /* only get here if exec failed */
-       dbprintf(("%s: child could not exec %s: %s\n",
-                 debug_prefix_time(NULL),
-                 amrestore_path,
-                 strerror(errno)));
-       return 1;
-       /*NOT REACHED*/
+    if(re_config && getconf_int(CNF_AMRECOVER_CHECK_LABEL) == 0) {
+       rst_flags->check_labels = 0;
     }
 
-    /* this is the parent */
-    if (pid == -1)
-    {
-       dbprintf(("%s: error forking amrestore child: %s\n",
-                 debug_prefix_time(NULL), strerror(errno)));
-       if(get_lock) {
-           unlink(conf_logfile);
+    /* establish a distinct data connection for dumpfile data */
+    if(am_has_feature(their_features, fe_recover_splits)){
+       int data_fd;
+       char *buf;
+       
+       dbprintf(("%s: Client understands split dumpfiles\n", get_pname()));
+       
+       if((data_sock = stream_server(&data_port, STREAM_BUFSIZE, -1)) < 0){
+           error("%s: could not create data socket: %s", get_pname(),
+                 strerror(errno));
        }
-       dbclose();
-       return 1;
-    }
-
-    /* wait for the child to do the restore */
-    if (waitpid(pid, &status, 0) == -1)
-    {
-       dbprintf(("%s: error waiting for amrestore child: %s\n",
-                 debug_prefix_time(NULL), strerror(errno)));
-       if(get_lock) {
-           unlink(conf_logfile);
+       dbprintf(("%s: Local port %d set aside for data\n", get_pname(),
+                 data_port));
+       
+       printf("CONNECT %d\n", data_port); /* tell client where to connect */
+       fflush(stdout);
+       
+       if((data_fd = stream_accept(data_sock, TIMEOUT, -1, -1)) < 0){
+           error("stream_accept failed for client data connection: %s\n",
+                 strerror(errno));
        }
-       dbclose();
-       return 1;
-    }
-    /* amrestore often sees the pipe reader (ie restore) quit in the middle
-       of the file because it has extracted all of the files needed. This
-       results in an exit status of 2. This unfortunately is the exit
-       status returned by many errors. Only when the exit status is 1 is it
-       guaranteed that an error existed. In all cases we should rewind the
-       tape if we can so that a retry starts from the correct place */
-    if (WIFEXITED(status) != 0)
-    {
 
-       dbprintf(("%s: amrestore terminated normally with status: %d\n",
-                 debug_prefix_time(NULL), WEXITSTATUS(status)));
-    }
-    else
-    {
-       dbprintf(("%s: amrestore terminated abnormally.\n",
-                 debug_prefix_time(NULL)));
-    }
+       buf = get_client_line_fd(data_fd);
 
-    /* rewind tape */
-    if(re_device) {
-       tapename = re_device;
+       check_security_buffer(buf);
+       rst_flags->pipe_to_fd = data_fd;
+        prompt_stream = stdout;
     }
     else {
-       /* the first non-option argument is the tape device */
-       for (i = 1; i <= amrestore_nargs; i++)
-           if (amrestore_args[i][0] != '-')
-               break;
-       if (i > amrestore_nargs) {
-           dbprintf(("%s: Couldn't find tape in arguments\n",
-                     debug_prefix_time(NULL)));
-           if(get_lock) {
-               unlink(conf_logfile);
-           }
-           dbclose();
-           return 1;
-       }
-
-       tapename = stralloc(amrestore_args[i]);
-    }
-    if (tape_stat(tapename, &stat_tape) != 0) {
-        error("could not stat %s: %s", tapename, strerror(errno));
-    }
-    isafile = S_ISREG((stat_tape.st_mode));
-    if (!isafile) {
-       char *errstr = NULL;
-
-       dbprintf(("%s: rewinding tape ...\n", debug_prefix_time(NULL)));
-       errstr = tape_rewind(tapename);
-
-       if (errstr != NULL) {
-           dbprintf(("%s: %s\n", debug_prefix_time(NULL), errstr));
-           amfree(errstr);
-       } else {
-           dbprintf(("%s: done\n", debug_prefix_time(NULL)));
-       }
-    }
-
-    if(get_lock) {
-       unlink(conf_logfile);
-    }
-
-    amfree(tapename);
+       rst_flags->pipe_to_fd = fileno(stdout);
+        prompt_stream = stderr;
+    }
+    dbprintf(("%s: Sending output to file descriptor %d\n",
+             get_pname(), rst_flags->pipe_to_fd));
+    
+    
+    /* make sure our restore flags aren't crazy */
+    if(check_rst_flags(rst_flags) == -1){
+       if(rst_flags->pipe_to_fd != -1) aclose(rst_flags->pipe_to_fd);
+       exit(1);
+    }
+    
+    /* actual restoration */
+    search_tapes(prompt_stream, use_changer, tapes, match_list, rst_flags,
+                their_features);
+    dbprintf(("%s: Restoration finished\n", debug_prefix_time(NULL)));
+    
+    /* cleanup */
+    if(rst_flags->pipe_to_fd != -1) aclose(rst_flags->pipe_to_fd);
+    free_tapelist(tapes);
+    
+    am_release_feature_set(their_features);
+
+    amfree(rst_flags->alt_tapedev);
+    amfree(rst_flags);
+    amfree(match_list->hostname);
+    amfree(match_list->diskname);
+    amfree(match_list->datestamp);
+    amfree(match_list);
+    amfree(config_dir);
+    amfree(re_config);
     dbclose();
     return 0;
 }
+
+static void
+cleanup(void)
+{
+    if(parent_pid == getpid()) {
+       if(get_lock) unlink(rst_conf_logfile);
+    }
+}
+
index aef9ba429d57cd8e417ffd09855993c1024e6069..1825cf219e62899e7f6ff04f7bc1772be4f3629d 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amrestore.c,v 1.28.2.4.4.3.2.8.2.4 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amrestore.c,v 1.56 2006/01/14 04:37:19 paddy_s Exp $
  *
  * retrieves files from an amanda tape
  */
  */
 
 #include "amanda.h"
+#include "util.h"
 #include "tapeio.h"
 #include "fileheader.h"
-#include "util.h"
+#include "restore.h"
 
 #define CREAT_MODE     0640
 
-char *buffer = NULL;
-
-int compflag, rawflag, pipeflag, headerflag;
-int got_sigpipe, file_number;
-pid_t compress_pid = -1;
-char *compress_type = COMPRESS_FAST_OPT;
-int tapedev;
-int bytes_read;
-long blocksize = -1;
-long filefsf = -1;
+static int file_number;
+static pid_t comp_enc_pid = -1;
+static int tapedev;
+static long filefsf = -1;
 
 /* local functions */
 
-void errexit P((void));
-void handle_sigpipe P((int sig));
-int disk_match P((dumpfile_t *file, char *datestamp, 
-                 char *hostname, char *diskname));
-char *make_filename P((dumpfile_t *file));
-void read_file_header P((dumpfile_t *file, int isafile));
-static int get_block P((int isafile));
-void restore P((dumpfile_t *file, char *filename, int isafile));
-void usage P((void));
+static void errexit P((void));
+static void usage P((void));
 int main P((int argc, char **argv));
 
-void errexit()
+static void errexit()
 /*
  * Do exit(2) after an error, rather than exit(1).
  */
@@ -78,372 +66,7 @@ void errexit()
 }
 
 
-void handle_sigpipe(sig)
-int sig;
-/*
- * Signal handler for the SIGPIPE signal.  Just sets a flag and returns.
- * The act of catching the signal causes the pipe write() to fail with
- * EINTR.
- */
-{
-    got_sigpipe++;
-}
-
-int disk_match(file, datestamp, hostname, diskname)
-dumpfile_t *file;
-char *datestamp, *hostname, *diskname;
-
-/*
- * Returns 1 if the current dump file matches the hostname and diskname
- * regular expressions given on the command line, 0 otherwise.  As a 
- * special case, empty regexs are considered equivalent to ".*": they 
- * match everything.
- */
-{
-    if(file->type != F_DUMPFILE) return 0;
-
-    if((*hostname == '\0' || match_host(hostname, file->name)) &&
-       (*diskname == '\0' || match_disk(diskname, file->disk)) &&
-       (*datestamp== '\0' || match_datestamp(datestamp, file->datestamp)))
-       return 1;
-    else
-       return 0;
-}
-
-
-char *make_filename(file)
-dumpfile_t *file;
-{
-    char number[NUM_STR_SIZE];
-    char *sfn;
-    char *fn;
-
-    ap_snprintf(number, sizeof(number), "%d", file->dumplevel);
-    sfn = sanitise_filename(file->disk);
-    fn = vstralloc(file->name,
-                  ".",
-                  sfn, 
-                  ".",
-                  file->datestamp,
-                  ".",
-                  number,
-                  NULL);
-    amfree(sfn);
-    return fn;
-}
-
-
-static int get_block(isafile)
-int isafile;
-{
-    static int test_blocksize = 1;
-    int buflen;
-
-    /*
-     * If this is the first call, set the blocksize if it was not on
-     * the command line.  Allocate the I/O buffer in any case.
-     *
-     * For files, the blocksize is always DISK_BLOCK_BYTES.  For tapes,
-     * we allocate a large buffer and set the size to the length of the
-     * first (successful) record.
-     */
-    buflen = blocksize;
-    if(test_blocksize) {
-       if(blocksize < 0) {
-           if(isafile) {
-               blocksize = buflen = DISK_BLOCK_BYTES;
-           } else {
-               buflen = MAX_TAPE_BLOCK_BYTES;
-           }
-       }
-       buffer = newalloc(buffer, buflen);
-    }
-    if(isafile) {
-       bytes_read = fullread(tapedev, buffer, buflen);
-    } else {
-       bytes_read = tapefd_read(tapedev, buffer, buflen);
-       if(blocksize < 0 && bytes_read > 0 && bytes_read < buflen) {
-           char *new_buffer;
-
-           blocksize = bytes_read;
-           new_buffer = alloc(blocksize);
-           memcpy(new_buffer, buffer, bytes_read);
-           amfree(buffer);
-           buffer = new_buffer;
-       }
-    }
-    if(blocksize > 0) {
-       test_blocksize = 0;
-    }
-    return bytes_read;
-}
-
-
-void read_file_header(file, isafile)
-dumpfile_t *file;
-int isafile;
-/*
- * Reads the first block of a tape file.
- */
-{
-    bytes_read = get_block(isafile);
-    if(bytes_read < 0) {
-       error("error reading file header: %s", strerror(errno));
-    } else if(bytes_read < blocksize) {
-       if(bytes_read == 0) {
-           fprintf(stderr, "%s: missing file header block\n", get_pname());
-       } else {
-           fprintf(stderr, "%s: short file header block: %d byte%s\n",
-                   get_pname(), bytes_read, (bytes_read == 1) ? "" : "s");
-       }
-       file->type = F_UNKNOWN;
-    } else {
-       parse_file_header(buffer, file, bytes_read);
-    }
-    return;
-}
-
-
-void restore(file, filename, isafile)
-dumpfile_t *file;
-char *filename;
-int isafile;
-/*
- * Restore the current file from tape.  Depending on the settings of
- * the command line flags, the file might need to be compressed or
- * uncompressed.  If so, a pipe through compress or uncompress is set
- * up.  The final output usually goes to a file named host.disk.date.lev,
- * but with the -p flag the output goes to stdout (and presumably is
- * piped to restore).
- */
-{
-    int rc = 0, dest, out, outpipe[2];
-    int wc;
-    int l, s;
-    int file_is_compressed;
-
-    /* adjust compression flag */
-
-    file_is_compressed = file->compressed;
-    if(!compflag && file_is_compressed && !known_compress_type(file)) {
-       fprintf(stderr, 
-               "%s: unknown compression suffix %s, can't uncompress\n",
-               get_pname(), file->comp_suffix);
-       compflag = 1;
-    }
-
-    /* set up final destination file */
-
-    if(pipeflag)
-       dest = 1;               /* standard output */
-    else {
-       char *filename_ext = NULL;
-
-       if(compflag) {
-           filename_ext = file_is_compressed ? file->comp_suffix
-                                             : COMPRESS_SUFFIX;
-       } else if(rawflag) {
-           filename_ext = ".RAW";
-       } else {
-           filename_ext = "";
-       }
-       filename_ext = stralloc2(filename, filename_ext);
-
-       if((dest = creat(filename, CREAT_MODE)) < 0)
-           error("could not create output file: %s", strerror(errno));
-       amfree(filename_ext);
-    }
-
-    out = dest;
-
-    /*
-     * If -r or -h, write the header before compress or uncompress pipe.
-     * Only write DISK_BLOCK_BYTES, regardless of how much was read.
-     * This makes the output look like a holding disk image, and also
-     * makes it easier to remove the header (e.g. in amrecover) since
-     * it has a fixed size.
-     */
-    if(rawflag || headerflag) {
-       int w;
-       char *cont_filename;
-
-       if(compflag && !file_is_compressed) {
-           file->compressed = 1;
-           ap_snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
-                       " %s %s |", UNCOMPRESS_PATH,
-#ifdef UNCOMPRESS_OPT
-                       UNCOMPRESS_OPT
-#else
-                       ""
-#endif
-                       );
-           strncpy(file->comp_suffix,
-                   COMPRESS_SUFFIX,
-                   sizeof(file->comp_suffix)-1);
-           file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
-       }
-
-       /* remove CONT_FILENAME from header */
-       cont_filename = stralloc(file->cont_filename);
-       memset(file->cont_filename,'\0',sizeof(file->cont_filename));
-       file->blocksize = DISK_BLOCK_BYTES;
-       build_header(buffer, file, bytes_read);
-
-       if((w = fullwrite(out, buffer, DISK_BLOCK_BYTES)) != DISK_BLOCK_BYTES) {
-           if(w < 0) {
-               error("write error: %s", strerror(errno));
-           } else {
-               error("write error: %d instead of %d", w, DISK_BLOCK_BYTES);
-           }
-       }
-       /* add CONT_FILENAME to header */
-       strncpy(file->cont_filename, cont_filename, sizeof(file->cont_filename));
-    }
-
-    /* if -c and file not compressed, insert compress pipe */
-
-    if(compflag && !file_is_compressed) {
-       if(pipe(outpipe) < 0) error("error [pipe: %s]", strerror(errno));
-       out = outpipe[1];
-       switch(compress_pid = fork()) {
-       case -1: error("could not fork for %s: %s",
-                      COMPRESS_PATH, strerror(errno));
-       default:
-           aclose(outpipe[0]);
-           aclose(dest);
-           break;
-       case 0:
-           aclose(outpipe[1]);
-           if(outpipe[0] != 0) {
-               if(dup2(outpipe[0], 0) == -1)
-                   error("error [dup2 pipe: %s]", strerror(errno));
-               aclose(outpipe[0]);
-           }
-           if(dest != 1) {
-               if(dup2(dest, 1) == -1)
-                   error("error [dup2 dest: %s]", strerror(errno));
-               aclose(dest);
-           }
-           if (*compress_type == '\0') {
-               compress_type = NULL;
-           }
-           execlp(COMPRESS_PATH, COMPRESS_PATH, compress_type, (char *)0);
-           error("could not exec %s: %s", COMPRESS_PATH, strerror(errno));
-       }
-    }
-
-    /* if not -r or -c, and file is compressed, insert uncompress pipe */
-
-    else if(!rawflag && !compflag && file_is_compressed) {
-       /* 
-        * XXX for now we know that for the two compression types we
-        * understand, .Z and optionally .gz, UNCOMPRESS_PATH will take
-        * care of both.  Later, we may need to reference a table of
-        * possible uncompress programs.
-        */
-       if(pipe(outpipe) < 0) error("error [pipe: %s]", strerror(errno));
-       out = outpipe[1];
-       switch(compress_pid = fork()) {
-       case -1: 
-           error("could not fork for %s: %s",
-                 UNCOMPRESS_PATH, strerror(errno));
-       default:
-           aclose(outpipe[0]);
-           aclose(dest);
-           break;
-       case 0:
-           aclose(outpipe[1]);
-           if(outpipe[0] != 0) {
-               if(dup2(outpipe[0], 0) < 0)
-                   error("dup2 pipe: %s", strerror(errno));
-               aclose(outpipe[0]);
-           }
-           if(dest != 1) {
-               if(dup2(dest, 1) < 0)
-                   error("dup2 dest: %s", strerror(errno));
-               aclose(dest);
-           }
-           (void) execlp(UNCOMPRESS_PATH, UNCOMPRESS_PATH,
-#ifdef UNCOMPRESS_OPT
-                         UNCOMPRESS_OPT,
-#endif
-                         (char *)0);
-           error("could not exec %s: %s", UNCOMPRESS_PATH, strerror(errno));
-       }
-    }
-
-
-    /* copy the rest of the file from tape to the output */
-    got_sigpipe = 0;
-    wc = 0;
-    do {
-       bytes_read = get_block(isafile);
-       if(bytes_read < 0) {
-           error("read error: %s", strerror(errno));
-       }
-       if(bytes_read == 0 && isafile) {
-           /*
-            * See if we need to switch to the next file.
-            */
-           if(file->cont_filename[0] == '\0') {
-               break;                          /* no more files */
-           }
-           close(tapedev);
-           if((tapedev = open(file->cont_filename, O_RDONLY)) == -1) {
-               char *cont_filename = strrchr(file->cont_filename,'/');
-               if(cont_filename) {
-                   cont_filename++;
-                   if((tapedev = open(cont_filename,O_RDONLY)) == -1) {
-                       error("can't open %s: %s", file->cont_filename,
-                             strerror(errno));
-                   }
-                   else {
-                       fprintf(stderr, "cannot open %s: %s\n",
-                               file->cont_filename, strerror(errno));
-                       fprintf(stderr, "using %s\n",
-                               cont_filename);
-                   }
-               }
-               else {
-                   error("can't open %s: %s", file->cont_filename,
-                         strerror(errno));
-               }
-           }
-           read_file_header(file, isafile);
-           if(file->type != F_DUMPFILE && file->type != F_CONT_DUMPFILE) {
-               fprintf(stderr, "unexpected header type: ");
-               print_header(stderr, file);
-               exit(2);
-           }
-           continue;
-       }
-       for(l = 0; l < bytes_read; l += s) {
-           if((s = write(out, buffer + l, bytes_read - l)) < 0) {
-               if(got_sigpipe) {
-                   fprintf(stderr,"Error %d (%s) offset %d+%d, wrote %d\n",
-                                  errno, strerror(errno), wc, bytes_read, rc);
-                   fprintf(stderr,  
-                           "%s: pipe reader has quit in middle of file.\n",
-                           get_pname());
-               } else {
-                   perror("amrestore: write error");
-               }
-               exit(2);
-           }
-       }
-       wc += bytes_read;
-    } while (bytes_read > 0);
-    if(pipeflag) {
-       if(out != dest) {
-           aclose(out);
-       }
-    } else {
-       aclose(out);
-    }
-}
-
-
-void usage()
+static void usage()
 /*
  * Print usage message and terminate.
  */
@@ -451,7 +74,6 @@ void usage()
     error("Usage: amrestore [-b blocksize] [-r|-c] [-p] [-h] [-f fileno] [-l label] tape-device|holdingfile [hostname [diskname [datestamp [hostname [diskname [datestamp ... ]]]]]]");
 }
 
-
 int main(argc, argv)
 int argc;
 char **argv;
@@ -481,38 +103,48 @@ char **argv;
     char *e;
     char *err;
     char *label = NULL;
+    rst_flags_t *rst_flags;
     int count_error;
+    size_t read_result;
 
     safe_fd(-1, 0);
 
     set_pname("amrestore");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     erroutput_type = ERR_INTERACTIVE;
 
     onerror(errexit);
-    signal(SIGPIPE, handle_sigpipe);
+
+    rst_flags = new_rst_flags();
+    rst_flags->inline_assemble = 0;
 
     /* handle options */
-    while( (opt = getopt(argc, argv, "b:cCd:rpkhf:l:")) != -1) {
+    while( (opt = getopt(argc, argv, "b:cCd:rphf:l:")) != -1) {
        switch(opt) {
        case 'b':
-           blocksize = strtol(optarg, &e, 10);
+           rst_flags->blocksize = strtol(optarg, &e, 10);
            if(*e == 'k' || *e == 'K') {
-               blocksize *= 1024;
+               rst_flags->blocksize *= 1024;
            } else if(*e == 'm' || *e == 'M') {
-               blocksize *= 1024 * 1024;
+               rst_flags->blocksize *= 1024 * 1024;
            } else if(*e != '\0') {
-               error("invalid blocksize value \"%s\"", optarg);
+               error("invalid rst_flags->blocksize value \"%s\"", optarg);
            }
-           if(blocksize < DISK_BLOCK_BYTES) {
+           if(rst_flags->blocksize < DISK_BLOCK_BYTES) {
                error("minimum block size is %dk", DISK_BLOCK_BYTES / 1024);
            }
            break;
-       case 'c': compflag = 1; break;
-       case 'C': compflag = 1; compress_type = COMPRESS_BEST_OPT; break;
-       case 'r': rawflag = 1; break;
-       case 'p': pipeflag = 1; break;
-       case 'h': headerflag = 1; break;
+       case 'c': rst_flags->compress = 1; break;
+       case 'C':
+           rst_flags->compress = 1;
+           rst_flags->comp_type = COMPRESS_BEST_OPT;
+           break;
+       case 'r': rst_flags->raw = 1; break;
+       case 'p': rst_flags->pipe_to_fd = fileno(stdout); break;
+       case 'h': rst_flags->headers = 1; break;
        case 'f':
            filefsf = strtol(optarg, &e, 10);
            if(*e != '\0') {
@@ -527,7 +159,7 @@ char **argv;
        }
     }
 
-    if(compflag && rawflag) {
+    if(rst_flags->compress && rst_flags->raw) {
        fprintf(stderr, 
                "Cannot specify both -r (raw) and -c (compressed) output.\n");
        usage();
@@ -610,8 +242,10 @@ char **argv;
            if((err = tape_rewind(tapename)) != NULL) {
                error("Could not rewind device '%s': %s", tapename, err);
            }
-           tapedev = tape_open(tapename, 0);
-           read_file_header(&file, isafile);
+           if ((tapedev = tape_open(tapename, 0)) == -1) {;
+               error("Could not open device '%s': %s", tapename, err);
+           }
+           read_file_header(&file, tapedev, isafile, rst_flags);
            if(file.type != F_TAPESTART) {
                fprintf(stderr,"Not an amanda tape\n");
                exit (1);
@@ -644,7 +278,7 @@ char **argv;
     }
 
     if(isafile) {
-       tapedev = open(tapename, 0);
+       tapedev = open(tapename, O_RDWR);
     } else {
        tapedev = tape_open(tapename, 0);
     }
@@ -652,7 +286,7 @@ char **argv;
        error("could not open %s: %s", tapename, strerror(errno));
     }
 
-    read_file_header(&file, isafile);
+    read_file_header(&file, tapedev, isafile, rst_flags);
 
     if(file.type != F_TAPESTART && !isafile && filefsf == -1) {
        fprintf(stderr, "%s: WARNING: not at start of tape, file numbers will be offset\n",
@@ -660,14 +294,15 @@ char **argv;
     }
 
     count_error=0;
+    read_result = 0;
     while(count_error < 10) {
        if(file.type == F_TAPEEND) break;
        found_match = 0;
-       if(file.type == F_DUMPFILE) {
+       if(file.type == F_DUMPFILE || file.type == F_SPLIT_DUMPFILE) {
            amfree(filename);
            filename = make_filename(&file);
            for(me = match_list; me; me = me->next) {
-               if(disk_match(&file,me->datestamp,me->hostname,me->diskname) != 0) {
+               if(disk_match(&file,me->datestamp,me->hostname,me->diskname,"") != 0) {
                    found_match = 1;
                    break;
                }
@@ -676,19 +311,20 @@ char **argv;
                            get_pname(),
                            file_number,
                            found_match ? "restoring" : "skipping");
-           if(file.type != F_DUMPFILE) {
+           if(file.type != F_DUMPFILE  && file.type != F_SPLIT_DUMPFILE) {
                print_header(stderr, &file);
            } else {
                fprintf(stderr, "%s\n", filename);
            }
        }
        if(found_match) {
-           restore(&file, filename, isafile);
-           if(compress_pid > 0) {
-               waitpid(compress_pid, &compress_status, 0);
-               compress_pid = -1;
+           read_result = restore(&file, filename,
+               tapedev, isafile, rst_flags);
+           if(comp_enc_pid > 0) {
+               waitpid(comp_enc_pid, &compress_status, 0);
+               comp_enc_pid = -1;
            }
-           if(pipeflag) {
+           if(rst_flags->pipe_to_fd != -1) {
                file_number++;                  /* for the last message */
                break;
            }
@@ -701,7 +337,7 @@ char **argv;
         * not a holding disk file, so we can call the tape functions
         * without checking.
         */
-       if(bytes_read == 0) {
+       if(read_result == 0) {
            /*
             * If the last read got EOF, how to get to the next
             * file depends on how the tape device driver is acting.
@@ -726,7 +362,7 @@ char **argv;
            count_error=0;
        }
        file_number++;
-       read_file_header(&file, isafile);
+       read_file_header(&file, tapedev, isafile, rst_flags);
     }
     if(isafile) {
        close(tapedev);
@@ -734,7 +370,7 @@ char **argv;
        /*
         * See the notes above about advancing to the next file.
         */
-       if(bytes_read == 0) {
+       if(read_result == 0) {
            tapefd_close(tapedev);
            if((tapedev = tape_open(tapename, 0)) < 0) {
                error("could not open %s: %s", tapename, strerror(errno));
@@ -747,9 +383,9 @@ char **argv;
        tapefd_close(tapedev);
     }
 
-    if((bytes_read <= 0 || file.type == F_TAPEEND) && !isafile) {
+    if((read_result <= 0 || file.type == F_TAPEEND) && !isafile) {
        fprintf(stderr, "%s: %3d: reached ", get_pname(), file_number);
-       if(bytes_read <= 0) {
+       if(read_result <= 0) {
            fprintf(stderr, "end of information\n");
        } else {
            print_header(stderr,&file);
diff --git a/restore-src/restore.c b/restore-src/restore.c
new file mode 100644 (file)
index 0000000..35818ef
--- /dev/null
@@ -0,0 +1,1733 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1998 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: restore.c,v 1.28 2006/03/14 13:12:01 martinea Exp $
+ *
+ * retrieves files from an amanda tape
+ */
+
+#include "amanda.h"
+#include "tapeio.h"
+#include "util.h"
+#include "restore.h"
+#include "find.h"
+#include "changer.h"
+#include "logfile.h"
+#include "fileheader.h"
+#include <signal.h>
+
+int file_number;
+
+/* stuff we're stuck having global */
+static long blocksize = -1;
+static char *cur_tapedev = NULL;
+static char *searchlabel = NULL;
+static int backwards;
+static int exitassemble = 0;
+static int tapefd, nslots;
+
+char *rst_conf_logdir = NULL;
+char *rst_conf_logfile = NULL;
+char *curslot = NULL;
+
+typedef struct open_output_s {
+    struct open_output_s *next;
+    dumpfile_t *file;
+    int lastpartnum;
+    pid_t comp_enc_pid;
+    int outfd;
+} open_output_t;
+
+
+typedef struct dumplist_s {
+    struct dumplist_s *next;
+    dumpfile_t *file;
+} dumplist_t;
+
+static open_output_t *open_outputs = NULL;
+static dumplist_t *alldumps_list = NULL;
+
+static ssize_t get_block P((int tapefd, char *buffer, int isafile));
+static void append_file_to_fd P((char *filename, int fd));
+static int headers_equal P((dumpfile_t *file1, dumpfile_t *file2, int ignore_partnums));
+static int already_have_dump P((dumpfile_t *file));
+
+/* local functions */
+
+static void handle_sigint(sig)
+int sig;
+/*
+ * We might want to flush any open dumps and unmerged splits before exiting
+ * on SIGINT, so do so.
+ */
+{
+    flush_open_outputs(exitassemble, NULL);
+    if(rst_conf_logfile) unlink(rst_conf_logfile);
+    exit(0);
+}
+
+int lock_logfile()
+{
+    rst_conf_logdir = getconf_str(CNF_LOGDIR);
+    if (*rst_conf_logdir == '/') {
+       rst_conf_logdir = stralloc(rst_conf_logdir);
+    } else {
+       rst_conf_logdir = stralloc2(config_dir, rst_conf_logdir);
+    }
+    rst_conf_logfile = vstralloc(rst_conf_logdir, "/log", NULL);
+    if (access(rst_conf_logfile, F_OK) == 0) {
+       error("%s exists: amdump or amflush is already running, or you must run amcleanup", rst_conf_logfile);
+    }
+    log_add(L_INFO, get_pname());
+    return 1;
+}
+
+/*
+ * Return 1 if the two fileheaders match in name, disk, type, split chunk part
+ * number, and datestamp, and 0 if not.  The part number can be optionally
+ * ignored.
+ */
+int headers_equal (file1, file2, ignore_partnums)
+dumpfile_t *file1, *file2;
+int ignore_partnums;
+{
+    if(!file1 || !file2) return(0);
+    
+    if(file1->dumplevel == file2->dumplevel &&
+          file1->type == file2->type &&
+          !strcmp(file1->datestamp, file2->datestamp) &&
+          !strcmp(file1->name, file2->name) &&
+          !strcmp(file1->disk, file2->disk) &&
+          (ignore_partnums || file1->partnum == file2->partnum)){
+       return(1);
+    }
+    return(0);
+}
+
+
+/*
+ * See whether we're already pulled an exact copy of the given file (chunk
+ * number and all).  Returns 0 if not, 1 if so.
+ */
+int already_have_dump(file)
+dumpfile_t *file;
+{
+    dumplist_t *fileentry = NULL;
+
+    if(!file) return(0);
+    for(fileentry=alldumps_list;fileentry;fileentry=fileentry->next){
+       if(headers_equal(file, fileentry->file, 0)) return(1);
+    }
+    return(0);
+}
+
+/*
+ * Open the named file and append its contents to the (hopefully open) file
+ * descriptor supplies.
+ */
+static void append_file_to_fd(filename, fd)
+char *filename;
+int fd;
+{
+    ssize_t bytes_read;
+    ssize_t s;
+    off_t wc = 0;
+    char *buffer;
+
+    if(blocksize == -1)
+       blocksize = DISK_BLOCK_BYTES;
+    buffer = alloc(blocksize);
+
+    if((tapefd = open(filename, O_RDONLY)) == -1) {
+       error("can't open %s: %s", filename, strerror(errno));
+       /* NOTREACHED */
+    }
+
+    for (;;) {
+       bytes_read = get_block(tapefd, buffer, 1); /* same as isafile = 1 */
+       if(bytes_read < 0) {
+           error("read error: %s", strerror(errno));
+           /* NOTREACHED */
+       }
+
+       if (bytes_read == 0)
+               break;
+
+       s = fullwrite(fd, buffer, bytes_read);
+       if (s < bytes_read) {
+           fprintf(stderr,"Error %d (%s) offset " OFF_T_FMT "+" AM64_FMT ", wrote " AM64_FMT "\n",
+                       errno, strerror(errno), wc, (am64_t)bytes_read, (am64_t)s);
+           if (s < 0) {
+               if((errno == EPIPE) || (errno == ECONNRESET)) {
+                   error("%s: pipe reader has quit in middle of file.\n",
+                       get_pname());
+                   /* NOTREACHED */
+               }
+               error("restore: write error = %s", strerror(errno));
+               /* NOTREACHED */
+           }
+           error("Short write: wrote %d bytes expected %d\n", s, bytes_read);
+           /* NOTREACHCED */
+       }
+       wc += bytes_read;
+    }
+
+    amfree(buffer);
+    aclose(tapefd);
+}
+
+/*
+ * Tape changer support routines, stolen brazenly from amtape
+ */
+static int 
+scan_init(ud, rc, ns, bk, s)
+     void * ud;
+     int rc, ns, bk, s;
+{
+    if(rc)
+        error("could not get changer info: %s", changer_resultstr);
+
+    nslots = ns;
+    backwards = bk;
+
+    return 0;
+}
+int loadlabel_slot(ud, rc, slotstr, device)
+     void *ud;
+int rc;
+char *slotstr;
+char *device;
+{
+    char *errstr;
+    char *datestamp = NULL;
+    char *label = NULL;
+
+
+    if(rc > 1)
+        error("could not load slot %s: %s", slotstr, changer_resultstr);
+    else if(rc == 1)
+        fprintf(stderr, "%s: slot %s: %s\n",
+                get_pname(), slotstr, changer_resultstr);
+    else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
+        fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
+    else {
+        fprintf(stderr, "%s: slot %s: date %-8s label %s",
+                get_pname(), slotstr, datestamp, label);
+        if(strcmp(label, FAKE_LABEL) != 0
+           && strcmp(label, searchlabel) != 0)
+            fprintf(stderr, " (wrong tape)\n");
+        else {
+            fprintf(stderr, " (exact label match)\n");
+            if((errstr = tape_rewind(device)) != NULL) {
+                fprintf(stderr,
+                        "%s: could not rewind %s: %s",
+                        get_pname(), device, errstr);
+                amfree(errstr);
+            }
+           amfree(cur_tapedev);
+           curslot = stralloc(slotstr);
+            amfree(datestamp);
+            amfree(label);
+           if(device)
+               cur_tapedev = stralloc(device);
+            return 1;
+        }
+    }
+    amfree(datestamp);
+    amfree(label);
+
+    if(cur_tapedev) amfree(cur_tapedev);
+    curslot = stralloc(slotstr);
+    if(!device) return(1);
+    cur_tapedev = stralloc(device);
+
+    return 0;
+}
+
+
+/* non-local functions follow */
+
+
+
+/*
+ * Check whether we've read all of the preceding parts of a given split dump,
+ * generally used to see if we're done and can close the thing.
+ */
+int have_all_parts (file, upto)
+dumpfile_t *file;
+int upto;
+{
+    int c;
+    int *foundparts = NULL;
+    dumplist_t *fileentry = NULL;
+
+    if(!file || file->partnum < 1) return(0);
+
+    if(upto < 1) upto = file->totalparts;
+
+    foundparts = alloc(sizeof(int) * upto); 
+    for(c = 0 ; c< upto; c++) foundparts[c] = 0;
+    
+    for(fileentry=alldumps_list;fileentry; fileentry=fileentry->next){
+       dumpfile_t *cur_file = fileentry->file;
+       if(headers_equal(file, cur_file, 1)){
+           if(cur_file->partnum > upto){
+               amfree(foundparts);
+               return(0);
+           }
+
+           foundparts[cur_file->partnum - 1] = 1;
+       }
+    }
+
+    for(c = 0 ; c< upto; c++){
+       if(!foundparts[c]){
+           amfree(foundparts);
+           return(0);
+       }
+    }
+    
+    amfree(foundparts);
+    return(1);
+}
+
+/*
+ * Free up the open filehandles and memory we were using to track in-progress
+ * dumpfiles (generally for split ones we're putting back together).  If
+ * applicable, also find the ones that are continuations of one another and
+ * string them together.  If given an optional file header argument, flush
+ * only that dump and do not flush/free any others.
+ */
+void flush_open_outputs(reassemble, only_file)
+int reassemble;
+dumpfile_t *only_file;
+{
+    open_output_t *cur_out = NULL, *prev = NULL;
+    find_result_t *sorted_files = NULL;
+    amwait_t compress_status;
+
+    if(!only_file){
+       fprintf(stderr, "\n");
+    }
+
+    /*
+     * Deal with any split dumps we've been working on, appending pieces
+     * that haven't yet been appended and closing filehandles we've been
+     * holding onto.
+     */
+    if(reassemble){
+       find_result_t *cur_find_res = NULL;
+       int outfd = -1, lastpartnum = -1;
+       dumpfile_t *main_file = NULL;
+       cur_out = open_outputs;
+       
+       /* stick the dumpfile_t's into a list find_result_t's so that we can
+          abuse existing sort functionality */
+       for(cur_out=open_outputs; cur_out; cur_out=cur_out->next){
+           find_result_t *cur_find_res = NULL;
+           dumpfile_t *cur_file = cur_out->file;
+           /* if we requested a particular file, do only that one */
+           if(only_file && !headers_equal(cur_file, only_file, 1)){
+               continue;
+           }
+           cur_find_res = alloc(sizeof(find_result_t));
+           memset(cur_find_res, '\0', sizeof(find_result_t));
+           cur_find_res->datestamp = atoi(cur_file->datestamp);
+           cur_find_res->hostname = stralloc(cur_file->name);
+           cur_find_res->diskname = stralloc(cur_file->disk);
+           cur_find_res->level = cur_file->dumplevel;
+           if(cur_file->partnum < 1) cur_find_res->partnum = stralloc("--");
+           else{
+               char part_str[NUM_STR_SIZE];
+               snprintf(part_str, sizeof(part_str), "%d", cur_file->partnum);
+               cur_find_res->partnum = stralloc(part_str);
+           }
+           cur_find_res->user_ptr = (void*)cur_out;
+
+           cur_find_res->next = sorted_files;
+           sorted_files = cur_find_res;
+       }
+       sort_find_result("hkdlp", &sorted_files);
+
+       /* now we have an in-order list of the files we need to concatenate */
+       cur_find_res = sorted_files;
+       for(cur_find_res=sorted_files;
+               cur_find_res;
+               cur_find_res=cur_find_res->next){
+           dumpfile_t *cur_file = NULL;
+           cur_out = (open_output_t*)cur_find_res->user_ptr;
+           cur_file = cur_out->file;
+
+           /* if we requested a particular file, do only that one */
+           if(only_file && !headers_equal(cur_file, only_file, 1)){
+               continue;
+           }
+
+           if(cur_file->type == F_SPLIT_DUMPFILE) {
+               /* is it a continuation of one we've been writing? */
+               if(main_file && cur_file->partnum > lastpartnum &&
+                       headers_equal(cur_file, main_file, 1)){
+
+                   /* effectively changing filehandles */
+                   aclose(cur_out->outfd);
+                   cur_out->outfd = outfd;
+
+                   fprintf(stderr, "Merging %s with %s\n",
+                           make_filename(cur_file), make_filename(main_file));
+                   append_file_to_fd(make_filename(cur_file), outfd);
+                   if(unlink(make_filename(cur_file)) < 0){
+                       fprintf(stderr, "Failed to unlink %s: %s\n",
+                                    make_filename(cur_file), strerror(errno));
+                   }
+               }
+               /* or a new file? */
+               else{
+                   if(outfd >= 0) aclose(outfd);
+                   if(main_file) amfree(main_file);
+                   main_file = alloc(sizeof(dumpfile_t));
+                   memcpy(main_file, cur_file, sizeof(dumpfile_t));
+                   outfd = cur_out->outfd;
+                   if(outfd < 0){
+                       if((outfd = open(make_filename(cur_file), O_RDWR|O_APPEND)) < 0){
+                         error("Couldn't open %s for appending: %s\n",
+                               make_filename(cur_file), strerror(errno));
+                       }
+                   }
+               }
+               lastpartnum = cur_file->partnum;
+           }
+           else {
+               aclose(cur_out->outfd);
+           }
+       }
+       if(outfd >= 0) {
+           aclose(outfd);
+       }
+
+       amfree(main_file);
+       free_find_result(&sorted_files);
+    }
+
+    /*
+     * Now that the split dump closure is done, free up resources we don't
+     * need anymore.
+     */
+    for(cur_out=open_outputs; cur_out; cur_out=cur_out->next){
+       dumpfile_t *cur_file = NULL;
+       if(prev) amfree(prev);
+       cur_file = cur_out->file;
+       /* if we requested a particular file, do only that one */
+       if(only_file && !headers_equal(cur_file, only_file, 1)){
+           continue;
+       }
+       if(!reassemble) {
+           aclose(cur_out->outfd);
+       }
+
+       if(cur_out->comp_enc_pid > 0){
+           waitpid(cur_out->comp_enc_pid, &compress_status, 0);
+       }
+       amfree(cur_out->file);
+       prev = cur_out;
+    }
+
+    open_outputs = NULL;
+}
+
+/*
+ * Turn a fileheader into a string suited for use on the filesystem.
+ */
+char *make_filename(file)
+dumpfile_t *file;
+{
+    char number[NUM_STR_SIZE];
+    char part[NUM_STR_SIZE];
+    char totalparts[NUM_STR_SIZE];
+    char *sfn = NULL;
+    char *fn = NULL;
+    char *pad = NULL;
+    int padlen = 0;
+
+    snprintf(number, sizeof(number), "%d", file->dumplevel);
+    snprintf(part, sizeof(part), "%d", file->partnum);
+
+    if(file->totalparts < 0){
+       snprintf(totalparts, sizeof(totalparts), "UNKNOWN");
+    }
+    else{
+       snprintf(totalparts, sizeof(totalparts), "%d", file->totalparts);
+    }
+    padlen = strlen(totalparts) + 1 - strlen(part);
+    pad = alloc(padlen);
+    memset(pad, '0', padlen);
+    pad[padlen - 1] = '\0';
+
+    snprintf(part, sizeof(part), "%s%d", pad, file->partnum);
+
+    sfn = sanitise_filename(file->disk);
+    fn = vstralloc(file->name,
+                  ".",
+                  sfn, 
+                  ".",
+                  file->datestamp,
+                  ".",
+                  number,
+                  NULL);
+    if(file->partnum > 0){
+       fn = vstralloc(fn, ".", part, NULL);
+    }
+    amfree(sfn);
+    amfree(pad);
+    return fn;
+}
+
+
+/*
+XXX Making this thing a lib functiong broke a lot of assumptions everywhere,
+but I think I've found them all.  Maybe.  Damn globals all over the place.
+*/
+static ssize_t get_block(tapefd, buffer, isafile)
+int tapefd, isafile;
+char *buffer;
+{
+    if(isafile)
+       return (fullread(tapefd, buffer, blocksize));
+
+    return(tapefd_read(tapefd, buffer, blocksize));
+}
+
+int disk_match(file, datestamp, hostname, diskname, level)
+dumpfile_t *file;
+char *datestamp, *hostname, *diskname, *level;
+/*
+ * Returns 1 if the current dump file matches the hostname and diskname
+ * regular expressions given on the command line, 0 otherwise.  As a 
+ * special case, empty regexs are considered equivalent to ".*": they 
+ * match everything.
+ */
+{
+    char level_str[NUM_STR_SIZE];
+    snprintf(level_str, sizeof(level_str), "%d", file->dumplevel);
+
+    if(file->type != F_DUMPFILE && file->type != F_SPLIT_DUMPFILE) return 0;
+
+    if((*hostname == '\0' || match_host(hostname, file->name)) &&
+       (*diskname == '\0' || match_disk(diskname, file->disk)) &&
+       (*datestamp == '\0' || match_datestamp(datestamp, file->datestamp)) &&
+       (*level == '\0' || match_level(level, level_str)))
+       return 1;
+    else
+       return 0;
+}
+
+
+void read_file_header(file, tapefd, isafile, flags)
+dumpfile_t *file;
+int tapefd;
+int isafile;
+rst_flags_t *flags;
+/*
+ * Reads the first block of a tape file.
+ */
+{
+    ssize_t bytes_read;
+    char *buffer;
+  
+    if(flags->blocksize > 0)
+       blocksize = flags->blocksize;
+    else if(blocksize == -1)
+       blocksize = DISK_BLOCK_BYTES;
+    buffer = alloc(blocksize);
+
+    bytes_read = get_block(tapefd, buffer, isafile);
+    if(bytes_read < 0) {
+       error("error reading file header: %s", strerror(errno));
+       /* NOTREACHED */
+    }
+
+    if(bytes_read < blocksize) {
+       if(bytes_read == 0) {
+           fprintf(stderr, "%s: missing file header block\n", get_pname());
+       } else {
+           fprintf(stderr, "%s: short file header block: " AM64_FMT " byte%s\n",
+                   get_pname(), (am64_t)bytes_read, (bytes_read == 1) ? "" : "s");
+       }
+       file->type = F_UNKNOWN;
+    } else {
+       parse_file_header(buffer, file, bytes_read);
+    }
+    amfree(buffer);
+}
+
+
+void drain_file(tapefd, flags)
+int tapefd;
+rst_flags_t *flags;
+{
+    ssize_t bytes_read;
+    char *buffer;
+
+    if(flags->blocksize)
+       blocksize = flags->blocksize;
+    else if(blocksize == -1)
+       blocksize = DISK_BLOCK_BYTES;
+    buffer = alloc(blocksize);
+
+    do {
+       bytes_read = get_block(tapefd, buffer, 0);
+       if(bytes_read < 0) {
+           error("drain read error: %s", strerror(errno));
+       }
+    } while (bytes_read > 0);
+
+    amfree(buffer);
+}
+
+ssize_t restore(file, filename, tapefd, isafile, flags)
+dumpfile_t *file;
+char *filename;
+int tapefd;
+int isafile;
+rst_flags_t *flags;
+/*
+ * Restore the current file from tape.  Depending on the settings of
+ * the command line flags, the file might need to be compressed or
+ * uncompressed.  If so, a pipe through compress or uncompress is set
+ * up.  The final output usually goes to a file named host.disk.date.lev,
+ * but with the -p flag the output goes to stdout (and presumably is
+ * piped to restore).
+ */
+{
+    int dest = -1, out;
+    ssize_t s;
+    int file_is_compressed;
+    int is_continuation = 0;
+    int check_for_aborted = 0;
+    char *tmp_filename = NULL, *final_filename = NULL;
+    struct stat statinfo;
+    open_output_t *myout = NULL, *oldout = NULL;
+    dumplist_t *tempdump = NULL, *fileentry = NULL;
+    char *buffer;
+    int need_compress=0, need_uncompress=0, need_decrypt=0;
+    int stage=0;
+    ssize_t bytes_read;
+    struct pipeline {
+        int    pipe[2];
+    } pipes[3];
+
+    if(flags->blocksize)
+       blocksize = flags->blocksize;
+    else if(blocksize == -1)
+       blocksize = DISK_BLOCK_BYTES;
+
+    if(already_have_dump(file)){
+       fprintf(stderr, " *** Duplicate file %s, one is probably an aborted write\n", make_filename(file));
+       check_for_aborted = 1;
+    }
+
+    /* store a shorthand record of this dump */
+    tempdump = alloc(sizeof(dumplist_t));
+    tempdump->file = alloc(sizeof(dumpfile_t));
+    tempdump->next = NULL;
+    memcpy(tempdump->file, file, sizeof(dumpfile_t));
+
+    /*
+     * If we're appending chunked files to one another, and if this is a
+     * continuation of a file we just restored, and we've still got the
+     * output handle from that previous restore, we're golden.  Phew.
+     */
+    if(flags->inline_assemble && file->type == F_SPLIT_DUMPFILE){
+       myout = open_outputs;
+       while(myout != NULL){
+           if(myout->file->type == F_SPLIT_DUMPFILE &&
+                   headers_equal(file, myout->file, 1)){
+               if(file->partnum == myout->lastpartnum + 1){
+                   is_continuation = 1;
+                   break;
+               }
+           }
+           myout = myout->next;
+       }
+       if(myout != NULL) myout->lastpartnum = file->partnum;
+       else if(file->partnum != 1){
+           fprintf(stderr, "%s:      Chunk out of order, will save to disk and append to output.\n", get_pname());
+           flags->pipe_to_fd = -1;
+           flags->compress = 0;
+           flags->leave_comp = 1;
+       }
+       if(myout == NULL){
+           myout = alloc(sizeof(open_output_t));
+           memset(myout, 0, sizeof(open_output_t));
+       }
+    }
+    else{
+      myout = alloc(sizeof(open_output_t));
+      memset(myout, 0, sizeof(open_output_t));
+    }
+
+
+    if(is_continuation && flags->pipe_to_fd == -1){
+       fprintf(stderr, "%s:      appending to %s\n", get_pname(),
+                   make_filename(myout->file));
+    }
+
+    /* adjust compression flag */
+    file_is_compressed = file->compressed;
+    if(!flags->compress && file_is_compressed && !known_compress_type(file)) {
+       fprintf(stderr, 
+               "%s: unknown compression suffix %s, can't uncompress\n",
+               get_pname(), file->comp_suffix);
+       flags->compress = 1;
+    }
+
+    /* set up final destination file */
+
+    if(is_continuation && myout != NULL) {
+      out = myout->outfd;
+    } else {
+      if(flags->pipe_to_fd != -1) {
+         dest = flags->pipe_to_fd;     /* standard output */
+      } else {
+         char *filename_ext = NULL;
+  
+         if(flags->compress) {
+             filename_ext = file_is_compressed ? file->comp_suffix
+                                             : COMPRESS_SUFFIX;
+         } else if(flags->raw) {
+             filename_ext = ".RAW";
+         } else {
+             filename_ext = "";
+         }
+         filename_ext = stralloc2(filename, filename_ext);
+         tmp_filename = stralloc(filename_ext); 
+         if(flags->restore_dir != NULL) {
+             char *tmpstr = vstralloc(flags->restore_dir, "/",
+                                      tmp_filename, NULL);
+             amfree(tmp_filename);
+             tmp_filename = tmpstr;
+         } 
+         final_filename = stralloc(tmp_filename); 
+         tmp_filename = newvstralloc(tmp_filename, ".tmp", NULL);
+         if((dest = creat(tmp_filename, CREAT_MODE)) < 0) {
+             error("could not create output file %s: %s",
+                                              tmp_filename, strerror(errno));
+             /*NOTREACHED*/
+         }
+         amfree(filename_ext);
+      }
+  
+      out = dest;
+    }
+
+    /*
+     * If -r or -h, write the header before compress or uncompress pipe.
+     * Only write DISK_BLOCK_BYTES, regardless of how much was read.
+     * This makes the output look like a holding disk image, and also
+     * makes it easier to remove the header (e.g. in amrecover) since
+     * it has a fixed size.
+     */
+    if(flags->raw || (flags->headers && !is_continuation)) {
+       int w;
+       char *cont_filename;
+       dumpfile_t tmp_hdr;
+
+       if(flags->compress && !file_is_compressed) {
+           file->compressed = 1;
+           snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
+                       " %s %s |", UNCOMPRESS_PATH,
+#ifdef UNCOMPRESS_OPT
+                       UNCOMPRESS_OPT
+#else
+                       ""
+#endif
+                       );
+           strncpy(file->comp_suffix,
+                   COMPRESS_SUFFIX,
+                   sizeof(file->comp_suffix)-1);
+           file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
+       }
+
+       memcpy(&tmp_hdr, file, sizeof(dumpfile_t));
+
+       /* remove CONT_FILENAME from header */
+       cont_filename = stralloc(file->cont_filename);
+       memset(file->cont_filename,'\0',sizeof(file->cont_filename));
+       file->blocksize = DISK_BLOCK_BYTES;
+
+       /*
+        * Dumb down split file headers as well, so that older versions of
+        * things like amrecover won't gag on them.
+        */
+       if(file->type == F_SPLIT_DUMPFILE && flags->mask_splits){
+           file->type = F_DUMPFILE;
+       }
+
+       buffer = alloc(DISK_BLOCK_BYTES);
+       build_header(buffer, file, DISK_BLOCK_BYTES);
+
+       if((w = fullwrite(out, buffer, DISK_BLOCK_BYTES)) != DISK_BLOCK_BYTES) {
+           if(w < 0) {
+               error("write error: %s", strerror(errno));
+           } else {
+               error("write error: %d instead of %d", w, DISK_BLOCK_BYTES);
+           }
+       }
+       amfree(buffer);
+       /* add CONT_FILENAME to header */
+#if 0
+//     strncpy(file->cont_filename, cont_filename, sizeof(file->cont_filename));
+#endif
+       amfree(cont_filename);
+       memcpy(file, &tmp_hdr, sizeof(dumpfile_t));
+    }
+    /* find out if compression or uncompression is needed here */
+    if(flags->compress && !file_is_compressed && !is_continuation
+         && !flags->leave_comp
+         && (flags->inline_assemble || file->type != F_SPLIT_DUMPFILE))
+       need_compress=1;
+       
+    if(!flags->raw && !flags->compress && file_is_compressed
+         && !is_continuation && !flags->leave_comp && (flags->inline_assemble
+         || file->type != F_SPLIT_DUMPFILE))
+       need_uncompress=1;   
+
+    if(!flags->raw && file->encrypted)
+       need_decrypt=1;
+   
+    /* Setup pipes for decryption / compression / uncompression  */
+    stage = 0;
+    if (need_decrypt) {
+      if (pipe(&pipes[stage].pipe[0]) < 0) 
+        error("error [pipe[%d]: %s]", stage, strerror(errno));
+      stage++;
+    }
+
+    if (need_compress || need_uncompress) {
+      if (pipe(&pipes[stage].pipe[0]) < 0) 
+        error("error [pipe[%d]: %s]", stage, strerror(errno));
+      stage++;
+    }
+    pipes[stage].pipe[0] = -1; 
+    pipes[stage].pipe[1] = out; 
+
+    stage = 0;
+
+    /* decrypt first if it's encrypted and no -r */
+    if(need_decrypt) {
+      switch(myout->comp_enc_pid = fork()) {
+      case -1:
+       error("could not fork for decrypt: %s", strerror(errno));
+      default:
+       aclose(pipes[stage].pipe[0]);
+       aclose(pipes[stage+1].pipe[1]);
+        stage++;
+       break;
+      case 0:
+       if(dup2(pipes[stage].pipe[0], 0) == -1)
+           error("error decrypt stdin [dup2 %d %d: %s]", stage,
+               pipes[stage].pipe[0], strerror(errno));
+
+       if(dup2(pipes[stage+1].pipe[1], 1) == -1)
+           error("error decrypt stdout [dup2 %d %d: %s]", stage + 1,
+               pipes[stage+1].pipe[1], strerror(errno));
+
+       safe_fd(-1, 0);
+       if (*file->srv_encrypt) {
+         (void) execlp(file->srv_encrypt, file->srv_encrypt,
+                       file->srv_decrypt_opt, NULL);
+         error("could not exec %s: %s", file->srv_encrypt, strerror(errno));
+       }  else if (*file->clnt_encrypt) {
+         (void) execlp(file->clnt_encrypt, file->clnt_encrypt,
+                       file->clnt_decrypt_opt, NULL);
+         error("could not exec %s: %s", file->clnt_encrypt, strerror(errno));
+       }
+      }
+    }
+
+    if (need_compress) {
+        /*
+         * Insert a compress pipe
+         */
+       switch(myout->comp_enc_pid = fork()) {
+       case -1: error("could not fork for %s: %s",
+                      COMPRESS_PATH, strerror(errno));
+       default:
+           aclose(pipes[stage].pipe[0]);
+           aclose(pipes[stage+1].pipe[1]);
+            stage++;
+           break;
+       case 0:
+           if(dup2(pipes[stage].pipe[0], 0) == -1)
+               error("error compress stdin [dup2 %d %d: %s]", stage,
+                 pipes[stage].pipe[0], strerror(errno));
+
+           if(dup2(pipes[stage+1].pipe[1], 1) == -1)
+               error("error compress stdout [dup2 %d %d: %s]", stage + 1,
+                 pipes[stage+1].pipe[1], strerror(errno));
+
+           if (*flags->comp_type == '\0') {
+               flags->comp_type = NULL;
+           }
+
+           safe_fd(-1, 0);
+           (void) execlp(COMPRESS_PATH, COMPRESS_PATH, flags->comp_type, (char *)0);
+           error("could not exec %s: %s", COMPRESS_PATH, strerror(errno));
+       }
+    } else if(need_uncompress) {
+        /*
+         * If not -r, -c, -l, and file is compressed, and split reassembly 
+         * options are sane, insert uncompress pipe
+         */
+
+       /* 
+        * XXX for now we know that for the two compression types we
+        * understand, .Z and optionally .gz, UNCOMPRESS_PATH will take
+        * care of both.  Later, we may need to reference a table of
+        * possible uncompress programs.
+        */ 
+       switch(myout->comp_enc_pid = fork()) {
+       case -1: 
+           error("could not fork for %s: %s",
+                 UNCOMPRESS_PATH, strerror(errno));
+       default:
+           aclose(pipes[stage].pipe[0]);
+           aclose(pipes[stage+1].pipe[1]);
+            stage++;
+           break;
+       case 0:
+           if(dup2(pipes[stage].pipe[0], 0) == -1)
+               error("error uncompress stdin [dup2 %d %d: %s]", stage,
+                 pipes[stage].pipe[0], strerror(errno));
+
+           if(dup2(pipes[stage+1].pipe[1], 1) == -1)
+               error("error uncompress stdout [dup2 %d %d: %s]", stage + 1,
+                 pipes[stage+1].pipe[1], strerror(errno));
+
+           safe_fd(-1, 0);
+           if (*file->srvcompprog) {
+             (void) execlp(file->srvcompprog, file->srvcompprog, "-d", NULL);
+             error("could not exec %s: %s", file->srvcompprog, strerror(errno));
+           } else if (*file->clntcompprog) {
+             (void) execlp(file->clntcompprog, file->clntcompprog, "-d", NULL);
+             error("could not exec %s: %s", file->clntcompprog, strerror(errno));
+           } else {
+             (void) execlp(UNCOMPRESS_PATH, UNCOMPRESS_PATH,
+#ifdef UNCOMPRESS_OPT
+                         UNCOMPRESS_OPT,
+#endif
+                         (char *)0);
+             error("could not exec %s: %s", UNCOMPRESS_PATH, strerror(errno));
+           }
+       }
+    }
+
+    /* copy the rest of the file from tape to the output */
+    if(flags->blocksize > 0)
+       blocksize = flags->blocksize;
+    else if(blocksize == -1)
+       blocksize = DISK_BLOCK_BYTES;
+    buffer = alloc(blocksize);
+
+    do {
+       bytes_read = get_block(tapefd, buffer, isafile);
+       if(bytes_read < 0) {
+           error("restore read error: %s", strerror(errno));
+           /* NOTREACHED */
+       }
+
+       if(bytes_read > 0) {
+           if((s = fullwrite(pipes[0].pipe[1], buffer, bytes_read)) < 0) {
+               if ((errno == EPIPE) || (errno == ECONNRESET)) {
+                   /*
+                    * reading program has ended early
+                    * e.g: bzip2 closes pipe when it
+                    * trailing garbage after EOF
+                    */
+                   break;
+               }
+               perror("restore: write error");
+               exit(2);
+           }
+       }
+       else if(isafile) {
+           /*
+            * See if we need to switch to the next file in a holding restore
+            */
+           if(file->cont_filename[0] == '\0') {
+               break;                          /* no more files */
+           }
+           aclose(tapefd);
+           if((tapefd = open(file->cont_filename, O_RDONLY)) == -1) {
+               char *cont_filename = strrchr(file->cont_filename,'/');
+               if(cont_filename) {
+                   cont_filename++;
+                   if((tapefd = open(cont_filename,O_RDONLY)) == -1) {
+                       error("can't open %s: %s", file->cont_filename,
+                             strerror(errno));
+                   }
+                   else {
+                       fprintf(stderr, "cannot open %s: %s\n",
+                               file->cont_filename, strerror(errno));
+                       fprintf(stderr, "using %s\n",
+                               cont_filename);
+                   }
+               }
+               else {
+                   error("can't open %s: %s", file->cont_filename,
+                         strerror(errno));
+               }
+           }
+           read_file_header(file, tapefd, isafile, flags);
+           if(file->type != F_DUMPFILE && file->type != F_CONT_DUMPFILE
+                   && file->type != F_SPLIT_DUMPFILE) {
+               fprintf(stderr, "unexpected header type: ");
+               print_header(stderr, file);
+               exit(2);
+           }
+       }
+    } while (bytes_read > 0);
+
+    amfree(buffer);
+
+    if(!flags->inline_assemble) {
+        if(out != dest)
+           aclose(out);
+    }
+    if(!is_continuation){
+       if(tmp_filename && stat(tmp_filename, &statinfo) < 0){
+           error("Can't stat the file I just created (%s)!\n", tmp_filename);
+       }
+       if(check_for_aborted){
+           char *old_dump = final_filename;
+           struct stat oldstat;
+           if(stat(old_dump, &oldstat) >= 0){
+               if(oldstat.st_size <= statinfo.st_size){
+                   dumplist_t *prev_fileentry = NULL;
+                   open_output_t *prev_out = NULL;
+                   fprintf(stderr, "Newer restore is larger, using that\n");
+                   /* nuke the old dump's entry in alldump_list */
+                   for(fileentry=alldumps_list;
+                           fileentry->next;
+                           fileentry=fileentry->next){
+                       if(headers_equal(file, fileentry->file, 0)){
+                           if(prev_fileentry){
+                               prev_fileentry->next = fileentry->next;
+                           }
+                           else {
+                               alldumps_list = fileentry->next;
+                           }
+                           amfree(fileentry);
+                           break;
+                       }
+                       prev_fileentry = fileentry;
+                   }
+                   myout = open_outputs;
+                   while(myout != NULL){
+                       if(headers_equal(file, myout->file, 0)){
+                           if(myout->outfd >= 0)
+                               aclose(myout->outfd);
+                           if(prev_out){
+                               prev_out->next = myout->next;
+                           }
+                           else open_outputs = myout->next;
+                           amfree(myout);
+                           break;
+                       }
+                       prev_out = myout;
+                       myout = myout->next;
+                   }
+               }
+               else{
+                   fprintf(stderr, "Older restore is larger, using that\n");
+                   unlink(tmp_filename);
+                   amfree(tempdump->file);
+                   amfree(tempdump);
+                   amfree(tmp_filename);
+                   amfree(final_filename);
+                    return (bytes_read);
+               }
+           }
+       }
+       if(tmp_filename && final_filename &&
+               rename(tmp_filename, final_filename) < 0){
+           error("Can't rename %s to %s: %s\n", tmp_filename, final_filename,
+                                            strerror(errno));
+       }
+    }
+    if(tmp_filename) amfree(tmp_filename);
+    if(final_filename) amfree(final_filename);
+
+
+    /*
+     * actually insert tracking data for this file into our various
+     * structures (we waited in case we needed to give up)
+     */
+    if(!is_continuation){
+        oldout = alloc(sizeof(open_output_t));
+        oldout->file = alloc(sizeof(dumpfile_t));
+        memcpy(oldout->file, file, sizeof(dumpfile_t));
+        if(flags->inline_assemble) oldout->outfd = pipes[0].pipe[1];
+       else oldout->outfd = -1;
+        oldout->comp_enc_pid = -1;
+        oldout->lastpartnum = file->partnum;
+        oldout->next = open_outputs;
+        open_outputs = oldout;
+    }
+    if(alldumps_list){
+       for(fileentry=alldumps_list;fileentry->next;fileentry=fileentry->next);
+       fileentry->next = tempdump;
+    }
+    else {
+       alldumps_list = tempdump;
+    }
+
+    return (bytes_read);
+}
+
+
+
+/* 
+ * Take a pattern of dumps and restore it blind, a la amrestore.  In addition,
+ * be smart enough to change tapes and continue with minimal operator
+ * intervention, and write out a record of what was found on tapes in the
+ * the regular logging format.  Can take a tapelist with a specific set of
+ * tapes to search (rather than "everything I can find"), which in turn can
+ * optionally list specific files to restore.
+ */
+void search_tapes(prompt_out, use_changer, tapelist, match_list, flags, their_features)
+FILE *prompt_out;
+int use_changer;
+tapelist_t *tapelist;
+match_list_t *match_list;
+rst_flags_t *flags;
+am_feature_t *their_features;
+{
+    struct stat stat_tape;
+    char *err;
+    int have_changer = 1;
+    int slot_num = -1;
+    int slots = -1;
+    int filenum;
+    FILE *logstream = NULL;
+    dumplist_t *fileentry = NULL;
+    tapelist_t *desired_tape = NULL;
+    struct sigaction act, oact;
+    int newtape = 1;
+    ssize_t bytes_read = 0;
+
+    struct seentapes{
+       struct seentapes *next;
+       char *slotstr;
+       char *label;
+       dumplist_t *files;
+    } *seentapes = NULL;
+
+    if(!prompt_out) prompt_out = stderr;
+
+    if(flags->blocksize) blocksize = flags->blocksize;
+    else if(blocksize == -1) blocksize = DISK_BLOCK_BYTES;
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    /* catch SIGINT with something that'll flush unmerged splits */
+    act.sa_handler = handle_sigint;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    if(sigaction(SIGINT, &act, &oact) != 0){
+       error("error setting SIGINT handler: %s", strerror(errno));
+    }
+    if(flags->delay_assemble || flags->inline_assemble) exitassemble = 1;
+    else exitassemble = 0;
+
+    /* if given a log file, print an inventory of stuff found */
+    if(flags->inventory_log){
+       if(!strcmp(flags->inventory_log, "-")) logstream = stdout;
+       else if((logstream = fopen(flags->inventory_log, "w+")) == NULL){
+           error("Couldn't open log file %s for writing: %s\n",
+                 flags->inventory_log, strerror(errno));
+       }
+    }
+
+    /* Suss what tape device we're using, whether there's a changer, etc. */
+    if(!use_changer || (have_changer = changer_init()) == 0) {
+       if(flags->alt_tapedev) cur_tapedev = stralloc(flags->alt_tapedev);
+       else if(!cur_tapedev) cur_tapedev = getconf_str(CNF_TAPEDEV);
+       /* XXX oughta complain if no config is loaded */
+       fprintf(stderr, "%s: Using tapedev %s\n", get_pname(), cur_tapedev);
+       have_changer = 0;
+    } else if (have_changer != 1) {
+       error("changer initialization failed: %s", strerror(errno));
+    }
+    else{ /* good, the changer works, see what it can do */
+       changer_info(&slots, &curslot, &backwards);
+    }
+
+    if(tapelist && !flags->amidxtaped){
+      slots = num_entries(tapelist);
+      /*
+       Spit out a list of expected tapes, so people with manual changers know
+       what to load
+      */
+      fprintf(prompt_out, "The following tapes are needed:");
+      for(desired_tape = tapelist;
+          desired_tape != NULL;
+         desired_tape = desired_tape->next){
+       fprintf(prompt_out, " %s", desired_tape->label);
+      }
+      fprintf(prompt_out, "\n");
+      fflush(prompt_out);
+      if(flags->wait_tape_prompt){
+       char *input = NULL;
+        fprintf(prompt_out,"Press enter when ready\n");
+       fflush(prompt_out);
+        input = agets(stdin);
+       amfree(input);
+       fprintf(prompt_out, "\n");
+       fflush(prompt_out);
+      }
+    }
+    desired_tape = tapelist;
+
+    /*
+     * If we're not given a tapelist, iterate over everything our changer can
+     * find.  If there's no changer, we'll prompt to be handfed tapes.
+     *
+     * If we *are* given a tapelist, restore from those tapes in the order in
+     * which they're listed.  Unless the changer (if we have one) can't go
+     * backwards, in which case check every tape we see and restore from it if
+     * appropriate.
+     *
+     * (obnoxious, isn't this?)
+     */
+    slot_num = 0;
+    curslot = stralloc("<none>");
+    while(desired_tape || ((slot_num < slots || !have_changer) && !tapelist)){
+       char *label = NULL;
+       struct seentapes *tape_seen = NULL;
+       dumpfile_t file, tapestart, prev_rst_file;
+       char *logline = NULL;
+       int tapefile_idx = -1;
+       int wrongtape = 0;
+       int isafile = 0;
+
+       /*
+        * Deal with instances where we're being asked to restore from a file
+        */
+       if(desired_tape && desired_tape->isafile){
+           isafile = 1;
+           if ((tapefd = open(desired_tape->label, 0)) == -1){
+               fprintf(stderr, "could not open %s: %s\n",
+                     desired_tape->label, strerror(errno));
+               continue;
+           }
+           fprintf(stderr, "Reading %s to fd %d\n", desired_tape->label, tapefd);
+
+           read_file_header(&file, tapefd, 1, flags);
+           label = stralloc(desired_tape->label);
+       }
+       /*
+        * Make sure we can read whatever tape is loaded, then grab the label.
+        */
+       else if(cur_tapedev && newtape){
+           if(tape_stat(cur_tapedev,&stat_tape)!=0) {
+               error("could not stat %s: %s", cur_tapedev, strerror(errno));
+           }
+
+           if((err = tape_rewind(cur_tapedev)) != NULL) {
+               fprintf(stderr, "Could not rewind device '%s': %s\n",
+                        cur_tapedev, err);
+               wrongtape = 1;
+           }
+           if((tapefd = tape_open(cur_tapedev, 0)) < 0){
+               fprintf(stderr, "could not open tape device %s: %s\n",
+                        cur_tapedev, strerror(errno));
+               wrongtape = 1;
+           }
+
+           if (!wrongtape) {
+               read_file_header(&file, tapefd, 0, flags);
+               if (file.type != F_TAPESTART) {
+                   fprintf(stderr, "Not an amanda tape\n");
+                   tapefd_close(tapefd);
+                   wrongtape = 1;
+               } else {
+                   memcpy(&tapestart, &file, sizeof(dumpfile_t));
+                   label = stralloc(file.name);
+               }
+           }
+       } else if(newtape) {
+         wrongtape = 1; /* nothing loaded */
+         bytes_read = -1;
+       }
+
+       /*
+        * Skip this tape if we did it already.  Note that this would let
+        * duplicate labels through, so long as they were in the same slot.
+        * I'm over it, are you?
+        */
+       if(label && newtape && !isafile && !wrongtape){
+           for(tape_seen = seentapes; tape_seen; tape_seen = tape_seen->next){
+               if(!strcmp(tape_seen->label, label) &&
+                       !strcmp(tape_seen->slotstr, curslot)){
+                   fprintf(stderr, "Saw repeat tape %s in slot %s\n", label, curslot);
+                   wrongtape = 1;
+                   amfree(label);
+                   break;
+               }
+           }
+       }
+
+       /*
+        * See if we've got the tape we were looking for, if we were looking
+        * for something specific.
+        */
+       if((desired_tape || !cur_tapedev) && newtape && !isafile && !wrongtape){
+           if(!label || (flags->check_labels &&
+                   desired_tape && strcmp(label, desired_tape->label) != 0)){
+               if(label){
+                   fprintf(stderr, "Label mismatch, got %s and expected %s\n", label, desired_tape->label);
+                   if(have_changer && !backwards){
+                       fprintf(stderr, "Changer can't go backwards, restoring anyway\n");
+                   }
+                   else wrongtape = 1;
+               }
+               else fprintf(stderr, "No tape device initialized yet\n");
+           }
+       }
+           
+
+       /*
+        * If we have an incorrect tape loaded, go try to find the right one
+        * (or just see what the next available one is).
+        */
+       if((wrongtape || !newtape) && !isafile){
+           if(desired_tape){
+               tapefd_close(tapefd);
+               if(have_changer){
+                   fprintf(stderr,"Looking for tape %s...\n", desired_tape->label);
+                   if(backwards){
+                       searchlabel = desired_tape->label; 
+                       changer_find(NULL, scan_init, loadlabel_slot, desired_tape->label);
+                   }
+                   else{
+                       changer_loadslot("next", &curslot, &cur_tapedev);
+                   }
+                   while(have_changer && !cur_tapedev){
+                       fprintf(stderr, "Changer did not set the tape device (slot empty or changer misconfigured?)\n");
+                       changer_loadslot("next", &curslot, &cur_tapedev);
+                   }
+               }
+               else {
+                   char *input = NULL;
+
+                    if (!flags->amidxtaped) {
+                        fprintf(prompt_out,
+                                "Insert tape labeled %s in device %s "
+                                "and press return\n", 
+                                desired_tape->label, cur_tapedev);
+                        fflush(prompt_out);
+                        input = agets(stdin);
+                        amfree(input);
+                    } else if (their_features &&
+                              am_has_feature(their_features,
+                                             fe_amrecover_FEEDME)) {
+                        fprintf(prompt_out, "FEEDME %s\n",
+                                desired_tape->label);
+                        fflush(prompt_out);
+                        input = agets(stdin); /* Strips \n but not \r */
+                        if (strcmp("OK\r", input) != 0) {
+                            error("Got bad response from amrecover: %s",
+                                  input);
+                        }
+                        amfree(input);
+                    } else {
+                        error("Client doesn't support fe_amrecover_FEEDME");
+                   }
+                }
+            }
+           else{
+                assert(!flags->amidxtaped);
+               if(have_changer){
+                   if(slot_num == 0)
+                       changer_loadslot("first", &curslot, &cur_tapedev);
+                   else
+                       changer_loadslot("next", &curslot, &cur_tapedev);
+                   if(have_changer && !cur_tapedev)
+                       error("Changer did not set the tape device, probably misconfigured");
+               }
+               else {
+                   /* XXX need a condition for ending processing? */
+                   char *input = NULL;
+                    fprintf(prompt_out,"Insert a tape to search and press enter, ^D to finish reading tapes\n");
+                   fflush(prompt_out);
+                    if((input = agets(stdin)) == NULL) break;
+                   amfree(input);
+               }
+           }
+           newtape = 1;
+           amfree(label);
+           continue;
+       }
+
+       newtape = 0;
+
+       slot_num++;
+
+       if(!isafile){
+           fprintf(stderr, "Scanning %s (slot %s)\n", label, curslot);
+           fflush(stderr);
+       }
+
+       tape_seen = alloc(sizeof(struct seentapes));
+       memset(tape_seen, '\0', sizeof(struct seentapes));
+
+       tape_seen->label = label;
+       tape_seen->slotstr = stralloc(curslot);
+       tape_seen->next = seentapes;
+       tape_seen->files = NULL;
+       seentapes = tape_seen;
+
+       /*
+        * Start slogging through the tape itself.  If our tapelist (if we
+        * have one) contains a list of files to restore, obey that instead
+        * of checking for matching headers on all files.
+        */
+       filenum = 0;
+       if(desired_tape && desired_tape->numfiles > 0) tapefile_idx = 0;
+
+       /* if we know where we're going, fastforward there */
+       if(flags->fsf && !isafile){
+           int fsf_by = 0;
+
+           /* If we have a tapelist entry, filenums will be store there */
+           if(tapefile_idx >= 0)
+               fsf_by = desired_tape->files[tapefile_idx]; 
+           /*
+            * older semantics assume we're restoring one file, with the fsf
+            * flag being the filenum on tape for said file
+            */
+           else fsf_by = flags->fsf;
+
+           if(fsf_by > 0){
+               if(tapefd_rewind(tapefd) < 0) {
+                   error("Could not rewind device %s: %s", cur_tapedev,
+                                                         strerror(errno));
+               }
+
+               if(tapefd_fsf(tapefd, fsf_by) < 0) {
+                   error("Could not fsf device %s by %d: %s", cur_tapedev, fsf_by,
+                                                          strerror(errno));
+               }
+               else {
+                       filenum = fsf_by;
+               }
+               read_file_header(&file, tapefd, isafile, flags);
+           }
+       }
+
+       while((file.type == F_TAPESTART || file.type == F_DUMPFILE ||
+             file.type == F_SPLIT_DUMPFILE) &&
+             (tapefile_idx < 0 || tapefile_idx < desired_tape->numfiles)) {
+           int found_match = 0;
+           match_list_t *me;
+           dumplist_t *tempdump = NULL;
+
+           /* store record of this dump for inventorying purposes */
+           tempdump = alloc(sizeof(dumplist_t));
+           tempdump->file = alloc(sizeof(dumpfile_t));
+           tempdump->next = NULL;
+           memcpy(tempdump->file, &file, sizeof(dumpfile_t));
+           if(tape_seen->files){
+               for(fileentry=tape_seen->files;
+                       fileentry->next;
+                       fileentry=fileentry->next);
+               fileentry->next = tempdump;
+           }
+           else tape_seen->files = tempdump;
+
+           /* see if we need to restore the thing */
+           if(isafile) found_match = 1;
+           else if(tapefile_idx >= 0){ /* do it by explicit file #s */
+               if(filenum == desired_tape->files[tapefile_idx]){
+                   found_match = 1;
+                   tapefile_idx++;
+               }
+           }
+           else{ /* search and match headers */
+               for(me = match_list; me; me = me->next) {
+                   if(disk_match(&file, me->datestamp, me->hostname,
+                               me->diskname, me->level) != 0){
+                       found_match = 1;
+                       break;
+                   }
+               }
+           }
+
+           if(found_match){
+               char *filename = make_filename(&file);
+               fprintf(stderr, "%s: %3d: restoring ", get_pname(), filenum);
+               print_header(stderr, &file);
+               bytes_read = restore(&file, filename, tapefd, isafile, flags);
+               filenum ++;
+               amfree(filename);
+           }
+
+           /* advance to the next file, fast-forwarding where reasonable */
+           if(bytes_read == 0 && !isafile) {
+               tapefd_close(tapefd);
+               if((tapefd = tape_open(cur_tapedev, 0)) < 0) {
+                   error("could not open %s: %s",
+                         cur_tapedev, strerror(errno));
+               }
+           } else if(!isafile){
+               /* cheat and jump ahead to where we're going if we can */
+               if (!found_match && flags->fsf) {
+                   drain_file(tapefd, flags);
+                   filenum ++;
+               } else if(tapefile_idx >= 0 && 
+                         tapefile_idx < desired_tape->numfiles &&
+                         flags->fsf){
+                   int fsf_by = desired_tape->files[tapefile_idx] - filenum;
+                   if(fsf_by > 0){
+                       if(tapefd_fsf(tapefd, fsf_by) < 0) {
+                           error("Could not fsf device %s by %d: %s", cur_tapedev, fsf_by,
+                                 strerror(errno));
+                       }
+                       else filenum = desired_tape->files[tapefile_idx];
+                   }
+               } else if (!found_match && flags->fsf) {
+                   /* ... or fsf by 1, whatever */
+                   if(tapefd_fsf(tapefd, 1) < 0) {
+                       error("could not fsf device %s: %s",
+                             cur_tapedev, strerror(errno));
+                   } else {
+                       filenum ++;
+                   }
+               }
+           }
+
+
+           memcpy(&prev_rst_file, &file, sizeof(dumpfile_t));
+
+             
+           if(isafile)
+                break;
+            read_file_header(&file, tapefd, isafile, flags);
+
+           /* only restore a single dump, if piping to stdout */
+           if(!headers_equal(&prev_rst_file, &file, 1) &&
+              flags->pipe_to_fd == fileno(stdout)) break;
+       } /* while we keep seeing headers */
+
+       if(!isafile){
+           if(bytes_read == 0) {
+               /* XXX is this dain-bramaged? */
+               aclose(tapefd);
+               if((tapefd = tape_open(cur_tapedev, 0)) < 0) {
+                   error("could not open %s: %s",
+                       cur_tapedev, strerror(errno));
+               }
+           } else{
+               if(tapefd_fsf(tapefd, 1) < 0) {
+                   error("could not fsf %s: %s",
+                       cur_tapedev, strerror(errno));
+               }
+           }
+       }
+        tapefd_close(tapefd);
+
+       /* spit out our accumulated list of dumps, if we're inventorying */
+       if(logstream){
+            logline = log_genstring(L_START, "taper",
+                                   "datestamp %s label %s tape %d",
+                              tapestart.datestamp, tapestart.name, slot_num);
+            fprintf(logstream, logline);
+            for(fileentry=tape_seen->files; fileentry; fileentry=fileentry->next){
+                logline = NULL;
+                switch(fileentry->file->type){
+                   case F_DUMPFILE:
+                       logline = log_genstring(L_SUCCESS, "taper",
+                                      "%s %s %s %d [faked log entry]",
+                                      fileentry->file->name,
+                                      fileentry->file->disk,
+                                      fileentry->file->datestamp,
+                                      fileentry->file->dumplevel);
+                   break;
+               case F_SPLIT_DUMPFILE:
+                   logline = log_genstring(L_CHUNK, "taper", 
+                                      "%s %s %s %d %d [faked log entry]",
+                                      fileentry->file->name,
+                                      fileentry->file->disk,
+                                      fileentry->file->datestamp,
+                                      fileentry->file->partnum,
+                                      fileentry->file->dumplevel);
+                   break;
+               default:
+                   break;
+                }
+                if(logline){
+                   fprintf(logstream, logline);
+                   amfree(logline);
+                   fflush(logstream);
+                }
+            }
+       }
+       fprintf(stderr, "%s: Search of %s complete\n",
+                       get_pname(), tape_seen->label);
+       if(desired_tape) desired_tape = desired_tape->next;
+
+       /* only restore a single dump, if piping to stdout */
+       if(!headers_equal(&prev_rst_file, &file, 1) &&
+         flags->pipe_to_fd == fileno(stdout)) break;
+    }
+
+    while(seentapes != NULL) {
+       struct seentapes *tape_seen = seentapes;
+       seentapes = seentapes->next;
+       while(tape_seen->files != NULL) {
+           dumplist_t *temp_dump = tape_seen->files;
+           tape_seen->files = temp_dump->next;
+           amfree(temp_dump->file);
+           amfree(temp_dump);
+       }
+       amfree(tape_seen->label);
+       amfree(tape_seen->slotstr);
+       amfree(tape_seen);
+       
+    }
+
+    if(logstream && logstream != stderr && logstream != stdout){
+       fclose(logstream);
+    }
+    if(flags->delay_assemble || flags->inline_assemble){
+       flush_open_outputs(1, NULL);
+    }
+    else flush_open_outputs(0, NULL);
+}
+
+/*
+ * Create a new, clean set of restore flags with some sane default values.
+ */
+rst_flags_t *new_rst_flags()
+{
+    rst_flags_t *flags = alloc(sizeof(rst_flags_t));
+
+    memset(flags, 0, sizeof(rst_flags_t));
+
+    flags->fsf = 1;
+    flags->comp_type = COMPRESS_FAST_OPT;
+    flags->inline_assemble = 1;
+    flags->pipe_to_fd = -1;
+    flags->check_labels = 1;
+
+    return(flags);
+}
+
+/*
+ * Make sure the set of restore options given is sane.  Print errors for
+ * things that're odd, and return -1 for fatal errors.
+ */
+int check_rst_flags(rst_flags_t *flags)
+{
+    int ret = 0;       
+    
+    if(!flags) return(-1);
+
+    if(flags->compress && flags->leave_comp){
+       fprintf(stderr, "Cannot specify 'compress output' and 'leave compression alone' together\n");
+       ret = -1;
+    }
+
+    if(flags->restore_dir != NULL){
+       struct stat statinfo;
+
+       if(flags->pipe_to_fd != -1){
+           fprintf(stderr, "Specifying output directory and piping output are mutually exclusive\n");
+           ret = -1;
+       }
+       if(stat(flags->restore_dir, &statinfo) < 0){
+           fprintf(stderr, "Cannot stat restore target dir '%s': %s\n",
+                     flags->restore_dir, strerror(errno));
+           ret = -1;
+       }
+       if((statinfo.st_mode & S_IFMT) != S_IFDIR){
+           fprintf(stderr, "'%s' is not a directory\n", flags->restore_dir);
+           ret = -1;
+       }
+    }
+
+    if((flags->pipe_to_fd != -1 || flags->compress) &&
+           (flags->delay_assemble || !flags->inline_assemble)){
+       fprintf(stderr, "Split dumps *must* be automatically reassembled when piping output or compressing/uncompressing\n");
+       ret = -1;
+    }
+
+    if(flags->delay_assemble && flags->inline_assemble){
+       fprintf(stderr, "Inline split assembling and delayed assembling are mutually exclusive\n");
+       ret = -1;
+    }
+
+    return(ret);
+}
+
+/*
+ * Clean up after a rst_flags_t
+ */
+void free_rst_flags(flags)
+rst_flags_t *flags;
+{
+    if(!flags) return;
+
+    if(flags->restore_dir) amfree(flags->restore_dir);
+    if(flags->alt_tapedev) amfree(flags->alt_tapedev);
+    if(flags->inventory_log) amfree(flags->inventory_log);
+
+    amfree(flags);
+}
+
+
+/*
+ * Clean up after a match_list_t
+ */
+void free_match_list(match_list)
+match_list_t *match_list;
+{
+    match_list_t *me;
+    match_list_t *prev = NULL;
+  
+    for(me = match_list; me; me = me->next){
+       /* XXX freeing these is broken? can't work out why */
+/*     if(me->hostname) amfree(me->hostname);
+       if(me->diskname) amfree(me->diskname);
+       if(me->datestamp) amfree(me->datestamp);
+       if(me->level) amfree(me->level); */
+       if(prev) amfree(prev);
+       prev = me;
+    }
+    if(prev) amfree(prev);
+}
diff --git a/restore-src/restore.h b/restore-src/restore.h
new file mode 100644 (file)
index 0000000..2dc32ca
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1998 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: restore.h,v 1.5 2006/03/14 13:12:01 martinea Exp $
+ *
+ * 
+ */
+
+#ifndef RESTORE_H
+#define RESTORE_H
+
+#include "fileheader.h"
+#include "tapelist.h"
+#include "amfeatures.h"
+
+#define CREAT_MODE  0640
+
+typedef struct match_list_s {
+    char *hostname;
+    char *diskname;
+    char *datestamp;
+    char *level;
+    struct match_list_s *next;
+} match_list_t;
+
+typedef struct rst_flags_s {
+    unsigned int inline_assemble:1;
+    unsigned int delay_assemble:1;
+    unsigned int compress:1;
+    unsigned int leave_comp:1;
+    unsigned int raw:1;
+    unsigned int headers:1;
+    unsigned int isafile:1;
+    unsigned int wait_tape_prompt:1; /* for interactive console use */
+    unsigned int amidxtaped:1; /* for client-daemon use */
+    unsigned int check_labels:1;
+    unsigned int mask_splits:1;
+    unsigned int fsf;
+    long blocksize;
+    int pipe_to_fd;
+    char *restore_dir;
+    char *comp_type;
+    char *alt_tapedev;
+    char *inventory_log;
+} rst_flags_t;
+
+char *make_filename P((dumpfile_t *file));
+int disk_match P((dumpfile_t *file, char *datestamp,
+                   char *hostname, char *diskname, char *level));
+void read_file_header P((dumpfile_t *file, int tapefd, int isafile,
+                        rst_flags_t *flags));
+ssize_t restore P((dumpfile_t *file, char *filename, int tapefd, int isafile,
+                       rst_flags_t *flags));
+void flush_open_outputs P((int reassemble, dumpfile_t *only_file));
+void search_tapes P((FILE *prompt_out, int use_changer, tapelist_t *tapelist,
+                        match_list_t *restorethese, rst_flags_t *flags, 
+                       am_feature_t *their_features));
+int have_all_parts P((dumpfile_t *file, int upto));
+rst_flags_t *new_rst_flags P((void));
+int check_rst_flags P((rst_flags_t *flags));
+void free_rst_flags P((rst_flags_t *flags));
+void free_match_list P((match_list_t *match_list));
+int lock_logfile P(());
+
+#endif /* RESTORE_H */
+
index 84c9b06c3a77d4fe50c8a2bb21e1294eded8b5cd..e3c46c4c21700c1e6450a1813c576721f40a9dfb 100644 (file)
@@ -1,13 +1,9 @@
 # Makefile for Amanda server programs.
 
-###
-# Yes, I really mean ../common-src.  The genversion.h file ends up getting
-# built there rather than into the source tree.
-###
-
-INCLUDES =             -I$(top_srcdir)/common-src \
-                       -I../common-src \
-                       -I$(top_srcdir)/tape-src
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/restore-src  \
+               -I$(top_srcdir)/tape-src
 
 lib_LTLIBRARIES =      libamserver.la
 LIB_EXTENSION = la
@@ -18,16 +14,19 @@ sbin_PROGRAMS =             amadmin         amcheck         amflush         \
 
 libexec_PROGRAMS =     amindexd        amlogroll       amtrmidx        \
                        amtrmlog        driver          dumper          \
-                       planner         taper           amcleanupdisk
+                       planner         taper           amcleanupdisk   \
+                       chunker
 
 sbin_SCRIPTS =         amcheckdb       amcleanup       amdump          \
                        amoverview      amrmtape        amtoc           \
-                       amverify        amverifyrun     amstatus
+                       amverify        amverifyrun     amstatus        \
+                       amcrypt         amaespipe
 
 libamserver_la_SOURCES=        amindex.c       changer.c                       \
                        conffile.c      diskfile.c      driverio.c      \
                        holding.c       infofile.c      logfile.c       \
-                       tapefile.c      find.c          server_util.c
+                       tapefile.c      find.c          server_util.c   \
+                        taperscan.c
 
 libamserver_la_LDFLAGS= -release $(VERSION)
 
@@ -41,6 +40,8 @@ libamserver_la_LDFLAGS= -release $(VERSION)
 LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 
 SUFFIXES =             .sh .pl
@@ -57,11 +58,9 @@ SUFFIXES =           .sh .pl
 # there are used for testing only:
 TEST_PROGS = diskfile conffile infofile
 
-EXTRA_PROGRAMS = $(TEST_PROGS)
-
-EXTRA_DIST = dumper-krb4.c
+EXTRA_PROGRAMS =       $(TEST_PROGS)
 
-CLEANFILES = *.test.c
+CLEANFILES = *.test.c $(sbin_SCRIPTS)
 
 amindexd_SOURCES =     amindexd.c                                      \
                        disk_history.c                  disk_history.h  \
@@ -74,7 +73,8 @@ amgetconf_SOURCES =   getconf.c
 noinst_HEADERS =       amindex.h       changer.h                       \
                        conffile.h      diskfile.h      driverio.h      \
                        holding.h       infofile.h      logfile.h       \
-                       tapefile.h      find.h          server_util.h
+                       tapefile.h      find.h          server_util.h   \
+                       taperscan.h
 
 install-exec-hook:
        @list="$(sbin_PROGRAMS) $(sbin_SCRIPTS)"; \
@@ -104,6 +104,7 @@ install-exec-hook:
                else true; \
                fi; \
        done
+if !WANT_SSH_SECURITY
        @list="dumper planner"; \
        for p in $$list; do \
                if echo "$(libexec_PROGRAMS)" | grep $$p >/dev/null 2>&1; then \
@@ -115,6 +116,7 @@ install-exec-hook:
                else true; \
                fi; \
        done
+endif
 
 diskfile_SOURCES = diskfile.test.c
 conffile_SOURCES = conffile.test.c
index f0cffa0d7ea10a8cfb52faa6243f9ba2cd283bba..39a971870fa5c1fb839acf2ff53e8618f3903374 100644 (file)
 
 # Makefile for Amanda server programs.
 
-###
-# Yes, I really mean ../common-src.  The genversion.h file ends up getting
-# built there rather than into the source tree.
-###
-
 
 
 
-SOURCES = $(libamserver_la_SOURCES) amadmin.c amcheck.c amcleanupdisk.c amflush.c $(amgetconf_SOURCES) $(amindexd_SOURCES) amlabel.c amlogroll.c $(amreport_SOURCES) amtape.c amtrmidx.c amtrmlog.c $(conffile_SOURCES) $(diskfile_SOURCES) driver.c dumper.c $(infofile_SOURCES) planner.c taper.c
+SOURCES = $(libamserver_la_SOURCES) amadmin.c amcheck.c amcleanupdisk.c amflush.c $(amgetconf_SOURCES) $(amindexd_SOURCES) amlabel.c amlogroll.c $(amreport_SOURCES) amtape.c amtrmidx.c amtrmlog.c chunker.c $(conffile_SOURCES) $(diskfile_SOURCES) driver.c dumper.c $(infofile_SOURCES) planner.c taper.c
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -55,12 +50,13 @@ sbin_PROGRAMS = amadmin$(EXEEXT) amcheck$(EXEEXT) amflush$(EXEEXT) \
 libexec_PROGRAMS = amindexd$(EXEEXT) amlogroll$(EXEEXT) \
        amtrmidx$(EXEEXT) amtrmlog$(EXEEXT) driver$(EXEEXT) \
        dumper$(EXEEXT) planner$(EXEEXT) taper$(EXEEXT) \
-       amcleanupdisk$(EXEEXT)
+       amcleanupdisk$(EXEEXT) chunker$(EXEEXT)
 EXTRA_PROGRAMS = $(am__EXEEXT_1)
 subdir = server-src
 DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
-       $(srcdir)/Makefile.in $(srcdir)/amcheckdb.sh.in \
-       $(srcdir)/amcleanup.sh.in $(srcdir)/amdump.sh.in \
+       $(srcdir)/Makefile.in $(srcdir)/amaespipe.sh.in \
+       $(srcdir)/amcheckdb.sh.in $(srcdir)/amcleanup.sh.in \
+       $(srcdir)/amcrypt.sh.in $(srcdir)/amdump.sh.in \
        $(srcdir)/amfreetapes.sh.in $(srcdir)/amoverview.pl.in \
        $(srcdir)/amrmtape.sh.in $(srcdir)/amstatus.pl.in \
        $(srcdir)/amtoc.pl.in $(srcdir)/amverify.sh.in \
@@ -74,7 +70,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/config/config.h
 CONFIG_CLEAN_FILES = amcheckdb.sh amcleanup.sh amdump.sh \
        amfreetapes.sh amoverview.pl amrmtape.sh amtoc.pl amverify.sh \
-       amstatus.pl amverifyrun.sh
+       amstatus.pl amverifyrun.sh amcrypt.sh amaespipe.sh
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -88,7 +84,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
 libamserver_la_LIBADD =
 am_libamserver_la_OBJECTS = amindex.lo changer.lo conffile.lo \
        diskfile.lo driverio.lo holding.lo infofile.lo logfile.lo \
-       tapefile.lo find.lo server_util.lo
+       tapefile.lo find.lo server_util.lo taperscan.lo
 libamserver_la_OBJECTS = $(am_libamserver_la_OBJECTS)
 am__EXEEXT_1 = diskfile$(EXEEXT) conffile$(EXEEXT) infofile$(EXEEXT)
 libexecPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
@@ -100,6 +96,8 @@ amadmin_LDADD = $(LDADD)
 amadmin_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amcheck_SOURCES = amcheck.c
 amcheck_OBJECTS = amcheck.$(OBJEXT)
@@ -107,6 +105,8 @@ amcheck_LDADD = $(LDADD)
 amcheck_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amcleanupdisk_SOURCES = amcleanupdisk.c
 amcleanupdisk_OBJECTS = amcleanupdisk.$(OBJEXT)
@@ -114,6 +114,8 @@ amcleanupdisk_LDADD = $(LDADD)
 amcleanupdisk_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amflush_SOURCES = amflush.c
 amflush_OBJECTS = amflush.$(OBJEXT)
@@ -121,6 +123,8 @@ amflush_LDADD = $(LDADD)
 amflush_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_amgetconf_OBJECTS = getconf.$(OBJEXT)
 amgetconf_OBJECTS = $(am_amgetconf_OBJECTS)
@@ -128,6 +132,8 @@ amgetconf_LDADD = $(LDADD)
 amgetconf_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_amindexd_OBJECTS = amindexd.$(OBJEXT) disk_history.$(OBJEXT) \
        list_dir.$(OBJEXT)
@@ -136,6 +142,8 @@ amindexd_LDADD = $(LDADD)
 amindexd_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amlabel_SOURCES = amlabel.c
 amlabel_OBJECTS = amlabel.$(OBJEXT)
@@ -143,6 +151,8 @@ amlabel_LDADD = $(LDADD)
 amlabel_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amlogroll_SOURCES = amlogroll.c
 amlogroll_OBJECTS = amlogroll.$(OBJEXT)
@@ -150,6 +160,8 @@ amlogroll_LDADD = $(LDADD)
 amlogroll_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_amreport_OBJECTS = reporter.$(OBJEXT)
 amreport_OBJECTS = $(am_amreport_OBJECTS)
@@ -157,6 +169,8 @@ amreport_LDADD = $(LDADD)
 amreport_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amtape_SOURCES = amtape.c
 amtape_OBJECTS = amtape.$(OBJEXT)
@@ -164,6 +178,8 @@ amtape_LDADD = $(LDADD)
 amtape_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amtrmidx_SOURCES = amtrmidx.c
 amtrmidx_OBJECTS = amtrmidx.$(OBJEXT)
@@ -171,6 +187,8 @@ amtrmidx_LDADD = $(LDADD)
 amtrmidx_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 amtrmlog_SOURCES = amtrmlog.c
 amtrmlog_OBJECTS = amtrmlog.$(OBJEXT)
@@ -178,6 +196,17 @@ amtrmlog_LDADD = $(LDADD)
 amtrmlog_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION)
+chunker_SOURCES = chunker.c
+chunker_OBJECTS = chunker.$(OBJEXT)
+chunker_LDADD = $(LDADD)
+chunker_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
+       libamserver.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_conffile_OBJECTS = conffile.test.$(OBJEXT)
 conffile_OBJECTS = $(am_conffile_OBJECTS)
@@ -185,6 +214,8 @@ conffile_LDADD = $(LDADD)
 conffile_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_diskfile_OBJECTS = diskfile.test.$(OBJEXT)
 diskfile_OBJECTS = $(am_diskfile_OBJECTS)
@@ -192,6 +223,8 @@ diskfile_LDADD = $(LDADD)
 diskfile_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 driver_SOURCES = driver.c
 driver_OBJECTS = driver.$(OBJEXT)
@@ -199,6 +232,8 @@ driver_LDADD = $(LDADD)
 driver_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 dumper_SOURCES = dumper.c
 dumper_OBJECTS = dumper.$(OBJEXT)
@@ -206,6 +241,8 @@ dumper_LDADD = $(LDADD)
 dumper_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 am_infofile_OBJECTS = infofile.test.$(OBJEXT)
 infofile_OBJECTS = $(am_infofile_OBJECTS)
@@ -213,6 +250,8 @@ infofile_LDADD = $(LDADD)
 infofile_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 planner_SOURCES = planner.c
 planner_OBJECTS = planner.$(OBJEXT)
@@ -220,6 +259,8 @@ planner_LDADD = $(LDADD)
 planner_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 taper_SOURCES = taper.c
 taper_OBJECTS = taper.$(OBJEXT)
@@ -227,6 +268,8 @@ taper_LDADD = $(LDADD)
 taper_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 sbinSCRIPT_INSTALL = $(INSTALL_SCRIPT)
 SCRIPTS = $(sbin_SCRIPTS)
@@ -244,13 +287,13 @@ LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 SOURCES = $(libamserver_la_SOURCES) amadmin.c amcheck.c \
        amcleanupdisk.c amflush.c $(amgetconf_SOURCES) \
        $(amindexd_SOURCES) amlabel.c amlogroll.c $(amreport_SOURCES) \
-       amtape.c amtrmidx.c amtrmlog.c $(conffile_SOURCES) \
+       amtape.c amtrmidx.c amtrmlog.c chunker.c $(conffile_SOURCES) \
        $(diskfile_SOURCES) driver.c dumper.c $(infofile_SOURCES) \
        planner.c taper.c
 DIST_SOURCES = $(libamserver_la_SOURCES) amadmin.c amcheck.c \
        amcleanupdisk.c amflush.c $(amgetconf_SOURCES) \
        $(amindexd_SOURCES) amlabel.c amlogroll.c $(amreport_SOURCES) \
-       amtape.c amtrmidx.c amtrmlog.c $(conffile_SOURCES) \
+       amtape.c amtrmidx.c amtrmlog.c chunker.c $(conffile_SOURCES) \
        $(diskfile_SOURCES) driver.c dumper.c $(infofile_SOURCES) \
        planner.c taper.c
 HEADERS = $(noinst_HEADERS)
@@ -304,7 +347,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -316,9 +361,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -331,6 +379,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -393,10 +442,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -447,20 +499,23 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-INCLUDES = -I$(top_srcdir)/common-src \
-                       -I../common-src \
-                       -I$(top_srcdir)/tape-src
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src   \
+               -I$(top_srcdir)/restore-src  \
+               -I$(top_srcdir)/tape-src
 
 lib_LTLIBRARIES = libamserver.la
 LIB_EXTENSION = la
 sbin_SCRIPTS = amcheckdb       amcleanup       amdump          \
                        amoverview      amrmtape        amtoc           \
-                       amverify        amverifyrun     amstatus
+                       amverify        amverifyrun     amstatus        \
+                       amcrypt         amaespipe
 
 libamserver_la_SOURCES = amindex.c     changer.c                       \
                        conffile.c      diskfile.c      driverio.c      \
                        holding.c       infofile.c      logfile.c       \
-                       tapefile.c      find.c          server_util.c
+                       tapefile.c      find.c          server_util.c   \
+                        taperscan.c
 
 libamserver_la_LDFLAGS = -release $(VERSION)
 
@@ -473,14 +528,15 @@ libamserver_la_LDFLAGS = -release $(VERSION)
 LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
        libamserver.$(LIB_EXTENSION) \
        ../tape-src/libamtape.$(LIB_EXTENSION) \
+       ../common-src/libamanda.$(LIB_EXTENSION) \
+       ../tape-src/libamtape.$(LIB_EXTENSION) \
        ../common-src/libamanda.$(LIB_EXTENSION)
 
 SUFFIXES = .sh .pl
 
 # there are used for testing only:
 TEST_PROGS = diskfile conffile infofile
-EXTRA_DIST = dumper-krb4.c
-CLEANFILES = *.test.c
+CLEANFILES = *.test.c $(sbin_SCRIPTS)
 amindexd_SOURCES = amindexd.c                                  \
                        disk_history.c                  disk_history.h  \
                        list_dir.c                      list_dir.h
@@ -490,7 +546,8 @@ amgetconf_SOURCES = getconf.c
 noinst_HEADERS = amindex.h     changer.h                       \
                        conffile.h      diskfile.h      driverio.h      \
                        holding.h       infofile.h      logfile.h       \
-                       tapefile.h      find.h          server_util.h
+                       tapefile.h      find.h          server_util.h   \
+                       taperscan.h
 
 diskfile_SOURCES = diskfile.test.c
 conffile_SOURCES = conffile.test.c
@@ -548,6 +605,10 @@ amstatus.pl: $(top_builddir)/config.status $(srcdir)/amstatus.pl.in
        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 amverifyrun.sh: $(top_builddir)/config.status $(srcdir)/amverifyrun.sh.in
        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+amcrypt.sh: $(top_builddir)/config.status $(srcdir)/amcrypt.sh.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+amaespipe.sh: $(top_builddir)/config.status $(srcdir)/amaespipe.sh.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
        @$(NORMAL_INSTALL)
        test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@@ -669,6 +730,9 @@ amtrmidx$(EXEEXT): $(amtrmidx_OBJECTS) $(amtrmidx_DEPENDENCIES)
 amtrmlog$(EXEEXT): $(amtrmlog_OBJECTS) $(amtrmlog_DEPENDENCIES) 
        @rm -f amtrmlog$(EXEEXT)
        $(LINK) $(amtrmlog_LDFLAGS) $(amtrmlog_OBJECTS) $(amtrmlog_LDADD) $(LIBS)
+chunker$(EXEEXT): $(chunker_OBJECTS) $(chunker_DEPENDENCIES) 
+       @rm -f chunker$(EXEEXT)
+       $(LINK) $(chunker_LDFLAGS) $(chunker_OBJECTS) $(chunker_LDADD) $(LIBS)
 conffile$(EXEEXT): $(conffile_OBJECTS) $(conffile_DEPENDENCIES) 
        @rm -f conffile$(EXEEXT)
        $(LINK) $(conffile_LDFLAGS) $(conffile_OBJECTS) $(conffile_LDADD) $(LIBS)
@@ -728,6 +792,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amtrmidx.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amtrmlog.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/changer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunker.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conffile.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conffile.test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk_history.Po@am__quote@
@@ -748,6 +813,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapefile.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/taper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/taperscan.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@@ -997,17 +1063,17 @@ install-exec-hook:
                else true; \
                fi; \
        done
-       @list="dumper planner"; \
-       for p in $$list; do \
-               if echo "$(libexec_PROGRAMS)" | grep $$p >/dev/null 2>&1; then \
-                       pa=$(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
-                       echo chown root $$pa; \
-                       chown root $$pa; \
-                       echo chmod u+s,o-rwx $$pa; \
-                       chmod u+s,o-rwx $$pa; \
-               else true; \
-               fi; \
-       done
+@WANT_SSH_SECURITY_FALSE@      @list="dumper planner"; \
+@WANT_SSH_SECURITY_FALSE@      for p in $$list; do \
+@WANT_SSH_SECURITY_FALSE@              if echo "$(libexec_PROGRAMS)" | grep $$p >/dev/null 2>&1; then \
+@WANT_SSH_SECURITY_FALSE@                      pa=$(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
+@WANT_SSH_SECURITY_FALSE@                      echo chown root $$pa; \
+@WANT_SSH_SECURITY_FALSE@                      chown root $$pa; \
+@WANT_SSH_SECURITY_FALSE@                      echo chmod u+s,o-rwx $$pa; \
+@WANT_SSH_SECURITY_FALSE@                      chmod u+s,o-rwx $$pa; \
+@WANT_SSH_SECURITY_FALSE@              else true; \
+@WANT_SSH_SECURITY_FALSE@              fi; \
+@WANT_SSH_SECURITY_FALSE@      done
 
 %.test.c: $(srcdir)/%.c
        echo '#define TEST' >$@
index 1309cf5314aecdc12ef933ff15fabec20fb9d6cb..51ebb93375e58817802f6c73f2fad3a140433a7f 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: amadmin.c,v 1.49.2.13.2.3.2.15.2.12 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amadmin.c,v 1.105 2006/02/03 17:29:28 vectro Exp $
  *
  * controlling process for the Amanda backup system
  */
@@ -39,7 +39,7 @@
 #include "holding.h"
 #include "find.h"
 
-disklist_t *diskqp;
+disklist_t diskq;
 
 int main P((int argc, char **argv));
 void usage P((void));
@@ -64,7 +64,7 @@ void delete P((int argc, char **argv));
 void delete_one P((disk_t *dp));
 void balance P((int argc, char **argv));
 void tape P((int argc, char **argv));
-void bumpsize P((void));
+void bumpsize P((int argc, char **argv));
 void diskloop P((int argc, char **argv, char *cmdname,
                 void (*func) P((disk_t *dp))));
 char *seqdatestr P((int seq));
@@ -74,27 +74,76 @@ void export_db P((int argc, char **argv));
 void import_db P((int argc, char **argv));
 void disklist P((int argc, char **argv));
 void disklist_one P((disk_t *dp));
+void show_version P((int argc, char **argv));
 static void check_dumpuser P((void));
 
 static char *conf_tapelist = NULL;
 static char *displayunit;
 static long int unitdivisor;
 
+static const struct {
+    const char *name;
+    void (*fn) P((int, char **));
+    const char *usage;
+} cmdtab[] = {
+    { "version", show_version,
+       "\t\t\t\t# Show version info." },
+    { "force", force,
+       " [<hostname> [<disks>]* ]+\t# Force level 0 at next run." },
+    { "unforce", unforce,
+       " [<hostname> [<disks>]* ]+\t# Clear force command." },
+    { "force-bump", force_bump,
+       " [<hostname> [<disks>]* ]+\t# Force bump at next run." },
+    { "force-no-bump", force_no_bump,
+       " [<hostname> [<disks>]* ]+\t# Force no-bump at next run." },
+    { "unforce-bump", unforce_bump,
+       " [<hostname> [<disks>]* ]+\t# Clear bump command." },
+    { "reuse", reuse,
+       " <tapelabel> ...\t\t# re-use this tape." },
+    { "no-reuse", noreuse,
+       " <tapelabel> ...\t# never re-use this tape." },
+    { "find", find,
+       " [<hostname> [<disks>]* ]*\t# Show which tapes these dumps are on." },
+    { "delete", delete,
+       " [<hostname> [<disks>]* ]+\t# Delete from database." },
+    { "info", info,
+       " [<hostname> [<disks>]* ]*\t# Show current info records." },
+    { "due", due,
+       " [<hostname> [<disks>]* ]*\t# Show due date." },
+    { "balance", balance,
+       " [-days <num>]\t\t# Show nightly dump size balance." },
+    { "tape", tape,
+       " [-days <num>]\t\t\t# Show which tape is due next." },
+    { "bumpsize", bumpsize,
+       "\t\t\t# Show current bump thresholds." },
+    { "export", export_db,
+       " [<hostname> [<disks>]* ]*\t# Export curinfo database to stdout." },
+    { "import", import_db,
+       "\t\t\t\t# Import curinfo database from stdin." },
+    { "disklist", disklist,
+       " [<hostname> [<disks>]* ]*\t# Debug disklist entries." },
+};
+#define        NCMDS   (sizeof(cmdtab) / sizeof(cmdtab[0]))
+
 int main(argc, argv)
-int argc;
-char **argv;
+     int argc;
+     char **argv;
 {
-    unsigned long malloc_hist_1, malloc_size_1;
-    unsigned long malloc_hist_2, malloc_size_2;
+    int i;
     char *conf_diskfile;
     char *conf_infofile;
     char *conffile;
+    unsigned long malloc_hist_1, malloc_size_1;
+    unsigned long malloc_hist_2, malloc_size_2;
 
     safe_fd(-1, 0);
     safe_cd();
 
     set_pname("amadmin");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     erroutput_type = ERR_INTERACTIVE;
@@ -102,15 +151,16 @@ char **argv;
     if(argc < 3) usage();
 
     if(strcmp(argv[2],"version") == 0) {
-       for(argc=0; version_info[argc]; printf("%s",version_info[argc++]));
-       return 0;
+       show_version(argc, argv);
+       goto done;
     }
+
     config_name = argv[1];
     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
     conffile = stralloc2(config_dir, CONFFILE_NAME);
-    if(read_conffile(conffile)) {
+
+    if(read_conffile(conffile))
        error("errors processing config file \"%s\"", conffile);
-    }
     amfree(conffile);
 
     check_dumpuser();
@@ -121,59 +171,49 @@ char **argv;
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((diskqp = read_diskfile(conf_diskfile)) == NULL) {
+    if (read_diskfile(conf_diskfile, &diskq) < 0)
        error("could not load disklist \"%s\"", conf_diskfile);
-    }
     amfree(conf_diskfile);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
     } else {
        conf_tapelist = stralloc2(config_dir, conf_tapelist);
     }
-    if(read_tapelist(conf_tapelist)) {
+    if(read_tapelist(conf_tapelist))
        error("could not load tapelist \"%s\"", conf_tapelist);
-    }
+
     conf_infofile = getconf_str(CNF_INFOFILE);
     if (*conf_infofile == '/') {
        conf_infofile = stralloc(conf_infofile);
     } else {
        conf_infofile = stralloc2(config_dir, conf_infofile);
     }
-    if(open_infofile(conf_infofile)) {
+    if(open_infofile(conf_infofile))
        error("could not open info db \"%s\"", conf_infofile);
-    }
     amfree(conf_infofile);
 
     displayunit = getconf_str(CNF_DISPLAYUNIT);
     unitdivisor = getconf_unit_divisor();
 
-    if(strcmp(argv[2],"force-bump") == 0) force_bump(argc, argv);
-    else if(strcmp(argv[2],"force-no-bump") == 0) force_no_bump(argc, argv);
-    else if(strcmp(argv[2],"unforce-bump") == 0) unforce_bump(argc, argv);
-    else if(strcmp(argv[2],"force") == 0) force(argc, argv);
-    else if(strcmp(argv[2],"unforce") == 0) unforce(argc, argv);
-    else if(strcmp(argv[2],"reuse") == 0) reuse(argc, argv);
-    else if(strcmp(argv[2],"no-reuse") == 0) noreuse(argc, argv);
-    else if(strcmp(argv[2],"info") == 0) info(argc, argv);
-    else if(strcmp(argv[2],"due") == 0) due(argc, argv);
-    else if(strcmp(argv[2],"find") == 0) find(argc, argv);
-    else if(strcmp(argv[2],"delete") == 0) delete(argc, argv);
-    else if(strcmp(argv[2],"balance") == 0) balance(argc, argv);
-    else if(strcmp(argv[2],"tape") == 0) tape(argc, argv);
-    else if(strcmp(argv[2],"bumpsize") == 0) bumpsize();
-    else if(strcmp(argv[2],"import") == 0) import_db(argc, argv);
-    else if(strcmp(argv[2],"export") == 0) export_db(argc, argv);
-    else if(strcmp(argv[2],"disklist") == 0) disklist(argc, argv);
-    else {
+    for (i = 0; i < NCMDS; i++)
+       if (strcmp(argv[2], cmdtab[i].name) == 0) {
+           (*cmdtab[i].fn)(argc, argv);
+           break;
+       }
+    if (i == NCMDS) {
        fprintf(stderr, "%s: unknown command \"%s\"\n", argv[0], argv[2]);
        usage();
     }
+
     close_infofile();
     clear_tapelist();
     amfree(conf_tapelist);
     amfree(config_dir);
 
+done:
+
     malloc_size_2 = malloc_inuse(&malloc_hist_2);
 
     if(malloc_size_1 != malloc_size_2) {
@@ -186,45 +226,13 @@ char **argv;
 
 void usage P((void))
 {
+    int i;
+
     fprintf(stderr, "\nUsage: %s%s <conf> <command> {<args>} ...\n",
            get_pname(), versionsuffix());
     fprintf(stderr, "    Valid <command>s are:\n");
-    fprintf(stderr,"\tversion\t\t\t\t# Show version info.\n");
-    fprintf(stderr,
-           "\tforce [<hostname> [<disks>]* ]+\t# Force level 0 at next run.\n");
-    fprintf(stderr,
-           "\tunforce [<hostname> [<disks>]* ]+\t# Clear force command.\n");
-    fprintf(stderr,
-           "\tforce-bump [<hostname> [<disks>]* ]+\t# Force bump at next run.\n");
-    fprintf(stderr,
-           "\tforce-no-bump [<hostname> [<disks>]* ]+\t# Force no-bump at next run.\n");
-    fprintf(stderr,
-           "\tunforce-bump [<hostname> [<disks>]* ]+\t# Clear bump command.\n");
-    fprintf(stderr,
-           "\treuse <tapelabel> ...\t\t# re-use this tape.\n");
-    fprintf(stderr,
-           "\tno-reuse <tapelabel> ...\t# never re-use this tape.\n");
-    fprintf(stderr,
-           "\tfind [<hostname> [<disks>]* ]*\t# Show which tapes these dumps are on.\n");
-    fprintf(stderr,
-           "\tdelete [<hostname> [<disks>]* ]*\t# Delete from database.\n");
-    fprintf(stderr,
-           "\tinfo [<hostname> [<disks>]* ]*\t# Show current info records.\n");
-    fprintf(stderr,
-           "\tdue [<hostname> [<disks>]* ]*\t# Show due date.\n");
-    fprintf(stderr,
-           "\tbalance [-days <num>]\t\t# Show nightly dump size balance.\n");
-    fprintf(stderr,
-           "\ttape [-days <num>]\t\t# Show which tape is due next.\n");
-    fprintf(stderr,
-           "\tbumpsize\t\t\t# Show current bump thresholds.\n");
-    fprintf(stderr,
-           "\texport [<hostname> [<disks>]* ]*\t# Export curinfo database to stdout.\n");
-    fprintf(stderr,
-           "\timport\t\t\t\t# Import curinfo database from stdin.\n");
-    fprintf(stderr,
-           "\tdisklist [<hostname> [<disks>]* ]*\t# Show disklist entries.\n");
-
+    for (i = 0; i < NCMDS; i++)
+       fprintf(stderr, "\t%s%s\n", cmdtab[i].name, cmdtab[i].usage);
     exit(1);
 }
 
@@ -244,7 +252,7 @@ int seq;
 
     tm = localtime(&t);
 
-    ap_snprintf(str, sizeof(str),
+    snprintf(str, sizeof(str),
                "%2d/%02d %3s", tm->tm_mon+1, tm->tm_mday, dow[tm->tm_wday]);
     return str;
 }
@@ -314,9 +322,9 @@ void (*func) P((disk_t *dp));
        usage();
     }
 
-    match_disklist(diskqp, argc-3, argv+3);
+    match_disklist(&diskq, argc-3, argv+3);
 
-    for(dp = diskqp->head; dp != NULL; dp = dp->next) {
+    for(dp = diskq.head; dp != NULL; dp = dp->next) {
        if(dp->todo) {
            count++;
            func(dp);
@@ -341,9 +349,9 @@ disk_t *dp;
     check_dumpuser();
 #endif
     get_info(hostname, diskname, &info);
-    info.command |= FORCE_FULL;
-    if(info.command & FORCE_BUMP) {
-       info.command ^= FORCE_BUMP;
+    SET(info.command, FORCE_FULL);
+    if (ISSET(info.command, FORCE_BUMP)) {
+       CLR(info.command, FORCE_BUMP);
        printf("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n",
               get_pname(), hostname, diskname);
     }
@@ -376,11 +384,11 @@ disk_t *dp;
     info_t info;
 
     get_info(hostname, diskname, &info);
-    if(info.command & FORCE_FULL) {
+    if (ISSET(info.command, FORCE_FULL)) {
 #if TEXTDB
        check_dumpuser();
 #endif
-       info.command ^= FORCE_FULL;
+       CLR(info.command, FORCE_FULL);
        if(put_info(hostname, diskname, &info) == 0){
            printf("%s: force command for %s:%s cleared.\n",
                   get_pname(), hostname, diskname);
@@ -418,14 +426,14 @@ disk_t *dp;
     check_dumpuser();
 #endif
     get_info(hostname, diskname, &info);
-    info.command |= FORCE_BUMP;
-    if(info.command & FORCE_NO_BUMP) {
-       info.command ^= FORCE_NO_BUMP;
+    SET(info.command, FORCE_BUMP);
+    if (ISSET(info.command, FORCE_NO_BUMP)) {
+       CLR(info.command, FORCE_NO_BUMP);
        printf("%s: WARNING: %s:%s FORCE_NO_BUMP command was cleared.\n",
               get_pname(), hostname, diskname);
     }
-    if (info.command & FORCE_FULL) {
-       info.command ^= FORCE_FULL;
+    if (ISSET(info.command, FORCE_FULL)) {
+       CLR(info.command, FORCE_FULL);
        printf("%s: WARNING: %s:%s FORCE_FULL command was cleared.\n",
               get_pname(), hostname, diskname);
     }
@@ -461,9 +469,9 @@ disk_t *dp;
     check_dumpuser();
 #endif
     get_info(hostname, diskname, &info);
-    info.command |= FORCE_NO_BUMP;
-    if(info.command & FORCE_BUMP) {
-       info.command ^= FORCE_BUMP;
+    SET(info.command, FORCE_NO_BUMP);
+    if (ISSET(info.command, FORCE_BUMP)) {
+       CLR(info.command, FORCE_BUMP);
        printf("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n",
               get_pname(), hostname, diskname);
     }
@@ -496,14 +504,11 @@ disk_t *dp;
     info_t info;
 
     get_info(hostname, diskname, &info);
-    if(info.command & (FORCE_BUMP | FORCE_NO_BUMP)) {
+    if (ISSET(info.command, FORCE_BUMP|FORCE_NO_BUMP)) {
 #if TEXTDB
        check_dumpuser();
 #endif
-       if(info.command & FORCE_BUMP)
-           info.command ^= FORCE_BUMP;
-       if(info.command & FORCE_NO_BUMP)
-           info.command ^= FORCE_NO_BUMP;
+       CLR(info.command, FORCE_BUMP|FORCE_NO_BUMP);
        if(put_info(hostname, diskname, &info) == 0) {
            printf("%s: bump command for %s:%s cleared.\n",
                   get_pname(), hostname, diskname);
@@ -654,11 +659,11 @@ disk_t *dp;
     get_info(dp->host->hostname, dp->name, &info);
 
     printf("\nCurrent info for %s %s:\n", dp->host->hostname, dp->name);
-    if(info.command & FORCE_FULL) 
+    if (ISSET(info.command, FORCE_FULL))
        printf("  (Forcing to level 0 dump at next run)\n");
-    if(info.command & FORCE_BUMP) 
+    if (ISSET(info.command, FORCE_BUMP))
        printf("  (Forcing bump at next run)\n");
-    if(info.command & FORCE_NO_BUMP) 
+    if (ISSET(info.command, FORCE_NO_BUMP))
        printf("  (Forcing no-bump at next run)\n");
     printf("  Stats: dump rates (kps), Full:  %5.1f, %5.1f, %5.1f\n",
           info.full.rate[0], info.full.rate[1], info.full.rate[2]);
@@ -689,7 +694,7 @@ char **argv;
     if(argc >= 4)
        diskloop(argc, argv, "info", info_one);
     else
-       for(dp = diskqp->head; dp != NULL; dp = dp->next)
+       for(dp = diskq.head; dp != NULL; dp = dp->next)
            info_one(dp);
 }
 
@@ -734,7 +739,7 @@ char **argv;
     if(argc >= 4)
        diskloop(argc, argv, "due", due_one);
     else
-       for(dp = diskqp->head; dp != NULL; dp = dp->next)
+       for(dp = diskq.head; dp != NULL; dp = dp->next)
            due_one(dp);
 }
 
@@ -755,6 +760,7 @@ char **argv;
            return;
        }
     }
+
     runtapes = getconf_int(CNF_RUNTAPES);
     tp = lookup_last_reusable_tape(0);
 
@@ -768,7 +774,7 @@ char **argv;
                printf("tape %s or ", tp->label);
            printf("a new tape.\n");
        
-           tp = lookup_last_reusable_tape((j*runtapes) + i + 1);
+           tp = lookup_last_reusable_tape(i + 1);
        }
     }
     lasttp = lookup_tapepos(lookup_nb_tape());
@@ -854,7 +860,7 @@ char **argv;
     for(seq=0; seq <= distinct; seq++)
        sp[seq].disks = sp[seq].origsize = sp[seq].outsize = 0;
 
-    for(dp = diskqp->head; dp != NULL; dp = dp->next) {
+    for(dp = diskq.head; dp != NULL; dp = dp->next) {
        if(get_info(dp->host->hostname, dp->name, &info)) {
            printf("new disk %s:%s ignored.\n", dp->host->hostname, dp->name);
            continue;
@@ -995,7 +1001,7 @@ char **argv;
 
     if(argc < 3) {
        fprintf(stderr,
-               "%s: expecting \"find [--sort <hkdlb>] [hostname [<disk>]]*\"\n",
+               "%s: expecting \"find [--sort <hkdlpb>] [hostname [<disk>]]*\"\n",
                get_pname());
        usage();
     }
@@ -1031,12 +1037,11 @@ char **argv;
     } else {
        start_argc=4;
     }
-    match_disklist(diskqp, argc-(start_argc-1), argv+(start_argc-1));
-    output_find = find_dump(1, diskqp);
-
+    match_disklist(&diskq, argc-(start_argc-1), argv+(start_argc-1));
+    output_find = find_dump(1, &diskq);
     if(argc-(start_argc-1) > 0) {
        free_find_result(&output_find);
-       match_disklist(diskqp, argc-(start_argc-1), argv+(start_argc-1));
+       match_disklist(&diskq, argc-(start_argc-1), argv+(start_argc-1));
        output_find = find_dump(0, NULL);
     }
 
@@ -1063,14 +1068,15 @@ int level;
     return bump;
 }
 
-void bumpsize()
+void bumpsize(argc, argv)
+int argc;
+char **argv;
 {
     int l;
     int conf_bumppercent = getconf_int(CNF_BUMPPERCENT);
     double conf_bumpmult = getconf_real(CNF_BUMPMULT);
 
     printf("Current bump parameters:\n");
-
     if(conf_bumppercent == 0) {
        printf("  bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n",
               getconf_int(CNF_BUMPSIZE));
@@ -1080,9 +1086,8 @@ void bumpsize()
               conf_bumpmult);
 
        printf("      Bump -> To  Threshold\n");
-       for(l = 1; l < 9; l++) {
+       for(l = 1; l < 9; l++)
            printf("\t%d  ->  %d  %9d KB\n", l, l+1, bump_thresh(l));
-       }
        putchar('\n');
     }
     else {
@@ -1094,7 +1099,6 @@ void bumpsize()
               getconf_int(CNF_BUMPDAYS));
        printf("  bumpmult %5.5g\t- threshold = disk_size * bumppercent * bumpmult**(level-1)\n\n",
               conf_bumpmult);
-
        printf("      Bump -> To  Threshold\n");
        for(l = 1; l < 9; l++) {
            printf("\t%d  ->  %d  %7.2f %%\n", l, l+1, bumppercent);
@@ -1121,26 +1125,23 @@ char **argv;
     printf("CURINFO Version %s CONF %s\n", version(), getconf_str(CNF_ORG));
 
     curtime = time(0);
-    if(gethostname(hostname, sizeof(hostname)-1) == -1) {
-       error("could not determine host name: %s", strerror(errno));
-    }
+    if(gethostname(hostname, sizeof(hostname)-1) == -1)
+       error("could not determine host name: %s\n", strerror(errno));
     hostname[sizeof(hostname)-1] = '\0';
     printf("# Generated by:\n#    host: %s\n#    date: %s",
           hostname, ctime(&curtime));
 
     printf("#    command:");
-    for(i = 0; i < argc; i++) {
+    for(i = 0; i < argc; i++)
        printf(" %s", argv[i]);
-    }
 
     printf("\n# This file can be merged back in with \"amadmin import\".\n");
     printf("# Edit only with care.\n");
 
-    if(argc >= 4) {
+    if(argc >= 4)
        diskloop(argc, argv, "export", export_one);
-    } else for(dp = diskqp->head; dp != NULL; dp = dp->next) {
+    else for(dp = diskq.head; dp != NULL; dp = dp->next)
        export_one(dp);
-    }
 }
 
 void export_one(dp)
@@ -1592,6 +1593,8 @@ disk_t *dp;
     am_host_t *hp;
     interface_t *ip;
     sle_t *excl;
+    time_t st;
+    struct tm *stm;
 
     hp = dp->host;
     ip = hp->netif;
@@ -1707,20 +1710,40 @@ disk_t *dp;
               dp->comprate[0], dp->comprate[1]);
     }
 
-    printf("        auth ");
-    switch(dp->auth) {
-    case AUTH_BSD:
-       printf("BSD\n");
+    printf("        encrypt ");
+    switch(dp->encrypt) {
+    case ENCRYPT_NONE:
+       printf("NONE\n");
        break;
-    case AUTH_KRB4:
-       printf("KRB4\n");
+    case ENCRYPT_CUST:
+       printf("CLIENT\n");
+       break;
+    case ENCRYPT_SERV_CUST:
+       printf("SERVER\n");
        break;
     }
-    printf("        kencrypt %s\n", (dp->kencrypt? "YES" : "NO"));
 
+    printf("        auth %s\n", dp->security_driver);
+    printf("        kencrypt %s\n", (dp->kencrypt? "YES" : "NO"));
     printf("        holdingdisk %s\n", (!dp->no_hold? "YES" : "NO"));
     printf("        record %s\n", (dp->record? "YES" : "NO"));
     printf("        index %s\n", (dp->index? "YES" : "NO"));
+    st = dp->start_t;
+        if(st) {
+            stm = localtime(&st);
+            printf("        starttime %d:%02d:%02d\n",
+              stm->tm_hour, stm->tm_min, stm->tm_sec);
+        }
+   
+    if(dp->tape_splitsize > 0) {
+       printf("        tape_splitsize %ld\n", dp->tape_splitsize);
+    }
+    if(dp->split_diskbuffer) {
+       printf("        split_diskbuffer %s\n", dp->split_diskbuffer);
+    }
+    if(dp->fallback_splitsize > 0) {
+       printf("        fallback_splitsize %ldMb\n", (dp->fallback_splitsize / 1024));
+    }
     printf("        skip-incr %s\n", (dp->skip_incr? "YES" : "NO"));
     printf("        skip-full %s\n", (dp->skip_full? "YES" : "NO"));
 
@@ -1736,6 +1759,16 @@ char **argv;
     if(argc >= 4)
        diskloop(argc, argv, "disklist", disklist_one);
     else
-       for(dp = diskqp->head; dp != NULL; dp = dp->next)
+       for(dp = diskq.head; dp != NULL; dp = dp->next)
            disklist_one(dp);
 }
+
+void show_version(argc, argv)
+int argc;
+char **argv;
+{
+    int i;
+
+    for(i = 0; version_info[i] != NULL; i++)
+       printf("%s", version_info[i]);
+}
diff --git a/server-src/amaespipe.sh.in b/server-src/amaespipe.sh.in
new file mode 100755 (executable)
index 0000000..dd1b5c7
--- /dev/null
@@ -0,0 +1,85 @@
+#! /bin/sh
+#
+# Copyright (c) 2005 Zmanda Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+# 
+# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
+# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
+#
+
+
+# wrapper script to use aespipe
+# based on bz2aespipe distributed by aespipe from 
+# http://loop-aes.sourceforge.net/
+# FILE FORMAT
+# 10 bytes: constant string 'bz2aespipe'
+# 10 bytes: itercountk digits
+# 1 byte: '0' = AES128, '1' = AES192, '2' = AES256
+# 1 byte: '0' = SHA256, '1' = SHA384, '2' = SHA512, '3' = RMD160
+# 24 bytes: random seed string
+# remaining bytes are aespipe encrypted
+
+# These definitions are only used when encrypting.
+# Decryption will autodetect these definitions from archive.
+ENCRYPTION=AES256
+HASHFUNC=SHA256
+ITERCOUNTK=100
+WAITSECONDS=1
+AMANDA_HOME=~@CLIENT_LOGIN@
+GPGKEY="$AMANDA_HOME/.gnupg/am_key.gpg"
+FDNUMBER=3
+
+PATH=/usr/bin:/usr/local/bin:/sbin:/usr/sbin
+export PATH
+
+if test x$1 = x-d ; then
+    # decrypt
+    n=`head -c 10 - | tr -d -c 0-9a-zA-Z`
+    if test x${n} != xbz2aespipe ; then
+        echo "bz2aespipe: wrong magic - aborted" >/dev/tty
+        exit 1
+    fi
+    itercountk=`head -c 10 - | tr -d -c 0-9`
+    if test x${itercountk} = x ; then itercountk=0; fi
+    n=`head -c 1 - | tr -d -c 0-9`
+    encryption=AES128
+    if test x${n} = x1 ; then encryption=AES192; fi
+    if test x${n} = x2 ; then encryption=AES256; fi
+    n=`head -c 1 - | tr -d -c 0-9`
+    hashfunc=SHA256
+    if test x${n} = x1 ; then hashfunc=SHA384; fi
+    if test x${n} = x2 ; then hashfunc=SHA512; fi
+    if test x${n} = x3 ; then hashfunc=RMD160; fi
+    seedstr=`head -c 24 - | tr -d -c 0-9a-zA-Z+/`
+    aespipe -K ${GPGKEY} -p ${FDNUMBER} -e ${encryption} -H ${hashfunc} -S ${seedstr} -C ${itercountk} -d
+else
+    # encrypt
+    echo -n bz2aespipe
+    echo ${ITERCOUNTK} | awk '{printf "%10u", $1;}'
+    n=`echo ${ENCRYPTION} | tr -d -c 0-9`
+    aesstr=0
+    if test x${n} = x192 ; then aesstr=1; fi
+    if test x${n} = x256 ; then aesstr=2; fi
+    n=`echo ${HASHFUNC} | tr -d -c 0-9`
+    hashstr=0
+    if test x${n} = x384 ; then hashstr=1; fi
+    if test x${n} = x512 ; then hashstr=2; fi
+    if test x${n} = x160 ; then hashstr=3; fi
+    seedstr=`head -c 18 /dev/urandom | uuencode -m - | head -n 2 | tail -n 1`
+    echo -n ${aesstr}${hashstr}${seedstr}
+    aespipe -K ${GPGKEY} -p ${FDNUMBER} -e ${ENCRYPTION} -H ${HASHFUNC} -S ${seedstr} -C ${ITERCOUNTK} -w ${WAITSECONDS}
+fi
+exit 0
index 79f2d308447bde3dc1fe9a2323668376159ce693..36ab3d957e10cfdfdb009495ae6c001b477c5fab 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amcheck.c,v 1.50.2.19.2.7.2.20.2.12 2005/10/11 14:50:00 martinea Exp $
+ * $Id: amcheck.c,v 1.121 2006/02/06 22:17:09 ktill Exp $
  *
  * checks for common problems in server and clients
  */
 #include "amanda.h"
+#include "util.h"
 #include "conffile.h"
 #include "statfs.h"
 #include "diskfile.h"
 #include "tapefile.h"
 #include "tapeio.h"
 #include "changer.h"
+#include "packet.h"
+#include "security.h"
 #include "protocol.h"
 #include "clock.h"
 #include "version.h"
 #include "amindex.h"
 #include "token.h"
-#include "util.h"
+#include "taperscan.h"
+#include "server_util.h"
 #include "pipespawn.h"
 #include "amfeatures.h"
 
-/*
- * If we don't have the new-style wait access functions, use our own,
- * compatible with old-style BSD systems at least.  Note that we don't
- * care about the case w_stopval == WSTOPPED since we don't ask to see
- * stopped processes, so should never get them from wait.
- */
-#ifndef WEXITSTATUS
-#   define WEXITSTATUS(r)       (((union wait *) &(r))->w_retcode)
-#   define WTERMSIG(r)          (((union wait *) &(r))->w_termsig)
-
-#   undef WIFSIGNALED
-#   define WIFSIGNALED(r)        (((union wait *) &(r))->w_termsig != 0)
-#endif
-
 #define BUFFER_SIZE    32768
 
 static int conf_ctimeout;
 static int overwrite;
-dgram_t *msg = NULL;
 
-static disklist_t *origqp;
+static disklist_t origq;
 
 static uid_t uid_dumpuser;
 
@@ -74,9 +63,6 @@ void usage P((void));
 int start_client_checks P((int fd));
 int start_server_check P((int fd, int do_localchk, int do_tapechk));
 int main P((int argc, char **argv));
-int scan_init P((int rc, int ns, int bk));
-int taperscan_slot P((int rc, char *slotstr, char *device));
-char *taper_scan P((void));
 int test_server_pgm P((FILE *outf, char *dir, char *pgm,
                       int suid, uid_t dumpuid));
 
@@ -104,11 +90,10 @@ char **argv;
     int do_clientchk, clientchk_pid, client_probs;
     int do_localchk, do_tapechk, serverchk_pid, server_probs;
     int chk_flag;
-    int opt, size, result_port, tempfd, mainfd;
+    int opt, size, tempfd, mainfd;
     amwait_t retstat;
     pid_t pid;
     extern int optind;
-    int l, n, s;
     char *mailto = NULL;
     extern char *optarg;
     int mailout;
@@ -124,28 +109,23 @@ char **argv;
     safe_cd();
 
     set_pname("amcheck");
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     dbopen();
 
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
-    ap_snprintf(pid_str, sizeof(pid_str), "%ld", (long)getpid());
+    snprintf(pid_str, sizeof(pid_str), "%ld", (long)getpid());
 
     erroutput_type = ERR_INTERACTIVE;
 
     our_features = am_init_feature_set();
     our_feature_string = am_feature_to_string(our_features);
 
-    /* set up dgram port first thing */
-
-    msg = dgram_alloc();
-
-    if(dgram_bind(msg, &result_port) == -1)
-       error("could not bind result datagram port: %s", strerror(errno));
-
     if(geteuid() == 0) {
-       /* set both real and effective uid's to real uid, likewise for gid */
-       setgid(getgid());
-       setuid(getuid());
+       seteuid(getuid());
     }
     uid_me = getuid();
 
@@ -214,17 +194,19 @@ char **argv;
        error("errors processing config file \"%s\"", conffile);
     }
     amfree(conffile);
+
     conf_ctimeout = getconf_int(CNF_CTIMEOUT);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((origqp = read_diskfile(conf_diskfile)) == NULL) {
+    if(read_diskfile(conf_diskfile, &origq) < 0) {
        error("could not load disklist %s", conf_diskfile);
     }
-    match_disklist(origqp, argc-1, argv+1);
+    match_disklist(&origq, argc-1, argv+1);
     amfree(conf_diskfile);
 
     /*
@@ -278,11 +260,10 @@ char **argv;
 
     /* start server side checks */
 
-    if(do_localchk || do_tapechk) {
+    if(do_localchk || do_tapechk)
        serverchk_pid = start_server_check(mainfd, do_localchk, do_tapechk);
-    } else {
+    else
        serverchk_pid = 0;
-    }
 
     /* start client side checks */
 
@@ -308,18 +289,14 @@ char **argv;
            char number[NUM_STR_SIZE];
            char *wait_msg = NULL;
 
-           ap_snprintf(number, sizeof(number), "%ld", (long)pid);
+           snprintf(number, sizeof(number), "%ld", (long)pid);
            wait_msg = vstralloc("parent: reaped bogus pid ", number, "\n",
                                 NULL);
-           for(l = 0, n = strlen(wait_msg); l < n; l += s) {
-               if((s = write(mainfd, wait_msg + l, n - l)) < 0) {
-                   error("write main file: %s", strerror(errno));
-               }
-           }
+           if (fullwrite(mainfd, wait_msg, strlen(wait_msg)) < 0)
+               error("write main file: %s", strerror(errno));
            amfree(wait_msg);
        }
     }
-    amfree(msg);
 
     /* copy temp output to main output and write tagline */
 
@@ -327,12 +304,9 @@ char **argv;
        if(lseek(tempfd, 0, 0) == -1)
            error("seek temp file: %s", strerror(errno));
 
-       while((size=read(tempfd, buffer, sizeof(buffer))) > 0) {
-           for(l = 0; l < size; l += s) {
-               if((s = write(mainfd, buffer + l, size - l)) < 0) {
-                   error("write main file: %s", strerror(errno));
-               }
-           }
+       while((size=fullread(tempfd, buffer, sizeof(buffer))) > 0) {
+           if (fullwrite(mainfd, buffer, size) < 0)
+               error("write main file: %s", strerror(errno));
        }
        if(size < 0)
            error("read temp file: %s", strerror(errno));
@@ -342,11 +316,8 @@ char **argv;
     version_string = vstralloc("\n",
                               "(brought to you by Amanda ", version(), ")\n",
                               NULL);
-    for(l = 0, n = strlen(version_string); l < n; l += s) {
-       if((s = write(mainfd, version_string + l, n - l)) < 0) {
-           error("write main file: %s", strerror(errno));
-       }
-    }
+    if (fullwrite(mainfd, version_string, strlen(version_string)) < 0)
+       error("write main file: %s", strerror(errno));
     amfree(version_string);
     amfree(config_dir);
     amfree(config_name);
@@ -410,8 +381,8 @@ char **argv;
            a[1] = mailto;
            a[2] = NULL;
        } else {
-           n = split(getconf_str(CNF_MAILTO), a, MAILTO_LIMIT, " ");
-           a[n + 1] = NULL;
+           r = split(getconf_str(CNF_MAILTO), a, MAILTO_LIMIT, " ");
+           a[r + 1] = NULL;
        }
        if((nullfd = open("/dev/null", O_RDWR)) < 0) {
            error("nullfd: /dev/null: %s", strerror(errno));
@@ -467,7 +438,7 @@ char **argv;
                    } else {
                        strappend(err, "returned ");
                    }
-                   ap_snprintf(number, sizeof(number), "%d", ret);
+                   snprintf(number, sizeof(number), "%d", ret);
                    strappend(err, number);
            }
        }
@@ -494,127 +465,6 @@ char *searchlabel, *labelstr;
 tape_t *tp;
 FILE *errf;
 
-int scan_init(rc, ns, bk)
-int rc, ns, bk;
-{
-    if(rc)
-       error("could not get changer info: %s", changer_resultstr);
-
-    nslots = ns;
-    backwards = bk;
-
-    return 0;
-}
-
-int taperscan_slot(rc, slotstr, device)
-int rc;
-char *slotstr;
-char *device;
-{
-    char *errstr;
-
-    if(rc == 2) {
-       fprintf(errf, "%s: fatal slot %s: %s\n",
-               get_pname(), slotstr, changer_resultstr);
-       return 1;
-    }
-    else if(rc == 1) {
-       fprintf(errf, "%s: slot %s: %s\n",
-               get_pname(), slotstr, changer_resultstr);
-       return 0;
-    }
-    else {
-       if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
-           fprintf(errf, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
-       } else {
-           /* got an amanda tape */
-           fprintf(errf, "%s: slot %s: date %-8s label %s",
-                   get_pname(), slotstr, datestamp, label);
-           if(searchlabel != NULL
-              && (strcmp(label, FAKE_LABEL) == 0
-                  || strcmp(label, searchlabel) == 0)) {
-               /* it's the one we are looking for, stop here */
-               fprintf(errf, " (exact label match)\n");
-               found_device = newstralloc(found_device, device);
-               found = 1;
-               return 1;
-           }
-           else if(!match(labelstr, label))
-               fprintf(errf, " (no match)\n");
-           else {
-               /* not an exact label match, but a labelstr match */
-               /* check against tape list */
-               tp = lookup_tapelabel(label);
-               if(tp == NULL)
-                   fprintf(errf, " (Not in tapelist)\n");
-               else if(!reusable_tape(tp))
-                   fprintf(errf, " (active tape)\n");
-               else if(got_match == 0 && tp->datestamp == 0) {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(errf, " (new tape)\n");
-                   found = 3;
-                   found_device = newstralloc(found_device, device);
-                   return 1;
-               }
-               else if(got_match)
-                   fprintf(errf, " (labelstr match)\n");
-               else {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(errf, " (first labelstr match)\n");
-                   if(!backwards || !searchlabel) {
-                       found = 2;
-                       found_device = newstralloc(found_device, device);
-                       return 1;
-                   }
-               }
-           }
-       }
-    }
-    return 0;
-}
-
-char *taper_scan()
-{
-    char *outslot = NULL;
-
-    if((tp = lookup_last_reusable_tape(0)) == NULL)
-       searchlabel = NULL;
-    else
-       searchlabel = tp->label;
-
-    found = 0;
-    got_match = 0;
-
-    changer_find(scan_init, taperscan_slot, searchlabel);
-
-    if(found == 2 || found == 3)
-       searchlabel = first_match_label;
-    else if(!found && got_match) {
-       searchlabel = first_match_label;
-       amfree(found_device);
-       if(changer_loadslot(first_match, &outslot, &found_device) == 0) {
-           found = 1;
-       }
-    } else if(!found) {
-       if(searchlabel) {
-           changer_resultstr = newvstralloc(changer_resultstr,
-                                            "label ", searchlabel,
-                                            " or new tape not found in rack",
-                                            NULL);
-       } else {
-           changer_resultstr = newstralloc(changer_resultstr,
-                                           "new tape not found in rack");
-       }
-    }
-    amfree(outslot);
-
-    return found ? found_device : NULL;
-}
-
 int test_server_pgm(outf, dir, pgm, suid, dumpuid)
 FILE *outf;
 char *dir;
@@ -652,15 +502,15 @@ int start_server_check(fd, do_localchk, do_tapechk)
     int fd;
     int do_localchk, do_tapechk;
 {
-    char *errstr, *tapename;
+    char *tapename;
     generic_fs_stats_t fs;
-    tape_t *tp;
     FILE *outf;
     holdingdisk_t *hdp;
     int pid;
     int confbad = 0, tapebad = 0, disklow = 0, logbad = 0;
     int userbad = 0, infobad = 0, indexbad = 0, pgmbad = 0;
     int testtape = do_tapechk;
+    tapetype_t *tp = NULL;
 
     switch(pid = fork()) {
     case -1: error("could not fork server check: %s", strerror(errno));
@@ -674,8 +524,6 @@ int start_server_check(fd, do_localchk, do_tapechk)
 
     set_pname("amcheck-server");
 
-    amfree(msg);
-
     startclock();
 
     if((outf = fdopen(fd, "w")) == NULL)
@@ -685,13 +533,16 @@ int start_server_check(fd, do_localchk, do_tapechk)
     fprintf(outf, "Amanda Tape Server Host Check\n");
     fprintf(outf, "-----------------------------\n");
 
+    if (do_localchk || testtape) {
+        tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
+    }
+
     /*
      * Check various server side config file settings.
      */
     if(do_localchk) {
        char *ColumnSpec;
        char *errstr = NULL;
-       tapetype_t *tp;
        char *lbl_templ;
 
        ColumnSpec = getconf_str(CNF_COLUMNSPEC);
@@ -700,7 +551,6 @@ int start_server_check(fd, do_localchk, do_tapechk)
            amfree(errstr);
            confbad = 1;
        }
-       tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
        lbl_templ = tp->lbl_templ;
        if(strcmp(lbl_templ, "") != 0) {
            if(strchr(lbl_templ, '/') == NULL) {
@@ -726,6 +576,10 @@ int start_server_check(fd, do_localchk, do_tapechk)
      * Look up the programs used on the server side.
      */
     if(do_localchk) {
+       int suid_check=1;
+#ifdef SSH_SECURITY
+       suid_check=0;
+#endif 
        if(access(libexecdir, X_OK) == -1) {
            fprintf(outf, "ERROR: program dir %s: not accessible\n",
                    libexecdir);
@@ -733,10 +587,10 @@ int start_server_check(fd, do_localchk, do_tapechk)
        } else {
            pgmbad = pgmbad \
                     || test_server_pgm(outf, libexecdir, "planner",
-                                       1, uid_dumpuser);
+                                       suid_check, uid_dumpuser);
            pgmbad = pgmbad \
                     || test_server_pgm(outf, libexecdir, "dumper",
-                                       1, uid_dumpuser);
+                                       suid_check, uid_dumpuser);
            pgmbad = pgmbad \
                     || test_server_pgm(outf, libexecdir, "driver",
                                        0, uid_dumpuser);
@@ -814,6 +668,10 @@ int start_server_check(fd, do_localchk, do_tapechk)
                    tapefile, strerror(errno));
            tapebad = 1;
        }
+       else if(!S_ISREG(statbuf.st_mode)) {
+           fprintf(outf, "ERROR: tapefile %s: should be a regular file.\n", tapefile);
+           tapebad = 1;
+       }
        else if(access(tapefile, F_OK) != 0) {
            fprintf(outf, "ERROR: can't access tape list %s\n", tapefile);
            tapebad = 1;
@@ -952,6 +810,8 @@ int start_server_check(fd, do_localchk, do_tapechk)
 
     if (testtape) {
        /* check that the tape is a valid amanda tape */
+        char *error_msg;
+        int tape_status;
 
        tapedays = getconf_int(CNF_TAPECYCLE);
        labelstr = getconf_str(CNF_LABELSTR);
@@ -962,56 +822,49 @@ int start_server_check(fd, do_localchk, do_tapechk)
                    "WARNING: if a tape changer is not available, runtapes must be set to 1\n");
        }
 
-       if(changer_init() && (tapename = taper_scan()) == NULL) {
-           fprintf(outf, "ERROR: %s\n", changer_resultstr);
-           tapebad = 1;
-       } else if(tape_access(tapename,F_OK|R_OK|W_OK) == -1) {
-           fprintf(outf, "ERROR: %s: %s\n", tapename, strerror(errno));
-           tapebad = 1;
-       } else if((errstr = tape_rdlabel(tapename, &datestamp, &label)) != NULL) {
-           fprintf(outf, "ERROR: %s: %s\n", tapename, errstr);
-           tapebad = 1;
-       } else if(strcmp(label, FAKE_LABEL) != 0) {
-           if(!match(labelstr, label)) {
-               fprintf(outf, "ERROR: label %s doesn't match labelstr \"%s\"\n",
-                       label, labelstr);
-               tapebad = 1;
-           }
-           else {
-               tp = lookup_tapelabel(label);
-               if(tp == NULL) {
-                   fprintf(outf, "ERROR: label %s match labelstr but it not listed in the tapelist file.\n", label);
-                   tapebad = 1;
-               }
-               else if(tp != NULL && !reusable_tape(tp)) {
-                   fprintf(outf, "ERROR: cannot overwrite active tape %s\n",
-                           label);
-                   tapebad = 1;
-               }
-           }
-
-       }
-
-       if(tapebad) {
+        tape_status = taper_scan(NULL, &label, &datestamp, &error_msg,
+                                 &tapename);
+        fprintf(outf, "%s\n", error_msg);
+        amfree(error_msg);
+        if (tape_status < 0) {
            tape_t *exptape = lookup_last_reusable_tape(0);
            fprintf(outf, "       (expecting ");
            if(exptape != NULL) fprintf(outf, "tape %s or ", exptape->label);
            fprintf(outf, "a new tape)\n");
-       }
-
-       if(!tapebad && overwrite) {
-           if((errstr = tape_writable(tapename)) != NULL) {
-               fprintf(outf,
-                       "ERROR: tape %s label ok, but is not writable\n",
-                       label);
-               tapebad = 1;
-           }
-           else fprintf(outf, "Tape %s is writable\n", label);
-       }
-       else fprintf(outf, "NOTE: skipping tape-writable test\n");
-
-       if(!tapebad)
-           fprintf(outf, "Tape %s label ok\n", label);
+       } else {
+            if (overwrite) {
+                char *wrlabel_status;
+                wrlabel_status = tape_wrlabel(tapename, "X", label,
+                                              tp->blocksize * 1024);
+                if (wrlabel_status != NULL) {
+                    if (tape_status == 3) {
+                        fprintf(outf,
+                                "ERROR: Could not label brand new tape: %s\n",
+                                wrlabel_status);
+                    } else {
+                        fprintf(outf,
+                                "ERROR: tape %s label ok, but is not writable (%s)\n",
+                                label, wrlabel_status);
+                    }
+                    tapebad = 1;
+                } else {
+                    if (tape_status != 3) {
+                        fprintf(outf, "Tape %s is writable; rewrote label.\n", label);
+                    } else {
+                        fprintf(outf, "Wrote label %s to brand new tape.\n", label);
+                    }
+                }
+            } else {
+                fprintf(outf, "NOTE: skipping tape-writable test\n");
+                if (tape_status == 3) {
+                    fprintf(outf,
+                            "Found a brand new tape, will label it %s.\n", 
+                            label);
+                } else {
+                    fprintf(outf, "Tape %s label ok\n", label);
+                }                    
+            }
+        }
     } else if (do_tapechk) {
        fprintf(outf, "WARNING: skipping tape test because amdump or amflush seem to be running\n");
        fprintf(outf, "WARNING: if they are not, you must run amcleanup\n");
@@ -1048,18 +901,20 @@ int start_server_check(fd, do_localchk, do_tapechk)
                        conf_tapecycle, conf_runspercycle);
        }
 
-       conf_infofile = stralloc(getconf_str(CNF_INFOFILE));
-       if (*conf_infofile != '/') {
-           char *ci = stralloc2(config_dir, conf_infofile);
-           amfree(conf_infofile);
-           conf_infofile = ci;
+       conf_infofile = getconf_str(CNF_INFOFILE);
+       if (*conf_infofile == '/') {
+           conf_infofile = stralloc(conf_infofile);
+       } else {
+           conf_infofile = stralloc2(config_dir, conf_infofile);
        }
-       conf_indexdir = stralloc(getconf_str(CNF_INDEXDIR));
-       if (*conf_indexdir != '/') {
-           char *ci = stralloc2(config_dir, conf_indexdir);
-           amfree(conf_indexdir);
-           conf_indexdir = ci;
+
+       conf_indexdir = getconf_str(CNF_INDEXDIR);
+       if (*conf_indexdir == '/') {
+           conf_indexdir = stralloc(conf_indexdir);
+       } else {
+           conf_indexdir = stralloc2(config_dir, conf_indexdir);
        }
+
 #if TEXTDB
        if(stat(conf_infofile, &statbuf) == -1) {
            fprintf(outf, "NOTE: info dir %s: does not exist\n", conf_infofile);
@@ -1077,8 +932,9 @@ int start_server_check(fd, do_localchk, do_tapechk)
            strappend(conf_infofile, "/");
        }
 #endif
-       while(!empty(*origqp)) {
-           hostp = origqp->head->host;
+
+       while(!empty(origq)) {
+           hostp = origq.head->host;
            host = sanitise_filename(hostp->hostname);
 #if TEXTDB
            if(conf_infofile) {
@@ -1200,8 +1056,24 @@ int start_server_check(fd, do_localchk, do_tapechk)
                        }
                    }
                }
+
+               if ( dp->encrypt == ENCRYPT_SERV_CUST && dp->srv_encrypt ) {
+                 if(access(dp->srv_encrypt, X_OK) == -1) {
+                   fprintf(outf, "ERROR: %s is not executable, server encryption will not work\n",
+                           dp->srv_encrypt );
+                   pgmbad = 1;
+                 }
+               }
+               if ( dp->compress == COMP_SERV_CUST && dp->srvcompprog ) {
+                 if(access(dp->srvcompprog, X_OK) == -1) {
+                   fprintf(outf, "ERROR: %s is not executable, server custom compression will not work\n",
+                           dp->srvcompprog );
+                   pgmbad = 1;
+                 }
+               }
+
                amfree(disk);
-               remove_disk(origqp, dp);
+               remove_disk(&origq, dp);
            }
            amfree(host);
            amfree(hostindexdir);
@@ -1244,13 +1116,8 @@ int start_server_check(fd, do_localchk, do_tapechk)
 
 int remote_errors;
 FILE *outf;
-int amanda_port;
 
-#ifdef KRB4_SECURITY
-int kamanda_port;
-#endif
-
-static void handle_response P((proto_t *p, pkt_t *pkt));
+static void handle_result P((void *, pkt_t *, security_handle_t *));
 
 #define HOST_READY                             ((void *)0)     /* must be 0 */
 #define HOST_ACTIVE                            ((void *)1)
@@ -1260,22 +1127,22 @@ static void handle_response P((proto_t *p, pkt_t *pkt));
 #define DISK_ACTIVE                            ((void *)1)
 #define DISK_DONE                              ((void *)2)
 
-int start_host(hostp)
+void start_host(hostp)
     am_host_t *hostp;
 {
     disk_t *dp;
     char *req = NULL;
     int req_len = 0;
-    int rc;
     int disk_count;
+    const security_driver_t *secdrv;
     char number[NUM_STR_SIZE];
 
     if(hostp->up != HOST_READY) {
-       return 0;
+       return;
     }
 
     if (strncmp (hostp->hostname,"localhost",9) == 0) {
-        fprintf(outf,
+       fprintf(outf,
                     "WARNING: Usage of fully qualified hostname recommended for Client %s.\n",
                     hostp->hostname);
     }
@@ -1331,7 +1198,7 @@ int start_host(hostp)
                   hostp->hostname);
        }
 
-       ap_snprintf(number, sizeof(number), "%d", hostp->maxdumps);
+       snprintf(number, sizeof(number), "%d", hostp->maxdumps);
        req = vstralloc("SERVICE ", "selfcheck", "\n",
                        "OPTIONS ",
                        has_features ? "features=" : "",
@@ -1347,17 +1214,15 @@ int start_host(hostp)
                        NULL);
 
        req_len = strlen(req);
-       req_len += 128;                         /* room for SECURITY ... */
-       req_len += 256;                         /* room for non-disk answers */
+       req_len += 128;                         /* room for SECURITY ... */
+       req_len += 256;                         /* room for non-disk answers */
        for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
            char *l;
            int l_len;
            char *o;
            char* calcsize;
 
-           if(dp->todo == 0) continue;
-
-           if(dp->up != DISK_READY) {
+           if(dp->up != DISK_READY || dp->todo != 1) {
                continue;
            }
            o = optionstr(dp, hostp->features, outf);
@@ -1379,43 +1244,91 @@ int start_host(hostp)
                     hostp->hostname, dp->name, dp->device);
                }
            }
-           if(strcmp(dp->program, "DUMP") == 0 &&
-              !am_has_feature(hostp->features, fe_program_dump)) {
-               fprintf(outf, "ERROR: %s:%s does not support DUMP.\n",
-                       hostp->hostname, dp->name);
-           }
-           if(strcmp(dp->program, "GNUTAR") == 0 &&
-              !am_has_feature(hostp->features, fe_program_gnutar)) {
-               fprintf(outf, "ERROR: %s:%s does not support GNUTAR.\n",
-                       hostp->hostname, dp->name);
-           }
-           if(dp->estimate == ES_CALCSIZE &&
-              !am_has_feature(hostp->features, fe_calcsize_estimate)) {
-               fprintf(outf, "ERROR: %s:%s does not support CALCSIZE for estimate, using CLIENT.\n",
-                       hostp->hostname, dp->name);
-               dp->estimate = ES_CLIENT;
-           }
+           if(strncmp(dp->program,"DUMP",4) == 0 || 
+              strncmp(dp->program,"GNUTAR",6) == 0) {
+               if(strcmp(dp->program, "DUMP") == 0 &&
+                  !am_has_feature(hostp->features, fe_program_dump)) {
+                   fprintf(outf, "ERROR: %s:%s does not support DUMP.\n",
+                           hostp->hostname, dp->name);
+               }
+               if(strcmp(dp->program, "GNUTAR") == 0 &&
+                  !am_has_feature(hostp->features, fe_program_gnutar)) {
+                   fprintf(outf, "ERROR: %s:%s does not support GNUTAR.\n",
+                           hostp->hostname, dp->name);
+               }
+               if(dp->estimate == ES_CALCSIZE &&
+                  !am_has_feature(hostp->features, fe_calcsize_estimate)) {
+                   fprintf(outf, "ERROR: %s:%s does not support CALCSIZE for estimate, using CLIENT.\n",
+                           hostp->hostname, dp->name);
+                   dp->estimate = ES_CLIENT;
+               }
+               if(dp->estimate == ES_CALCSIZE &&
+                  am_has_feature(hostp->features, fe_selfcheck_calcsize))
+                   calcsize = "CALCSIZE ";
+               else
+                   calcsize = "";
 
-           if(dp->estimate == ES_CALCSIZE &&
-              am_has_feature(hostp->features, fe_selfcheck_calcsize))
-               calcsize = "CALCSIZE ";
-           else
-               calcsize = "";
-
-           l = vstralloc(calcsize, 
-                         dp->program, " ",
-                         dp->name, " ",
-                         dp->device ? dp->device : "",
-                         " 0 OPTIONS |",
-                         o,
-                         "\n",
-                         NULL);
+               if(dp->compress == COMP_CUST &&
+                  !am_has_feature(hostp->features, fe_options_compress_cust)) {
+                 fprintf(outf,
+                         "ERROR: Client %s does not support custom compression.\n",
+                         hostp->hostname);
+               }
+               if(dp->encrypt == ENCRYPT_CUST ) {
+                 if ( !am_has_feature(hostp->features, fe_options_encrypt_cust)) {
+                   fprintf(outf,
+                           "ERROR: Client %s does not support data encryption.\n",
+                           hostp->hostname);
+                   remote_errors++;
+                 } else if ( dp->compress == COMP_SERV_FAST || 
+                             dp->compress == COMP_SERV_BEST ||
+                             dp->compress == COMP_SERV_CUST ) {
+                   fprintf(outf,
+                           "ERROR: %s: Client encryption with server compression is not supported. See amanda.conf(5) for detail.\n", hostp->hostname);
+                   remote_errors++;
+                 } 
+               }
+               if(dp->device) {
+                   l = vstralloc(calcsize,
+                                 dp->program, " ",
+                                 dp->name, " ",
+                                 dp->device,
+                                 " 0 OPTIONS |",
+                                 o,
+                                 "\n",
+                                 NULL);
+               }
+               else {
+                   l = vstralloc(calcsize,
+                                 dp->program, " ",
+                                 dp->name,
+                                 " 0 OPTIONS |",
+                                 o,
+                                 "\n",
+                                 NULL);
+               }
+           } else {
+               if(!am_has_feature(hostp->features, fe_program_dumper_api)) {
+                   fprintf(outf, "ERROR: %s:%s does not support DUMPER-API.\n",
+                           hostp->hostname, dp->name);
+               }
+               l = vstralloc("DUMPER ",
+                             dp->program, 
+                             " ",
+                             dp->name,
+                             " ",
+                             dp->device,
+                             " 0 OPTIONS |",
+                             o,
+                             "\n",
+                             NULL);
+           }
            l_len = strlen(l);
            amfree(o);
            /*
-            * Allow 2X for error response in return packet.
+            * Allow 2X for err response.
             */
-           if(req_len + l_len > MAX_DGRAM / 2) {
+           if(req_len + l_len > MAX_PACKET / 2) {
                amfree(l);
                break;
            }
@@ -1425,7 +1338,6 @@ int start_host(hostp)
            dp->up = DISK_ACTIVE;
            disk_count++;
        }
-
     }
     else { /* noop service */
        req = vstralloc("SERVICE ", "noop", "\n",
@@ -1434,41 +1346,30 @@ int start_host(hostp)
                        "\n",
                        NULL);
        for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
-           if(dp->todo == 0) continue;
-
-           if(dp->up != DISK_READY) {
+           if(dp->up != DISK_READY || dp->todo != 1) {
                continue;
            }
            disk_count++;
        }
     }
+
     if(disk_count == 0) {
        amfree(req);
        hostp->up = HOST_DONE;
-       return 0;
+       return;
     }
 
-#ifdef KRB4_SECURITY
-    if(hostp->disks->auth == AUTH_KRB4)
-       rc = make_krb_request(hostp->hostname, kamanda_port, req,
-                             hostp, conf_ctimeout, handle_response);
-    else
-#endif
-        rc = make_request(hostp->hostname, amanda_port, req,
-                         hostp, conf_ctimeout, handle_response);
+    secdrv = security_getdriver(hostp->disks->security_driver);
+    if (secdrv == NULL) {
+       error("could not find security driver '%s' for host '%s'",
+             hostp->disks->security_driver, hostp->hostname);
+    }
+    protocol_sendreq(hostp->hostname, secdrv, generic_get_security_conf, 
+                    req, conf_ctimeout, handle_result, hostp);
 
-    req = NULL;                                /* do not own this any more */
+    amfree(req);
 
-    if(rc) {
-       /* couldn't resolve hostname */
-       fprintf(outf,
-               "ERROR: %s: could not resolve hostname\n", hostp->hostname);
-       remote_errors++;
-       hostp->up = HOST_DONE;
-    } else {
-       hostp->up = HOST_ACTIVE;
-    }
-    return 1;
+    hostp->up = HOST_ACTIVE;
 }
 
 int start_client_checks(fd)
@@ -1477,7 +1378,6 @@ int fd;
     am_host_t *hostp;
     disk_t *dp;
     int hostcount, pid;
-    struct servent *amandad;
     int userbad = 0;
 
     switch(pid = fork()) {
@@ -1501,39 +1401,20 @@ int fd;
     fprintf(outf, "\nAmanda Backup Client Hosts Check\n");
     fprintf(outf,   "--------------------------------\n");
 
-#ifdef KRB4_SECURITY
-    kerberos_service_init();
-#endif
-
-    proto_init(msg->socket, time(0), 1024);
-
-    /* get remote service port */
-    if((amandad = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL)
-       amanda_port = AMANDA_SERVICE_DEFAULT;
-    else
-       amanda_port = ntohs(amandad->s_port);
-
-#ifdef KRB4_SECURITY
-    if((amandad = getservbyname(KAMANDA_SERVICE_NAME, "udp")) == NULL)
-       kamanda_port = KAMANDA_SERVICE_DEFAULT;
-    else
-       kamanda_port = ntohs(amandad->s_port);
-#endif
+    protocol_init();
 
     hostcount = remote_errors = 0;
 
-    for(dp = origqp->head; dp != NULL; dp = dp->next) {
+    for(dp = origq.head; dp != NULL; dp = dp->next) {
        hostp = dp->host;
        if(hostp->up == HOST_READY) {
-           if(start_host(hostp) == 1) {
-               hostcount++;
-               check_protocol();
-           }
+           start_host(hostp);
+           hostcount++;
+           protocol_check();
        }
     }
 
-    run_protocol();
-    amfree(msg);
+    protocol_run();
 
     fprintf(outf,
      "Client check: %d host%s checked in %s seconds, %d problem%s found\n",
@@ -1556,9 +1437,10 @@ int fd;
     return 0;
 }
 
-static void handle_response(p, pkt)
-proto_t *p;
+static void handle_result(datap, pkt, sech)
+void *datap;
 pkt_t *pkt;
+security_handle_t *sech;
 {
     am_host_t *hostp;
     disk_t *dp;
@@ -1568,39 +1450,21 @@ pkt_t *pkt;
     int ch;
     int tch;
 
-    hostp = (am_host_t *) p->datap;
+    hostp = (am_host_t *)datap;
     hostp->up = HOST_READY;
 
-    if(p->state == S_FAILED && pkt == NULL) {
-       if(p->prevstate == S_REPWAIT) {
-           fprintf(outf,
-                   "WARNING: %s: selfcheck reply timed out.\n",
-                   hostp->hostname);
-       }
-       else {
-           fprintf(outf,
-                   "WARNING: %s: selfcheck request timed out.  Host down?\n",
-                   hostp->hostname);
-       }
-       remote_errors++;
-       hostp->up = HOST_DONE;
-       return;
-    }
-
-#ifdef KRB4_SECURITY
-    if(hostp->disks->auth == AUTH_KRB4 &&
-       !check_mutual_authenticator(host2key(hostp->hostname), pkt, p)) {
-       fprintf(outf, "ERROR: %s [mutual-authentication failed]\n",
-               hostp->hostname);
+    if (pkt == NULL) {
+       fprintf(outf,
+           "WARNING: %s: selfcheck request failed: %s\n", hostp->hostname,
+           security_geterror(sech));
        remote_errors++;
        hostp->up = HOST_DONE;
        return;
     }
-#endif
 
 #if 0
-    fprintf(errf, "got %sresponse from %s:\n----\n%s----\n\n",
-           (p->state == S_FAILED) ? "NAK " : "", hostp->hostname, pkt->body);
+    fprintf(errf, "got response from %s:\n----\n%s----\n\n",
+           hostp->hostname, pkt->body);
 #endif
 
     s = pkt->body;
@@ -1633,13 +1497,13 @@ pkt_t *pkt;
 
 #define sc "OK "
        if(strncmp(line, sc, sizeof(sc)-1) == 0) {
-#undef sc
            continue;
+#undef sc
        }
 
 #define sc "ERROR "
        if(strncmp(line, sc, sizeof(sc)-1) == 0) {
-           t = line + sizeof(sc)-1;
+           t = line + sizeof(sc) - 1;
            tch = t[-1];
 #undef sc
 
@@ -1650,14 +1514,14 @@ pkt_t *pkt;
             * We can ignore this.
             */
            if(hostp->features == NULL
-              && p->state == S_FAILED
+              && pkt->type == P_NAK
               && (strcmp(t - 1, "unknown service: noop") == 0
-                  || strcmp(t - 1, "noop: invalid service") == 0)) {
+                  || strcmp(t - 1, "noop: invalid service") == 0)) {
            } else {
                fprintf(outf, "ERROR: %s%s: %s\n",
-                       (p->state == S_FAILED) ? "NAK " : "",
-                       hostp->hostname,
-                       t - 1);
+                       (pkt->type == P_NAK) ? "NAK " : "",
+                       hostp->hostname,
+                       t - 1);
                remote_errors++;
                hostp->up = HOST_DONE;
            }
index 27d33a701f4331406d38a7270e25931d6e7634fe..e73af4cd94f3c1ecea55880875b478bc48398af8 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amcleanupdisk.c,v 1.1.2.6.4.3.2.2.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amcleanupdisk.c,v 1.16 2006/01/14 04:37:19 paddy_s Exp $
  */
 #include "amanda.h"
 
@@ -50,7 +50,7 @@ char **main_argv;
 {
     struct passwd *pw;
     char *dumpuser;
-    disklist_t *diskqp;
+    disklist_t diskq;
     char *conffile;
     char *conf_diskfile;
     char *conf_infofile;
@@ -60,48 +60,48 @@ char **main_argv;
 
     set_pname("amcleanupdisk");
 
-    if(main_argc != 2) {
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    if(main_argc != 2)
        error("Usage: amcleanupdisk%s <confdir>", versionsuffix());
-    }
 
     config_name = main_argv[1];
 
     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
+
     conffile = stralloc2(config_dir, CONFFILE_NAME);
-    if(read_conffile(conffile)) {
+    if(read_conffile(conffile))
        error("errors processing config file \"%s\"", conffile);
-    }
     amfree(conffile);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((diskqp = read_diskfile(conf_diskfile)) == NULL) {
+    if (read_diskfile(conf_diskfile, &diskq) < 0)
        error("could not load disklist %s", conf_diskfile);
-    }
     amfree(conf_diskfile);
+
     conf_infofile = getconf_str(CNF_INFOFILE);
     if (*conf_infofile == '/') {
        conf_infofile = stralloc(conf_infofile);
     } else {
        conf_infofile = stralloc2(config_dir, conf_infofile);
     }
-    if(open_infofile(conf_infofile)) {
+    if (open_infofile(conf_infofile) < 0)
        error("could not open info db \"%s\"", conf_infofile);
-    }
     amfree(conf_infofile);
 
     datestamp = construct_datestamp(NULL);
 
     dumpuser = getconf_str(CNF_DUMPUSER);
-    if((pw = getpwnam(dumpuser)) == NULL) {
+    if((pw = getpwnam(dumpuser)) == NULL)
        error("dumpuser %s not found in password file", dumpuser);
-    }
-    if(pw->pw_uid != getuid()) {
+    if(pw->pw_uid != getuid())
        error("must run amcleanupdisk as user %s", dumpuser);
-    }
 
     holding_list = pick_all_datestamp(1);
 
diff --git a/server-src/amcrypt.sh.in b/server-src/amcrypt.sh.in
new file mode 100755 (executable)
index 0000000..8b06168
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Original wrapper by Paul Bijnens
+#
+# worked by Stefan G. Weichinger
+# to enable gpg-encrypted dumps via aespipe
+# also worked by Matthieu Lochegnies for server-side encryption
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+AMANDA_HOME=~@CLIENT_LOGIN@
+
+AM_AESPIPE=@sbindir@/amaespipe
+AM_PASSPHRASE=$AMANDA_HOME/.am_passphrase
+PATH=/usr/bin:/usr/local/bin:/sbin:/usr/sbin
+export PATH
+
+AESPIPE=`which aespipe`
+
+if [ $? -ne 0 ] ; then
+       echo "amcrypt: aespipe not found in $PATH" >&2
+        exit 2
+fi
+
+if [ ! -x $AESPIPE ] ; then
+        echo "amcrypt: aespipe it's not executable" >&2
+        exit 2
+fi
+
+if [ ! -x $AM_AESPIPE ] ; then
+        echo "amcrypt: $AM_AESPIPE not found or it's not executable"  >&2
+        exit 2
+fi
+
+$AM_AESPIPE "$@" 3< $AM_PASSPHRASE
+
+rc=$?
+exit $rc
index c8d5a4a428221e588ab6958be46e5e77d88abe4a..1cd9749056612f0d29476a1e2e2a80c303cb137f 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amflush.c,v 1.41.2.13.4.6.2.9.2.3 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amflush.c,v 1.80 2006/01/14 04:37:19 paddy_s Exp $
  *
  * write files from work directory onto tape
  */
@@ -55,7 +55,7 @@ void confirm P((void));
 void redirect_stderr P((void));
 void detach P((void));
 void run_dumps P((void));
-
+static int get_letter_from_user P((void));
 
 int main(main_argc, main_argv)
 int main_argc;
@@ -72,9 +72,10 @@ char **main_argv;
     char *conf_diskfile;
     char *conf_tapelist;
     char *conf_logfile;
-    disklist_t *diskqp;
+    disklist_t diskq;
     disk_t *dp;
-    pid_t pid, driver_pid, reporter_pid;
+    pid_t pid;
+    pid_t driver_pid, reporter_pid;
     amwait_t exitcode;
     int opt;
     dumpfile_t file;
@@ -89,6 +90,7 @@ char **main_argv;
 
     set_pname("amflush");
 
+    /* Don't die when child closes pipe */
     signal(SIGPIPE, SIG_IGN);
 
     erroutput_type = ERR_INTERACTIVE;
@@ -107,7 +109,7 @@ char **main_argv;
        case 's': redirect = 0;
                  break;
        case 'D': if (datearg == NULL)
-                       datearg = alloc(21*sizeof(char *));
+                     datearg = alloc(21*sizeof(char *));
                  if(nb_datearg == 20) {
                      fprintf(stderr,"maximum of 20 -D arguments.\n");
                      exit(1);
@@ -129,33 +131,32 @@ char **main_argv;
     }
 
     config_name = main_argv[0];
-
     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
+
     conffile = stralloc2(config_dir, CONFFILE_NAME);
-    if(read_conffile(conffile)) {
+    if(read_conffile(conffile))
        error("errors processing config file \"%s\"", conffile);
-    }
     amfree(conffile);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((diskqp = read_diskfile(conf_diskfile)) == NULL) {
+    if (read_diskfile(conf_diskfile, &diskq) < 0)
        error("could not read disklist file \"%s\"", conf_diskfile);
-    }
-    match_disklist(diskqp, main_argc-1, main_argv+1);
+    match_disklist(&diskq, main_argc-1, main_argv+1);
     amfree(conf_diskfile);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
     } else {
        conf_tapelist = stralloc2(config_dir, conf_tapelist);
     }
-    if(read_tapelist(conf_tapelist)) {
+    if(read_tapelist(conf_tapelist))
        error("could not load tapelist \"%s\"", conf_tapelist);
-    }
     amfree(conf_tapelist);
 
     datestamp = construct_datestamp(NULL);
@@ -173,13 +174,12 @@ char **main_argv;
        conf_logdir = stralloc2(config_dir, conf_logdir);
     }
     conf_logfile = vstralloc(conf_logdir, "/log", NULL);
-    if (access(conf_logfile, F_OK) == 0) {
+    if (access(conf_logfile, F_OK) == 0)
        error("%s exists: amdump or amflush is already running, or you must run amcleanup", conf_logfile);
-    }
     amfree(conf_logfile);
+
     driver_program = vstralloc(libexecdir, "/", "driver", versionsuffix(),
-                                NULL);
+                              NULL);
     reporter_program = vstralloc(sbindir, "/", "amreport", versionsuffix(),
                                 NULL);
     logroll_program = vstralloc(libexecdir, "/", "amlogroll", versionsuffix(),
@@ -224,7 +224,7 @@ char **main_argv;
 
     if(!batch) confirm();
 
-    for(dp = diskqp->head; dp != NULL; dp = dp->next) {
+    for(dp = diskq.head; dp != NULL; dp = dp->next) {
        if(dp->todo)
            log_add(L_DISK, "%s %s", dp->host->hostname, dp->name);
     }
@@ -325,21 +325,21 @@ char **main_argv;
        /* First, find out the last existing errfile,           */
        /* to avoid ``infinite'' loops if tapecycle is infinite */
 
-       ap_snprintf(number,100,"%d",days);
+       snprintf(number,100,"%d",days);
        errfilex = newvstralloc(errfilex, errfile, ".", number, NULL);
        while ( days < maxdays && stat(errfilex,&stat_buf)==0) {
            days++;
-           ap_snprintf(number,100,"%d",days);
+           snprintf(number,100,"%d",days);
            errfilex = newvstralloc(errfilex, errfile, ".", number, NULL);
        }
-       ap_snprintf(number,100,"%d",days);
+       snprintf(number,100,"%d",days);
        errfilex = newvstralloc(errfilex, errfile, ".", number, NULL);
        nerrfilex = NULL;
        while (days > 1) {
            amfree(nerrfilex);
            nerrfilex = errfilex;
            days--;
-           ap_snprintf(number,100,"%d",days);
+           snprintf(number,100,"%d",days);
            errfilex = vstralloc(errfile, ".", number, NULL);
            if (rename(errfilex, nerrfilex) != 0) {
                error("cannot rename \"%s\" to \"%s\": %s",
@@ -398,10 +398,9 @@ char **main_argv;
 }
 
 
-int get_letter_from_user()
+static int get_letter_from_user()
 {
-    int r = '\0';
-    int ch;
+    int r, ch;
 
     fflush(stdout); fflush(stderr);
     while((ch = getchar()) != EOF && ch != '\n' && isspace(ch)) {}
index 9944b1fc85ed58384003d56bb1c3332b22c396ea..2e763dc44b88225ae38bb16cce821af42cd149d8 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: amindex.c,v 1.10.4.2.4.1 2001/09/01 03:35:17 jrjackson Exp $
+ * $Id: amindex.c,v 1.13 2001/09/01 03:36:24 jrjackson Exp $
  *
  * index control
  */
@@ -58,7 +58,7 @@ int level;
     datebuf[sizeof(datebuf)-1] = '\0';
     dc = datebuf;
 
-    ap_snprintf(level_str, sizeof(level_str), "%d", level);
+    snprintf(level_str, sizeof(level_str), "%d", level);
   }
 
   host = sanitise_filename(host);
index 08145611887763baf8c96344471d7adecdb525e0..e4722a47efd29136a1c1f291969e8f53f6ecee55 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: amindex.h,v 1.5.4.2 1999/09/08 23:27:30 jrj Exp $
+ * $Id: amindex.h,v 1.7 1999/09/15 00:32:27 jrj Exp $
  *
  * headers for index control
  */
index 7ad24e871941771e3da41b7fb987f9457607afc4..f721e2cf97bf18115be7d19b1debe43ce8da1cdb 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amindexd.c,v 1.39.2.11.4.4.2.13.2.3 2005/10/02 13:48:42 martinea Exp $
+ * $Id: amindexd.c,v 1.86 2006/03/09 16:51:41 martinea Exp $
  *
  * This is the server daemon part of the index client/server system.
  * It is assumed that this is launched from inetd instead of being
@@ -45,9 +45,7 @@
 #include "diskfile.h"
 #include "arglist.h"
 #include "clock.h"
-#include "dgram.h"
 #include "version.h"
-#include "protocol.h"
 #include "amindex.h"
 #include "disk_history.h"
 #include "list_dir.h"
@@ -78,7 +76,7 @@ char *remote_hostname = NULL;                 /* the client */
 char *dump_hostname = NULL;                    /* machine we are restoring */
 char *disk_name;                               /* disk we are restoring */
 char *target_date = NULL;
-disklist_t *disk_list;                         /* all disks in cur config */
+disklist_t disk_list;                          /* all disks in cur config */
 find_result_t *output_find = NULL;
 
 static int amindexd_debug = 0;
@@ -89,14 +87,34 @@ static REMOVE_ITEM *uncompress_remove = NULL;
 static am_feature_t *our_features = NULL;
 static am_feature_t *their_features = NULL;
 
-static void reply P((int n, char * fmt, ...))
+static REMOVE_ITEM *remove_files P((REMOVE_ITEM *));
+static char *uncompress_file P((char *, char **));
+static int process_ls_dump P((char *, DUMP_ITEM *, int, char **));
+
+ /* XXX this is a hack to make sure the printf-ish output buffer
+    for lreply and friends is big enough for long label strings.
+    Should go away if someone institutes a more fundamental fix 
+    for that problem. */
+ static int str_buffer_size = STR_SIZE;
+
+static void reply P((int, char *, ...))
     __attribute__ ((format (printf, 2, 3)));
-static void lreply P((int n, char * fmt, ...))
+static void lreply P((int, char *, ...))
     __attribute__ ((format (printf, 2, 3)));
-static void fast_lreply P((int n, char * fmt, ...))
+static void fast_lreply P((int, char *, ...))
     __attribute__ ((format (printf, 2, 3)));
-
-REMOVE_ITEM *remove_files(remove)
+static int is_dump_host_valid P((char *));
+static int is_disk_valid P((char *));
+static int is_config_valid P((char *));
+static int build_disk_table P((void));
+static int disk_history_list P((void));
+static int is_dir_valid_opaque P((char *));
+static int opaque_ls P((char *, int));
+static int tapedev_is P((void));
+static int are_dumps_compressed P((void));
+int main P((int, char **));
+
+static REMOVE_ITEM *remove_files(remove)
 REMOVE_ITEM *remove;
 {
     REMOVE_ITEM *prev;
@@ -113,7 +131,7 @@ REMOVE_ITEM *remove;
     return remove;
 }
 
-char *uncompress_file(filename_gz, emsg)
+static char *uncompress_file(filename_gz, emsg)
 char *filename_gz;
 char **emsg;
 {
@@ -248,11 +266,13 @@ char **emsg;
 printf_arglist_function1(static void reply, int, n, char *, fmt)
 {
     va_list args;
-    char buf[STR_SIZE];
+    char *buf;
+
+    buf = alloc(str_buffer_size);
 
     arglist_start(args, fmt);
-    ap_snprintf(buf, sizeof(buf), "%03d ", n);
-    ap_vsnprintf(buf+4, sizeof(buf)-4, fmt, args);
+    snprintf(buf, str_buffer_size, "%03d ", n);
+    vsnprintf(buf+4, str_buffer_size-4, fmt, args);
     arglist_end(args);
 
     if (printf("%s\r\n", buf) < 0)
@@ -270,18 +290,16 @@ printf_arglist_function1(static void reply, int, n, char *, fmt)
        exit(1);
     }
     dbprintf(("%s: < %s\n", debug_prefix_time(NULL), buf));
+    amfree(buf);
 }
 
-/* send one line of a multi-line response */
-printf_arglist_function1(static void lreply, int, n, char *, fmt)
-{
-    va_list args;
-    char buf[STR_SIZE];
+static void lreply_backend(int flush, int n, char *fmt, va_list args) {
+    char *buf;
 
-    arglist_start(args, fmt);
-    ap_snprintf(buf, sizeof(buf), "%03d-", n);
-    ap_vsnprintf(buf+4, sizeof(buf)-4, fmt, args);
-    arglist_end(args);
+    buf = alloc(str_buffer_size);
+
+    snprintf(buf, str_buffer_size, "%03d-", n);
+    vsnprintf(buf+4, str_buffer_size-4, fmt, args);
 
     if (printf("%s\r\n", buf) < 0)
     {
@@ -290,7 +308,7 @@ printf_arglist_function1(static void lreply, int, n, char *, fmt)
        uncompress_remove = remove_files(uncompress_remove);
        exit(1);
     }
-    if (fflush(stdout) != 0)
+    if (flush && fflush(stdout) != 0)
     {
        dbprintf(("%s: ! error %d (%s) in fflush\n",
                  debug_prefix_time(NULL), errno, strerror(errno)));
@@ -299,26 +317,29 @@ printf_arglist_function1(static void lreply, int, n, char *, fmt)
     }
 
     dbprintf(("%s: < %s\n", debug_prefix_time(NULL), buf));
+    amfree(buf);
+}
+
+/* send one line of a multi-line response */
+printf_arglist_function1(static void lreply, int, n, char *, fmt)
+{
+    va_list args;
+
+    arglist_start(args, fmt);
+    lreply_backend(1, n, fmt, args);
+    arglist_end(args);
+
 }
 
 /* send one line of a multi-line response */
 printf_arglist_function1(static void fast_lreply, int, n, char *, fmt)
 {
     va_list args;
-    char buf[STR_SIZE];
 
     arglist_start(args, fmt);
-    ap_snprintf(buf, sizeof(buf), "%03d-", n);
-    ap_vsnprintf(buf+4, sizeof(buf)-4, fmt, args);
+    lreply_backend(0, n, fmt, args);
     arglist_end(args);
 
-    if (printf("%s\r\n", buf) < 0)
-    {
-       dbprintf(("%s: ! error %d (%s) in printf\n",
-                 debug_prefix_time(NULL), errno, strerror(errno)));
-       uncompress_remove = remove_files(uncompress_remove);
-       exit(1);
-    }
 }
 
 /* see if hostname is valid */
@@ -326,7 +347,7 @@ printf_arglist_function1(static void fast_lreply, int, n, char *, fmt)
 /* also do a security check on the requested dump hostname */
 /* to restrict access to index records if required */
 /* return -1 if not okay */
-int is_dump_host_valid(host)
+static int is_dump_host_valid(host)
 char *host;
 {
     struct stat dir_stat;
@@ -371,7 +392,7 @@ char *host;
 }
 
 
-int is_disk_valid(disk)
+static int is_disk_valid(disk)
 char *disk;
 {
     char *fn;
@@ -403,7 +424,7 @@ char *disk;
 }
 
 
-int is_config_valid(config)
+static int is_config_valid(config)
 char *config;
 {
     char *conffile;
@@ -426,18 +447,20 @@ char *config;
        return -1;
     }
     amfree(conffile);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if ((disk_list = read_diskfile(conf_diskfile)) == NULL) {
+    if (read_diskfile(conf_diskfile, &disk_list) < 0) {
        reply(501, "Could not read disk file %s!", conf_diskfile);
        amfree(conf_diskfile);
        return -1;
     }
     amfree(conf_diskfile);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
@@ -451,10 +474,9 @@ char *config;
     }
     amfree(conf_tapelist);
 
-    output_find = find_dump(1, disk_list);
-    sort_find_result("DLKHB", &output_find);
+    output_find = find_dump(1, &disk_list);
+    sort_find_result("DLKHpB", &output_find);
 
-    /* okay, now look for the index directory */
     conf_indexdir = getconf_str(CNF_INDEXDIR);
     if(*conf_indexdir == '/') {
        conf_indexdir = stralloc(conf_indexdir);
@@ -472,12 +494,13 @@ char *config;
 }
 
 
-int build_disk_table P((void))
+static int build_disk_table()
 {
     char date[3 * NUM_STR_SIZE + 2 + 1];
     long last_datestamp;
     int last_filenum;
     int last_level;
+    int last_partnum;
     find_result_t *find_output;
 
     if (config_name == NULL || dump_hostname == NULL || disk_name == NULL) {
@@ -489,41 +512,48 @@ int build_disk_table P((void))
     last_datestamp = -1;
     last_filenum = -1;
     last_level = -1;
+    last_partnum = -1;
     for(find_output = output_find;
        find_output != NULL; 
        find_output = find_output->next) {
        if(strcasecmp(dump_hostname, find_output->hostname) == 0 &&
           strcmp(disk_name    , find_output->diskname) == 0 &&
           strcmp("OK"         , find_output->status)   == 0) {
+           int partnum = -1;
+           if(strcmp("--", find_output->partnum)){
+               partnum = atoi(find_output->partnum);
+           }
            /*
-            * The sort order puts holding disk entries first.  We want to
+            * The sort order puts holding disk entries first.  We want to
             * use them if at all possible, so ignore any other entries
             * for the same datestamp after we see a holding disk entry
             * (as indicated by a filenum of zero).
             */
            if(find_output->datestamp == last_datestamp &&
-              find_output->level == last_level && last_filenum == 0) {
+              find_output->level == last_level && 
+              partnum == last_partnum && last_filenum == 0) {
                continue;
            }
            last_datestamp = find_output->datestamp;
            last_filenum = find_output->filenum;
            last_level = find_output->level;
-           ap_snprintf(date, sizeof(date), "%04d-%02d-%02d",
+           last_partnum = partnum;
+           snprintf(date, sizeof(date), "%04d-%02d-%02d",
                        find_output->datestamp/10000,
                        (find_output->datestamp/100) %100,
                        find_output->datestamp %100);
            add_dump(date, find_output->level, find_output->label, 
-                    find_output->filenum);
-           dbprintf(("%s: - %s %d %s %d\n",
-                     debug_prefix_time(NULL), date, find_output->level, 
-                     find_output->label, find_output->filenum));
+                    find_output->filenum, partnum);
+           dbprintf(("%s: - %s %d %s %d %d\n",
+                    debug_prefix_time(NULL), date, find_output->level, 
+                    find_output->label, find_output->filenum, partnum));
        }
     }
     return 0;
 }
 
 
-int disk_history_list P((void))
+static int disk_history_list()
 {
     DUMP_ITEM *item;
 
@@ -535,9 +565,22 @@ int disk_history_list P((void))
     lreply(200, " Dump history for config \"%s\" host \"%s\" disk \"%s\"",
          config_name, dump_hostname, disk_name);
 
-    for (item=first_dump(); item!=NULL; item=next_dump(item))
-       lreply(201, " %s %d %s %d", item->date, item->level, item->tape,
+    for (item=first_dump(); item!=NULL; item=next_dump(item)){
+        char *tapelist_str = marshal_tapelist(item->tapes, 1);
+
+       if(am_has_feature(their_features, fe_amindexd_marshall_in_DHST)){
+           str_buffer_size = strlen(item->date) + NUM_STR_SIZE +
+                             strlen(tapelist_str) + 9;
+           lreply(201, " %s %d %s", item->date, item->level, tapelist_str);
+       }
+       else{
+           str_buffer_size = strlen(item->date) + NUM_STR_SIZE +
+                             strlen(tapelist_str) + NUM_STR_SIZE + 9;
+           lreply(201, " %s %d %s %d", item->date, item->level, tapelist_str,
               item->file);
+       }
+       str_buffer_size = STR_SIZE;
+    }
 
     reply(200, "Dump history for config \"%s\" host \"%s\" disk \"%s\"",
          config_name, dump_hostname, disk_name);
@@ -549,7 +592,7 @@ int disk_history_list P((void))
 /* is the directory dir backed up - dir assumed complete relative to
    disk mount point */
 /* opaque version of command */
-int is_dir_valid_opaque(dir)
+static int is_dir_valid_opaque(dir)
 char *dir;
 {
     DUMP_ITEM *item;
@@ -636,7 +679,7 @@ char *dir;
     return -1;
 }
 
-int opaque_ls(dir,recursive)
+static int opaque_ls(dir,recursive)
 char *dir;
 int  recursive;
 {
@@ -644,6 +687,13 @@ int  recursive;
     DIR_ITEM *dir_item;
     int last_level;
     static char *emsg = NULL;
+    am_feature_e marshall_feature;
+
+    if (recursive) {
+        marshall_feature = fe_amindexd_marshall_in_ORLD;
+    } else {
+        marshall_feature = fe_amindexd_marshall_in_OLSD;
+    }
 
     clear_dir_list();
 
@@ -691,52 +741,61 @@ int  recursive;
     }
 
     /* return the information to the caller */
-    if(recursive)
-    {
-       lreply(200, " Opaque recursive list of %s", dir);
-       for (dir_item = get_dir_list(); dir_item != NULL; 
-            dir_item = dir_item->next) {
-           if(am_has_feature(their_features, fe_amindexd_fileno_in_ORLD)){
-               fast_lreply(201, " %s %d %-16s %d %s",
-                           dir_item->dump->date, dir_item->dump->level,
-                           dir_item->dump->tape, dir_item->dump->file,
-                           dir_item->path);
-           }
-           else {
-               fast_lreply(201, " %s %d %-16s %s",
-                           dir_item->dump->date, dir_item->dump->level,
-                           dir_item->dump->tape, dir_item->path);
-           }
-       }
-       reply(200, " Opaque recursive list of %s", dir);
-    }
-    else
-    {
-       lreply(200, " Opaque list of %s", dir);
-       for (dir_item = get_dir_list(); dir_item != NULL; 
-            dir_item = dir_item->next) {
-           if(am_has_feature(their_features, fe_amindexd_fileno_in_OLSD)){
-               lreply(201, " %s %d %-16s %d %s",
-                           dir_item->dump->date, dir_item->dump->level,
-                           dir_item->dump->tape, dir_item->dump->file,
-                           dir_item->path);
-           }
-           else {
-               lreply(201, " %s %d %-16s %s",
-                           dir_item->dump->date, dir_item->dump->level,
-                           dir_item->dump->tape, dir_item->path);
-           }
-       }
-       reply(200, " Opaque list of %s", dir);
+    lreply(200, " Opaque list of %s", dir);
+        for (dir_item = get_dir_list(); dir_item != NULL; 
+             dir_item = dir_item->next) {
+            char *tapelist_str;
+
+            if (!am_has_feature(their_features, marshall_feature) &&
+                (num_entries(dir_item->dump->tapes) > 1 ||
+                dir_item->dump->tapes->numfiles > 1)) {
+                fast_lreply(501, " ERROR: Split dumps not supported"
+                            " with old version of amrecover.");
+                break;
+            } else {
+                if (am_has_feature(their_features, marshall_feature)) {
+                    tapelist_str = marshal_tapelist(dir_item->dump->tapes, 1);
+                } else {
+                    tapelist_str = dir_item->dump->tapes->label;
+                }
+                
+                if((!recursive && am_has_feature(their_features,
+                                                 fe_amindexd_fileno_in_OLSD))
+                   ||
+                   (recursive && am_has_feature(their_features,
+                                                fe_amindexd_fileno_in_ORLD))) {
+                    str_buffer_size = strlen(dir_item->dump->date) +
+                        NUM_STR_SIZE + strlen(tapelist_str) + 
+                        strlen(dir_item->path) + NUM_STR_SIZE + 9;
+                    fast_lreply(201, " %s %d %s %d %s",
+                                dir_item->dump->date, dir_item->dump->level,
+                                tapelist_str, dir_item->dump->file,
+                                dir_item->path);
+                }
+                else {
+                    str_buffer_size = strlen(dir_item->dump->date) +
+                        NUM_STR_SIZE + strlen(tapelist_str) +
+                        strlen(dir_item->path) + 9;
+                    fast_lreply(201, " %s %d %s %s",
+                                dir_item->dump->date, dir_item->dump->level,
+                                tapelist_str, dir_item->path);
+                }
+               if(am_has_feature(their_features, marshall_feature)) {
+                   amfree(tapelist_str);
+               }
+                str_buffer_size = STR_SIZE;
+            }
     }
+    reply(200, " Opaque list of %s", dir);
+
     clear_dir_list();
     return 0;
 }
 
 
-/* returns the value of tapedev from the amanda.conf file if set,
+/* returns the value of changer or tapedev from the amanda.conf file if set,
    otherwise reports an error */
-int tapedev_is P((void))
+static int tapedev_is()
 {
     char *result;
 
@@ -746,20 +805,40 @@ int tapedev_is P((void))
        return -1;
     }
 
+    /* use amrecover_changer if possible */
+    if ((result = getconf_str(CNF_AMRECOVER_CHANGER)) != NULL  &&
+        *result != '\0') {
+       dbprintf(("%s: tapedev_is amrecover_changer: %s\n",
+                  debug_prefix_time(NULL), result));
+       reply(200, result);
+       return 0;
+    }
+
+    /* use changer if possible */
+    if ((result = getconf_str(CNF_TPCHANGER)) != NULL  &&  *result != '\0') {
+       dbprintf(("%s: tapedev_is tpchanger: %s\n",
+                  debug_prefix_time(NULL), result));
+       reply(200, result);
+       return 0;
+    }
+
     /* get tapedev value */
-    if ((result = getconf_str(CNF_TAPEDEV)) == NULL)
-    {
-       reply(501, "Tapedev not set in config file.");
-       return -1;
+    if ((result = getconf_str(CNF_TAPEDEV)) != NULL  &&  *result != '\0') {
+       dbprintf(("%s: tapedev_is tapedev: %s\n",
+                  debug_prefix_time(NULL), result));
+       reply(200, result);
+       return 0;
     }
 
-    reply(200, result);
-    return 0;
+    dbprintf(("%s: No tapedev or changer in config site.\n",
+              debug_prefix_time(NULL)));
+    reply(501, "Tapedev or changer not set in config file.");
+    return -1;
 }
 
 
 /* returns YES if dumps for disk are compressed, NO if not */
-int are_dumps_compressed P((void))
+static int are_dumps_compressed()
 {
     disk_t *diskp;
 
@@ -770,7 +849,7 @@ int are_dumps_compressed P((void))
     }
 
     /* now go through the list of disks and find which have indexes */
-    for (diskp = disk_list->head; diskp != NULL; diskp = diskp->next)
+    for (diskp = disk_list.head; diskp != NULL; diskp = diskp->next)
        if ((strcasecmp(diskp->host->hostname, dump_hostname) == 0)
            && (strcmp(diskp->name, disk_name) == 0))
            break;
@@ -827,6 +906,9 @@ char **argv;
 
     set_pname(pgm);
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
 #ifdef FORCE_USERID
 
     /* we'd rather not run as root */
@@ -844,10 +926,13 @@ char **argv;
 #endif /* FORCE_USERID */
 
     dbopen();
-    startclock();
     dbprintf(("%s: version %s\n", get_pname(), version()));
 
-    if (! (argc >= 1 && argv != NULL && argv[0] != NULL)) {
+    if(argv == NULL) {
+       error("argv == NULL\n");
+    }
+
+    if (! (argc >= 1 && argv[0] != NULL)) {
        dbprintf(("%s: WARNING: argv[0] not defined: check inetd.conf\n",
                  debug_prefix_time(NULL)));
     }
@@ -959,7 +1044,7 @@ char **argv;
                    dbprintf(("%s: ? unprocessed input:\n",
                              debug_prefix_time(NULL)));
                    dbprintf(("-----\n"));
-                   dbprintf(("%s\n", line));
+                   dbprintf(("%s\n", line));
                    dbprintf(("-----\n"));
                }
                amfree(line);
@@ -1017,17 +1102,16 @@ char **argv;
 
        amfree(errstr);
        if (!user_validated && strcmp(cmd, "SECURITY") == 0 && arg) {
-           user_validated = security_ok(&his_addr, arg, 0, &errstr);
+           user_validated = check_security(&his_addr, arg, 0, &errstr);
            if(user_validated) {
                reply(200, "Access OK");
                continue;
            }
        }
-       if (!user_validated) {
-           if (errstr) {
-               reply(500, "Access not allowed: %s", errstr);
-           } else {
-               reply(500, "Access not allowed");
+       if (!user_validated) {  /* don't tell client the reason, just log it to debug log */
+           reply(500, "Access not allowed");
+           if (errstr) {   
+               dbprintf(("%s: %s\n", debug_prefix_time(NULL), errstr));
            }
            break;
        }
@@ -1063,7 +1147,7 @@ char **argv;
            else if(arg) {
                lreply(200, " List of disk for device %s on host %s", arg,
                       dump_hostname);
-               for (disk = disk_list->head; disk!=NULL; disk = disk->next) {
+               for (disk = disk_list.head; disk!=NULL; disk = disk->next) {
                    if(strcmp(disk->host->hostname, dump_hostname) == 0 &&
                       ((disk->device && strcmp(disk->device, arg) == 0) ||
                        (!disk->device && strcmp(disk->name, arg) == 0))) {
@@ -1082,7 +1166,7 @@ char **argv;
            }
            else {
                lreply(200, " List of disk for host %s", dump_hostname);
-               for (disk = disk_list->head; disk!=NULL; disk = disk->next) {
+               for (disk = disk_list.head; disk!=NULL; disk = disk->next) {
                    if(strcmp(disk->host->hostname, dump_hostname) == 0) {
                        fast_lreply(201, " %s", disk->name);
                        nbdisk++;
index b713fc0a384ec22d00de75639443a594a80fbec0..b7bdc4ca04bfd00f805a306c409418ff385f1af6 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amlabel.c,v 1.18.2.15.4.3.2.4.2.4 2005/10/02 13:48:42 martinea Exp $
+ * $Id: amlabel.c,v 1.43 2006/01/14 04:37:19 paddy_s Exp $
  *
  * write an Amanda label on a tape
  */
@@ -40,6 +40,7 @@
 
 /* local functions */
 
+int main P((int, char **));
 void usage P((char *argv0));
 
 void usage(argv0)
@@ -89,7 +90,9 @@ int main(argc, argv)
     safe_cd();
 
     set_pname("amlabel");
-    dbopen();
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
 
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
@@ -120,6 +123,7 @@ int main(argc, argv)
     if (read_conffile(conffile)) {
        error("errors processing config file \"%s\"", conffile);
     }
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
@@ -410,8 +414,8 @@ int main(argc, argv)
        } /* write tape list */
 
         if(have_changer) {
-           /* Now we try to inform the changer, about the new label */
-           changer_label(outslot,label); 
+           /*  Now we try to inform the changer, about the new label */
+           /* changer_label(outslot,label); */
        }
        printf(", done.\n");
     } else {
@@ -431,6 +435,5 @@ int main(argc, argv)
        malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
     }
 
-    dbclose();
     return 0;
 }
index cd7601b911b6a416cf02f79e091df440fc45ccac..35e504d72ae4bdcb86f4aaa8c4280d76fca591ab 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: amlogroll.c,v 1.1.2.1.4.1.2.3.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amlogroll.c,v 1.7 2005/09/20 21:32:26 jrjackson Exp $
  *
  * rename a live log file to the datestamped name.
  */
index 25f1e07c888d89da0a77957c88c59d12114daf5e..300f7ddd1c2e1ad3790ad890a0f0c7af51b088ff 100644 (file)
@@ -78,6 +78,15 @@ elsif($#ARGV > 0) {
   Usage();
 }
 
+#untaint user input $ARGV[0]
+
+if ($opt_config =~ /^([\w.-]+)$/) {          # $1 is untainted
+   $opt_config = $1;
+} else {
+    die "filename '$opt_config' has invalid characters.\n";
+}
+
+
 -d "$confdir/$opt_config" or
        die "$0: directory `$confdir/$opt_config' does not exist.\n";
 
@@ -115,7 +124,7 @@ while (<$fh>) {
     next if /found Amanda directory/;
     next if /skipping cruft directory/;
     next if /skip-incr/;
-    ($date, $host, $disk, $level, $tape, $file, $status) = split ' ', $_;
+    ($date, $host, $disk, $level, $tape, $file, $part, $status) = split ' ', $_;
     next if $date eq 'date';
     next if $date eq 'Warning:';
     next if $date eq 'Scanning';
index 9a702534fdb00ade0a35afd3633be934d7c60ad3..2becac57f1477986343292964dc5ed39fbcd2f39 100644 (file)
@@ -53,10 +53,22 @@ else {
        }
 }
 
+#untaint user input $ARGV[0]
+
+if ($conf =~ /^([\w.-]+)$/) {          # $1 is untainted
+   $conf = $1;
+} else {
+    die "filename '$conf' has invalid characters.\n";
+}
+
+
 if ( ! -d "$confdir/$conf" ) {
     die "amstatus$suf: could not find directory $confdir/$conf";
 }
 
+$oldPATH = $ENV{'PATH'};
+$ENV{'PATH'} = "/bin:/usr/bin:/usr/sbin:/sbin";       # force known path
+
 $pwd = `pwd`;
 chomp $pwd;
 chdir "$confdir/$conf";
@@ -93,6 +105,7 @@ if($nb_options == 0 ) {
 }
 
 $unit=`$sbindir/amgetconf$suf displayunit`;
+$ENV{'PATH'} = $oldPATH;
 chomp($unit);
 $unitdivisor=1;
 if($unit eq 'K') {
@@ -346,7 +359,6 @@ while(<AMDUMP>) {
                $dump_started{$hostpart}=1;
                $dump_time{$hostpart}=$1;
                $dump_finished{$hostpart}=0;
-               $holding_file{$hostpart}=$5;
                if(     $level{$hostpart} != $8 &&
                   $degr_level{$hostpart} == $8) {
                        $level{$hostpart}=$degr_level{$hostpart};
@@ -365,6 +377,32 @@ while(<AMDUMP>) {
                        $dumpers_held[$dumpers_active]={};
                }
        }
+       elsif(/driver: send-cmd time (\S+) to (chunker\d*): (PORT-WRITE) (\d+-\d+) (\S+) (\S+) (\S+) (\d+)/) {
+               $current_time=$1;
+               $host=$6;
+               $partition=$7;
+               $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+               $serial=$4;
+               $serial{$serial}=$hostpart;
+               #$chunk_started{$hostpart}=1;
+               #$chunk_time{$hostpart}=$1;
+               #$chunk_finished{$hostpart}=0;
+               $holding_file{$hostpart}=$5;
+       }
+       elsif(/driver: send-cmd time (\S+) to (chunker\d*): (PORT-WRITE) (\d+-\d+) (\S+) (\S+) (\S+) (\S+) (\d+)/) {
+               $current_time=$1;
+               $host=$6;
+               $features=$7;
+               $features=$features;
+               $partition=$8;
+               $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+               $serial=$4;
+               $serial{$serial}=$hostpart;
+               #$chunk_started{$hostpart}=1;
+               #$chunk_time{$hostpart}=$1;
+               #$chunk_finished{$hostpart}=0;
+               $holding_file{$hostpart}=$5;
+       }
        elsif(/driver: send-cmd time (\S+) to (dumper\d*): (FILE-DUMP|PORT-DUMP) (\d+-\d+) (\S+) (\S+) (\S+) (\S+) (\d+)/) {
                $current_time=$1;
                $host=$6;
@@ -429,7 +467,7 @@ while(<AMDUMP>) {
                        $dumpers_held[$dumpers_active]={};
                }
        }
-       elsif(/driver: send-cmd time (\S+) to (dumper\d*): CONTINUE (\d+-\d+) (\S+) (\d+) (\d+)/) {
+       elsif(/driver: send-cmd time (\S+) to (chunker\d*): CONTINUE (\d+-\d+) (\S+) (\d+) (\d+)/) {
                $current_time=$1;
                $serial=$3;
                $hostpart=$serial{$serial};
@@ -463,11 +501,11 @@ while(<AMDUMP>) {
                $error{$hostpart}="driver: (aborted:$error)";
                $dumpers_active--;
        }
-       elsif(/driver: result time (\S+) from (dumper\d+): DONE (\d+-\d+) (\d+) (\d+) (\d+) \[.*\]/) {
+       elsif(/driver: result time (\S+) from (dumper\d+): (DONE|PARTIAL) (\d+-\d+) (\d+) (\d+) (\d+) \[.*\]/) {
                $current_time=$1;
-               $serial=$3;
-               $origsize=$4 / $unitdivisor;
-               $outputsize=$5 / $unitdivisor;
+               $serial=$4;
+               $origsize=$5 / $unitdivisor;
+               $outputsize=$6 / $unitdivisor;
                $hostpart=$serial{$serial};
                $size{$hostpart}=$outputsize;
                $dump_finished{$hostpart}=1;
@@ -476,6 +514,20 @@ while(<AMDUMP>) {
                $dump_time{$hostpart}=$1;
                $error{$hostpart}="";
                $dumpers_active--;
+               $partial{$hostpart}=1 if $3 eq "PARTIAL" ;
+       }
+       elsif(/driver: result time (\S+) from (chunker\d+): (DONE|PARTIAL) (\d+-\d+) (\d+) \[.*\]/) {
+               $current_time=$1;
+               $serial=$4;
+               $outputsize=$5 / $unitdivisor;
+               $hostpart=$serial{$serial};
+               $size{$hostpart}=$outputsize;
+               $dump_finished{$hostpart}=1;
+               $busy_time{$2}+=($1-$dump_time{$hostpart});
+               $running_dumper{$2} = "0";
+               $dump_time{$hostpart}=$1;
+               $error{$hostpart}="";
+               $partial{$hostpart}=1 if $3 eq "PARTIAL" ;
        }
        elsif(/driver: result time (\S+) from (dumper\d+): ABORT-FINISHED (\d+-\d+)/) {
                $current_time=$1;
@@ -489,7 +541,7 @@ while(<AMDUMP>) {
                $error{$hostpart}="driver: (aborted)";
                $dumpers_active--;
        }
-       elsif(/driver: result time (\S+) from (dumper\d+): RQ-MORE-DISK (\d+-\d+)/) {
+       elsif(/driver: result time (\S+) from (chunker\d+): RQ-MORE-DISK (\d+-\d+)/) {
                $current_time=$1;
                $serial=$3;
                $hostpart=$serial{$serial};
@@ -576,11 +628,11 @@ while(<AMDUMP>) {
                $taper_finished{$hostpart}=0;
                $taper_time{$hostpart}=$1;
        }
-       elsif(/driver: result time (\S+) from taper: DONE (\d+-\d+) (\S+) (\d+) \[sec (\S+) kb (\d+) kps/) {
+       elsif(/driver: result time (\S+) from taper: (DONE|PARTIAL) (\d+-\d+) (\S+) (\d+) \[sec (\S+) kb (\d+) kps/) {
                $current_time=$1;
-               $serial=$2;
-               $label=$3;
-               $size=$6 / $unitdivisor;
+               $serial=$3;
+               $label=$4;
+               $size=$7 / $unitdivisor;
                $hostpart=$serial{$serial};
                $taper_finished{$hostpart}=1;
                $busy_time{"taper"}+=($1-$taper_time{$hostpart});
@@ -596,6 +648,7 @@ while(<AMDUMP>) {
                else {
                        $ntesize{$nb_tape} += $size{$hostpart};
                }
+               $partial{$hostpart}=1 if $3 eq "PARTIAL" ;
        }
        elsif(/driver: result time (\S+) from taper: (TRY-AGAIN|TAPE-ERROR) (\d+-\d+) (.+)/) {
                $current_time=$1;
@@ -904,6 +957,7 @@ foreach $host (sort @hosts) {
                                                        if( defined $starttime ) {
                                                                print " (", &showtime($taper_time{$hostpart}), ")";
                                                        }
+                                                       print ", PARTIAL" if defined $partial{$hostpart};
                                                        print "\n";
                                                }
                                                $tpartition++;
@@ -989,7 +1043,9 @@ foreach $host (sort @hosts) {
                                                        if( defined $starttime ) {
                                                                print " (", &showtime($dump_time{$hostpart}), ")";
                                                        }
-                                                       print ", wait for writing to tape\n";
+                                                       print ", wait for writing to tape";
+                                                  print ", PARTIAL" if defined $partial{$hostpart};
+                                                       print "\n";
                                                }
                                                $dpartition++;
                                                $dsize += $size{$hostpart};
@@ -1009,7 +1065,9 @@ foreach $host (sort @hosts) {
                                                printf "%8s ", $datestamp if defined $opt_date;
                                                printf "%-${maxnamelength}s%2d", "$host:$partition", $level{$hostpart};
                                                printf "%9d$unit", $size{$hostpart};
-                                               print " waiting to flush\n";
+                                               print " waiting to flush";
+                                               print ", PARTIAL" if defined $partial{$hostpart};
+                                               print "\n";
                                        }
                                        $wfpartition++;
                                        $wfsize += $size{$hostpart};
index 3465e7ffdb958923e3f4c6b59a087b59d3632975..fad6e406b78dda813269e1806307f29110501966 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amtape.c,v 1.22.2.6.4.5.2.4.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amtape.c,v 1.40 2006/01/14 04:37:19 paddy_s Exp $
  *
  * tape changer interface program
  */
 #include "amanda.h"
 #include "conffile.h"
 #include "tapefile.h"
+#include "taperscan.h"
 #include "tapeio.h"
 #include "clock.h"
 #include "changer.h"
@@ -46,39 +47,60 @@ void load_slot P((int argc, char **argv));
 void load_label P((int argc, char **argv));
 void show_slots P((int argc, char **argv));
 void show_current P((int argc, char **argv));
-void taper_scan P((int argc, char **argv));
+void amtape_taper_scan P((int argc, char **argv));
 void show_device P((int argc, char **argv));
-int scan_init P((int rc, int ns, int bk));
-int loadlabel_slot P((int rc, char *slotstr, char *device));
-int show_init P((int rc, int ns, int bk));
-int show_init_all P((int rc, int ns, int bk));
-int show_init_current P((int rc, int ns, int bk));
-int show_slot P((int rc, char *slotstr, char *device));
-int taperscan_slot P((int rc, char *slotstr, char *device));
-int update_one_slot P((int rc, char *slotstr, char *device));
-void update_labeldb P((int argc, char **argv));
+int loadlabel_slot P((void *ud, int rc, char *slotstr, char *device));
+int show_init P((void *ud, int rc, int ns, int bk, int s));
+int show_init_all P((void *ud, int rc, int ns, int bk, int s));
+int show_init_current P((void *ud, int rc, int ns, int bk, int s));
+int show_slot P((void *ud, int rc, char *slotstr, char *device));
+
+static const struct {
+    const char *name;
+    void (*fn) P((int, char **));
+    const char *usage;
+} cmdtab[] = {
+    { "reset", reset_changer,
+       "reset                Reset changer to known state" },
+    { "eject", eject_tape,
+       "eject                Eject current tape from drive" },
+    { "clean", clean_tape,
+       "clean                Clean the drive" },
+    { "show", show_slots,
+       "show                 Show contents of all slots" },
+    { "current", show_current,
+       "current              Show contents of current slot" },
+    { "slot" , load_slot,
+       "slot <slot #>        load tape from slot <slot #>" },
+    { "slot" , load_slot,
+       "slot current         load tape from current slot" },
+    { "slot" , load_slot,
+       "slot prev            load tape from previous slot" },
+    { "slot" , load_slot,
+       "slot next            load tape from next slot" },
+    { "slot" , load_slot,
+       "slot advance         advance to next slot but do not load" },
+    { "slot" , load_slot,
+       "slot first           load tape from first slot" },
+    { "slot" , load_slot,
+       "slot last            load tape from last slot" },
+    { "label", load_label,
+       "label <label>        find and load labeled tape" },
+    { "taper", amtape_taper_scan,
+       "taper                perform taper's scan alg." },
+    { "device", show_device,
+       "device               show current tape device" },
+};
+#define        NCMDS   (sizeof(cmdtab) / sizeof(cmdtab[0]))
 
 void usage()
 {
+    int i;
+
     fprintf(stderr, "Usage: amtape%s <conf> <command>\n", versionsuffix());
     fprintf(stderr, "\tValid commands are:\n");
-    fprintf(stderr, "\t\treset                Reset changer to known state\n");
-    fprintf(stderr, "\t\teject                Eject current tape from drive\n");
-    fprintf(stderr, "\t\tclean                Clean the drive\n");
-    fprintf(stderr, "\t\tshow                 Show contents of all slots\n");
-    fprintf(stderr, "\t\tcurrent              Show contents of current slot\n");
-    fprintf(stderr, "\t\tslot <slot #>        load tape from slot <slot #>\n");
-    fprintf(stderr, "\t\tslot current         load tape from current slot\n");
-    fprintf(stderr, "\t\tslot prev            load tape from previous slot\n");
-    fprintf(stderr, "\t\tslot next            load tape from next slot\n");
-    fprintf(stderr, "\t\tslot advance         advance to next slot but do not load\n");
-    fprintf(stderr, "\t\tslot first           load tape from first slot\n");
-    fprintf(stderr, "\t\tslot last            load tape from last slot\n");
-    fprintf(stderr, "\t\tlabel <label>        find and load labeled tape\n");
-    fprintf(stderr, "\t\ttaper                perform taper's scan alg.\n");
-    fprintf(stderr, "\t\tdevice               show current tape device\n");
-    fprintf(stderr, "\t\tupdate               update the label matchingdatabase\n");
-
+    for (i = 0; i < NCMDS; i++)
+       fprintf(stderr, "\t\t%s\n", cmdtab[i].usage);
     exit(1);
 }
 
@@ -91,6 +113,7 @@ char **argv;
     char *argv0 = argv[0];
     unsigned long malloc_hist_1, malloc_size_1;
     unsigned long malloc_hist_2, malloc_size_2;
+    int i;
     int have_changer;
     uid_t uid_me;
     uid_t uid_dumpuser;
@@ -101,7 +124,9 @@ char **argv;
     safe_cd();
 
     set_pname("amtape");
-    dbopen();
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
 
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
@@ -116,6 +141,7 @@ char **argv;
     if (read_conffile(conffile)) {
        error("errors processing config file \"%s\"", conffile);
     }
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
@@ -155,17 +181,12 @@ char **argv;
     /* switch on command name */
 
     argc -= 2; argv += 2;
-    if(strcmp(argv[0], "reset") == 0) reset_changer(argc, argv);
-    else if(strcmp(argv[0], "clean") == 0) clean_tape(argc, argv);
-    else if(strcmp(argv[0], "eject") == 0) eject_tape(argc, argv);
-    else if(strcmp(argv[0], "slot") == 0) load_slot(argc, argv);
-    else if(strcmp(argv[0], "label") == 0) load_label(argc, argv);
-    else if(strcmp(argv[0], "current") == 0)  show_current(argc, argv);
-    else if(strcmp(argv[0], "show") == 0)  show_slots(argc, argv);
-    else if(strcmp(argv[0], "taper") == 0) taper_scan(argc, argv);
-    else if(strcmp(argv[0], "device") == 0) show_device(argc, argv);
-    else if(strcmp(argv[0], "update") == 0) update_labeldb(argc, argv);
-    else {
+    for (i = 0; i < NCMDS; i++)
+       if (strcmp(argv[0], cmdtab[i].name) == 0) {
+           (*cmdtab[i].fn)(argc, argv);
+           break;
+       }
+    if (i == NCMDS) {
        fprintf(stderr, "%s: unknown command \"%s\"\n", argv0, argv[0]);
        usage();
     }
@@ -180,7 +201,6 @@ char **argv;
        malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
     }
 
-    dbclose();
     return 0;
 }
 
@@ -283,8 +303,10 @@ char *label = NULL, *first_match_label = NULL, *first_match = NULL;
 char *searchlabel, *labelstr;
 tape_t *tp;
 
-int scan_init(rc, ns, bk)
-int rc, ns, bk;
+static int 
+scan_init(ud, rc, ns, bk, s)
+     void *ud;
+     int rc, ns, bk, s;
 {
     if(rc)
        error("could not get changer info: %s", changer_resultstr);
@@ -295,7 +317,8 @@ int rc, ns, bk;
     return 0;
 }
 
-int loadlabel_slot(rc, slotstr, device)
+int loadlabel_slot(ud, rc, slotstr, device)
+     void *ud;
 int rc;
 char *slotstr;
 char *device;
@@ -348,7 +371,7 @@ char **argv;
 
     found = 0;
 
-    changer_find(scan_init, loadlabel_slot, searchlabel);
+    changer_find(NULL, scan_init, loadlabel_slot, searchlabel);
 
     if(found)
        fprintf(stderr, "%s: label %s is now loaded.\n",
@@ -361,8 +384,9 @@ char **argv;
 
 /* ---------------------------- */
 
-int show_init(rc, ns, bk)
-int rc, ns, bk;
+int show_init(ud, rc, ns, bk, s)
+     void *ud;
+int rc, ns, bk, s;
 {
     if(rc)
        error("could not get changer info: %s", changer_resultstr);
@@ -372,47 +396,28 @@ int rc, ns, bk;
     return 0;
 }
 
-int show_init_all(rc, ns, bk)
-int rc, ns, bk;
+int show_init_all(ud, rc, ns, bk, s)
+     void *ud;
+int rc, ns, bk, s;
 {
-    int ret = show_init(rc, ns, bk);
+    int ret = show_init(NULL, rc, ns, bk, s);
     fprintf(stderr, "%s: scanning all %d slots in tape-changer rack:\n",
            get_pname(), nslots);
     return ret;
 }
 
-int show_init_current(rc, ns, bk)
-int rc, ns, bk;
+int show_init_current(ud, rc, ns, bk, s)
+     void *ud;
+int rc, ns, bk, s;
 {
-    int ret = show_init(rc, ns, bk);
+    int ret = show_init(NULL, rc, ns, bk, s);
     fprintf(stderr, "%s: scanning current slot in tape-changer rack:\n",
            get_pname());
     return ret;
 }
 
-int update_one_slot(rc, slotstr, device)
-int rc;
-char *slotstr, *device;
-{
-    char *errstr;
-
-    if(rc > 1)
-       error("could not load slot %s: %s", slotstr, changer_resultstr);
-    else if(rc == 1)
-       fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
-    else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
-       fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
-    else {
-       fprintf(stderr, "slot %s: date %-8s label %s\n",
-               slotstr, datestamp, label);
-       changer_label(slotstr,label);
-    }
-    amfree(datestamp);
-    amfree(label);
-    return 0;
-}
-
-int show_slot(rc, slotstr, device)
+int show_slot(ud, rc, slotstr, device)
+     void *ud;
 int rc;
 char *slotstr, *device;
 {
@@ -440,17 +445,7 @@ char **argv;
     if(argc != 1)
        usage();
 
-    changer_current(show_init_current, show_slot);
-}
-
-void update_labeldb(argc, argv)
-int argc;
-char **argv;
-{
-    if(argc != 1)
-       usage();
-
-    changer_scan(show_init_all, update_one_slot);
+    changer_current(NULL, show_init_current, show_slot);
 }
 
 void show_slots(argc, argv)
@@ -460,88 +455,17 @@ char **argv;
     if(argc != 1)
        usage();
 
-    changer_scan(show_init_all, show_slot);
+    changer_find(NULL, show_init_all, show_slot, NULL);
 }
 
 
 /* ---------------------------- */
-
-int taperscan_slot(rc, slotstr, device)
-int rc;
-char *slotstr;
-char *device;
-{
-    char *errstr;
-
-    if(rc == 2)
-       error("could not load slot %s: %s", slotstr, changer_resultstr);
-    else if(rc == 1)
-       fprintf(stderr, "%s: slot %s: %s\n",
-               get_pname(), slotstr, changer_resultstr);
-    else {
-       if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
-           fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
-       } else {
-           /* got an amanda tape */
-           fprintf(stderr, "%s: slot %s: date %-8s label %s",
-                   get_pname(), slotstr, datestamp, label);
-           if(searchlabel != NULL
-              && (strcmp(label, FAKE_LABEL) == 0
-                  || strcmp(label, searchlabel) == 0)) {
-               /* it's the one we are looking for, stop here */
-               fprintf(stderr, " (exact label match)\n");
-               found = 1;
-               amfree(datestamp);
-               amfree(label);
-               return 1;
-           }
-           else if(!match(labelstr, label))
-               fprintf(stderr, " (no match)\n");
-           else {
-               /* not an exact label match, but a labelstr match */
-               /* check against tape list */
-               tp = lookup_tapelabel(label);
-               if(tp == NULL)
-                   fprintf(stderr, " (not in tapelist)\n");
-               else if(!reusable_tape(tp))
-                   fprintf(stderr, " (active tape)\n");
-               else if(got_match == 0 && tp->datestamp == 0) {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(stderr, " (new tape)\n");
-                   found = 3;
-                   amfree(datestamp);
-                   amfree(label);
-                   return 1;
-               }
-               else if(got_match)
-                   fprintf(stderr, " (labelstr match)\n");
-               else {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(stderr, " (first labelstr match)\n");
-                   if(!backwards || !searchlabel) {
-                       found = 2;
-                       amfree(datestamp);
-                       amfree(label);
-                       return 1;
-                   }
-               }
-           }
-       }
-    }
-    amfree(datestamp);
-    amfree(label);
-    return 0;
-}
-
-void taper_scan(argc, argv)
+void amtape_taper_scan(argc, argv)
 int argc;
 char **argv;
 {
-    char *slotstr = NULL, *device = NULL;
+    char *device = NULL;
+    char *label = NULL, *errmsg = NULL;
 
     if((tp = lookup_last_reusable_tape(0)) == NULL)
        searchlabel = NULL;
@@ -557,48 +481,17 @@ char **argv;
     if(searchlabel) fprintf(stderr, "tape label %s or ", searchlabel);
     fprintf(stderr, "a new tape.\n");
 
-    if (searchlabel != NULL)
-      changer_find(scan_init, taperscan_slot, searchlabel);
-    else
-      changer_scan(scan_init, taperscan_slot);
-
-    if(found == 3) {
-       fprintf(stderr, "%s: settling for new tape\n", get_pname());
-       searchlabel = newstralloc(searchlabel, first_match_label);
-    }
-    else if(found == 2) {
-       fprintf(stderr, "%s: %s: settling for first labelstr match\n",
-               get_pname(),
-               searchlabel? "gravity stacker": "looking only for new tape");
-       searchlabel = newstralloc(searchlabel, first_match_label);
-    }
-    else if(!found && got_match) {
-       fprintf(stderr,
-               "%s: %s not found, going back to first labelstr match %s\n",
-               get_pname(), searchlabel, first_match_label);
-       searchlabel = newstralloc(searchlabel, first_match_label);
-       if(changer_loadslot(first_match, &slotstr, &device) == 0) {
-           found = 1;
-       } else {
-           fprintf(stderr, "%s: could not load labelstr match in slot %s: %s\n",
-                   get_pname(), first_match, changer_resultstr);
-       }
-       amfree(device);
-       amfree(slotstr);
-    }
-    else if(!found) {
-       fprintf(stderr, "%s: could not find ", get_pname());
-       if(searchlabel) fprintf(stderr, "tape %s or ", searchlabel);
-       fprintf(stderr, "a new tape in the tape rack.\n");
+    if (taper_scan(searchlabel, &label, &datestamp, &errmsg, &device) <= 0) {
+        fprintf(stderr, "%s\n", errmsg);
     }
 
-    if(found)
-       fprintf(stderr, "%s: label %s is now loaded.\n",
-               get_pname(), searchlabel);
+    fprintf(stderr, "%s: label %s is now loaded.\n",
+            get_pname(), label);
 
-    amfree(searchlabel);
-    amfree(first_match);
-    amfree(first_match_label);
+    amfree(label);
+    amfree(datestamp);
+    amfree(errmsg);
+    amfree(device);
 }
 
 /* ---------------------------- */
index 0e6a8d7da340e425acb84e208e5cada365394c18..d25010234792e7ad1c3418a9d4c706ffd9590c06 100644 (file)
@@ -34,7 +34,7 @@
 
 
 #--------------------------------------------------------
-sub pr($$$$$$) { 
+sub pr($$$$$$$) { 
 # you can update these proc if you want another formating
 # format: filenumber  host:part  date  level  size
 # If you use tabular option, modifie the format at the end of the code
@@ -44,9 +44,10 @@ sub pr($$$$$$) {
        $dt=$_[3];
        $lvl=$_[4];
        $sz=$_[5];
+       $ch=$_[6];
     write($OF);
   } else {
-    print $OF "$_[0]  $_[1]:$_[2]  $_[3]  $_[4]  $_[5]\n";
+    print $OF "$_[0]  $_[1]:$_[2]  $_[3]  $_[4]  $_[5]  $_[6]\n";
   }
 }
 #--------------------------------------------------------
@@ -145,23 +146,24 @@ while ( <$IF> ) {
   }
   if ( /^SUCCESS dumper (\S+) (\S+)/ ) {
     $host = $1;
-    $part = $2;
+    $disk = $2;
     $line =~ /orig-kb (\d+)/;
-    $osize{$host}{$part} = $1;
-    $tot_or_size += $osize{$host}{$part};
-    $fail{$host}{$part} = 0;
+    $osize{$host}{$disk} = $1;
+    $tot_or_size += $osize{$host}{$disk};
+    $fail{$host}{$disk} = 0;
     next;
   }
   if ( /^START amflush/ ) {
     $flash_mode = 1;
     next;
   }
-  if ( ! /^([A-Z]+) taper (\S+) (\S+) (\S+) (\S+)/) { next;}
+  if ( ! /^([A-Z]+) taper (\S+) (\S+) (\S+) (\S+) (\S+)/) { next;}
   # $_ = $1;
   $host = $2;
-  $part = $3;
+  $disk = $3;
   $date = $4;
-  $level = $5;
+  $chunk = $5;
+  $level = $6;
   switch: {
     /START taper/ && do {
       $tocfilename=&tfn($level) if ($#subs >= 0);
@@ -183,23 +185,34 @@ while ( <$IF> ) {
 
 
       $filenumber=0;
-      &pr("#","Server","/partition","date", "level","size[Kb]");
-      &pr("$filenumber","$level","","$part","-","-");
+      &pr("#","Server","/partition","date", "level","size[Kb]","part");
+      &pr("$filenumber","$chunk","","$disk","-","-","-");
       last switch; };
-    /SUCCESS taper/ && do {
-      $line =~ / kb (\d+) /;
-      if ( $fail{$host}{$part} ) {
-        &pr("$filenumber","${host}","${part}","${date}","${level}","FAIL");
+    /^(?:SUCCESS|CHUNK) taper/ && do {
+      if(/SUCCESS/){
+       $level = $chunk;
+       $chunk = "-";
+      }
+      $mysize = 0;
+      if(/ kb (\d+) /){
+       $mysize = $1;
+      }
+      if ( $fail{$host}{$disk} ) {
+        &pr("$filenumber","${host}","${disk}","${date}","${level}","FAIL","${chunk}");
       } else {
        if (defined($flash_mode)) {
-          &pr("$filenumber","${host}","${part}","${date}","${level}","$1");
+          &pr("$filenumber","${host}","${disk}","${date}","${level}","$mysize","${chunk}");
        } else {
-         if (defined($osize{$host}{$part})) {
-            &pr("$filenumber","${host}","${part}","${date}","${level}","$osize{$host}{$part}");
+         if (defined($osize{$host}{$disk}) && !/^CHUNK/) {
+            &pr("$filenumber","${host}","${disk}","${date}","${level}","$osize{$host}{$disk}","${chunk}");
          } else {
+           $note = "";
+           if(!/^CHUNK/){
                # this case should never happend: 
-            &pr("$filenumber","${host}","${part}","${date}","${level}","*$1");
            $strange=1;
+             $note = "*";
+           }
+            &pr("$filenumber","${host}","${disk}","${date}","${level}","$note$mysize","${chunk}");
          }
        }
       }
@@ -212,14 +225,14 @@ while ( <$IF> ) {
       $size = $1;
       $line =~ / fm (\d+) /;
       print "\n\n" if ($vwspace);
-      &pr("$1","total","on_tape","-","-","$size");
+      &pr("$1","total","on_tape","-","-","$size","-");
       if (defined($flash_mode)) {
-       &pr("$1","total","origin","-","not","available");
+       &pr("$1","total","origin","-","not","available","-");
       } else {
-       &pr("$1","total","origin","-","-","$tot_or_size");
+       &pr("$1","total","origin","-","-","$tot_or_size","-");
       }
       if (defined($strange)) {
-       &pr("*","size","on_tape","-","-","-");
+       &pr("*","size","on_tape","-","-","-","-");
       }
       last switch; };
     /FAIL taper/ && do { next; };
@@ -236,6 +249,6 @@ $fnbr,$hstprt,$dt,$lvl,$sz
 .
 
 format STDOUT =
-@>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<< @>> @>>>>>>>>
-$fnbr,$hstprt,$dt,$lvl,$sz
+@>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<< @>> @>>>>>>>> @>>>
+$fnbr,$hstprt,$dt,$lvl,$sz,$ch
 .
index 62adeb7fe269b849f6d96b9e0dce131e9f248eb1..681e4ab088ad11eedc33e033a9d69d3faf878d18 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amtrmidx.c,v 1.21.4.1.4.2.2.5.2.2 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amtrmidx.c,v 1.34 2006/01/14 04:37:19 paddy_s Exp $
  *
  * trims number of index files to only those still in system.  Well
  * actually, it keeps a few extra, plus goes back to the last level 0
@@ -43,8 +43,8 @@
 #include "version.h"
 
 static int sort_by_name_reversed(a, b)
-const void *a;
-const void *b;
+    const void *a;
+    const void *b;
 {
     char **ap = (char **) a;
     char **bp = (char **) b;
@@ -52,12 +52,14 @@ const void *b;
     return -1 * strcmp(*ap, *bp);
 }
 
+int main P((int, char **));
+
 int main(argc, argv)
 int argc;
 char **argv;
 {
     disk_t *diskp;
-    disklist_t *diskl;
+    disklist_t diskl;
     int i;
     char *conffile;
     char *conf_diskfile;
@@ -72,6 +74,9 @@ char **argv;
 
     set_pname("amtrmidx");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     dbopen();
     dbprintf(("%s: version %s\n", argv[0], version()));
 
@@ -90,32 +95,31 @@ char **argv;
 
     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
     conffile = stralloc2(config_dir, CONFFILE_NAME);
-    if(read_conffile(conffile)) {
+    if (read_conffile(conffile))
        error("errors processing config file \"%s\"", conffile);
-    }
     amfree(conffile);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if(*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((diskl = read_diskfile(conf_diskfile)) == NULL) {
-       error("could not load disklist \"%s\".", conf_diskfile);
-    }
+    if (read_diskfile(conf_diskfile, &diskl) < 0)
+       error("could not load disklist \"%s\"", conf_diskfile);
     amfree(conf_diskfile);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if(*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
     } else {
        conf_tapelist = stralloc2(config_dir, conf_tapelist);
     }
-    if(read_tapelist(conf_tapelist)) {
+    if(read_tapelist(conf_tapelist))
        error("could not load tapelist \"%s\"", conf_tapelist);
-    }
     amfree(conf_tapelist);
 
-    output_find = find_dump(1, diskl);
+    output_find = find_dump(1, &diskl);
 
     conf_indexdir = getconf_str(CNF_INDEXDIR);
     if(*conf_indexdir == '/') {
@@ -127,8 +131,10 @@ char **argv;
     /* now go through the list of disks and find which have indexes */
     time(&tmp_time);
     tmp_time -= 7*24*60*60;                    /* back one week */
-    for (diskp = diskl->head; diskp != NULL; diskp = diskp->next) {
-       if (diskp->index) {
+    for (diskp = diskl.head; diskp != NULL; diskp = diskp->next)
+    {
+       if (diskp->index)
+       {
            char *indexdir;
            DIR *d;
            struct dirent *f;
@@ -143,13 +149,13 @@ char **argv;
            /* get listing of indices, newest first */
            host = sanitise_filename(diskp->host->hostname);
            disk = sanitise_filename(diskp->name);
-           indexdir = vstralloc (conf_indexdir, "/",
-                                 host, "/",
-                                 disk, "/",
-                                 NULL);
+           indexdir = vstralloc(conf_indexdir, "/",
+                                host, "/",
+                                disk, "/",
+                                NULL);
            amfree(host);
            amfree(disk);
-           if((d = opendir(indexdir)) == NULL) {
+           if ((d = opendir(indexdir)) == NULL) {
                dbprintf(("could not open index directory \"%s\"\n", indexdir));
                amfree(indexdir);
                continue;
index 52e936db9d633020e1bfc9966e8f8b5cdf0ab3c2..f075ca92f99867386740b5af6fa19f3966a81d91 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amtrmlog.c,v 1.1.2.3.4.1.2.2.2.1 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: amtrmlog.c,v 1.10 2006/01/14 04:37:19 paddy_s Exp $
  *
  * trims number of index files to only those still in system.  Well
  * actually, it keeps a few extra, plus goes back to the last level 0
 #include "find.h"
 #include "version.h"
 
+int main P((int, char **));
+
 int main(argc, argv)
 int argc;
 char **argv;
 {
-    disklist_t *diskl;
+    disklist_t diskl;
     int no_keep;                       /* files per system to keep */
     char **output_find_log;
     DIR *dir;
@@ -70,13 +72,16 @@ char **argv;
 
     set_pname("amtrmlog");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     if (argc > 1 && strcmp(argv[1], "-t") == 0) {
        amtrmidx_debug = 1;
        argc--;
        argv++;
     }
 
-    if (argc != 2) {
+    if (argc < 2) {
        fprintf(stderr, "Usage: %s [-t] <config>\n", argv[0]);
        return 1;
     }
@@ -88,35 +93,34 @@ char **argv;
 
     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
     conffile = stralloc2(config_dir, CONFFILE_NAME);
-    if(read_conffile(conffile)) {
-       error("errors processing config file \"%s\"", conffile);
-    }
+    if (read_conffile(conffile))
+       error("errors processing amanda config file \"%s\"", conffile);
     amfree(conffile);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((diskl = read_diskfile(conf_diskfile)) == NULL) {
-       error("could not load disklist %s", conf_diskfile);
-    }
+    if (read_diskfile(conf_diskfile, &diskl) < 0)
+       error("could not load disklist \"%s\"", conf_diskfile);
     amfree(conf_diskfile);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
     } else {
        conf_tapelist = stralloc2(config_dir, conf_tapelist);
     }
-    if (read_tapelist(conf_tapelist)) {
+    if (read_tapelist(conf_tapelist))
        error("could not load tapelist \"%s\"", conf_tapelist);
-    }
     amfree(conf_tapelist);
 
     today = time((time_t *)NULL);
     date_keep = today - (getconf_int(CNF_DUMPCYCLE)*86400);
 
-    output_find_log = find_log(NULL,0,NULL);
+    output_find_log = find_log();
 
     /* determine how many log to keep */
     no_keep = getconf_int(CNF_TAPECYCLE) * 2;
@@ -129,12 +133,10 @@ char **argv;
        conf_logdir = stralloc2(config_dir, conf_logdir);
     }
     olddir = vstralloc(conf_logdir, "/oldlog", NULL);
-    if (mkpdir(olddir, 02700, (uid_t)-1, (gid_t)-1) != 0) {
+    if (mkpdir(olddir, 02700, (uid_t)-1, (gid_t)-1) != 0)
        error("could not create parents of %s: %s", olddir, strerror(errno));
-    }
-    if (mkdir(olddir, 02700) != 0 && errno != EEXIST) {
+    if (mkdir(olddir, 02700) != 0 && errno != EEXIST)
        error("could not create %s: %s", olddir, strerror(errno));
-    }
 
     if (stat(olddir,&stat_old) == -1) {
        error("can't stat oldlog directory \"%s\": %s", olddir, strerror(errno));
@@ -143,33 +145,32 @@ char **argv;
     if (!S_ISDIR(stat_old.st_mode)) {
        error("Oldlog directory \"%s\" is not a directory", olddir);
     }
-    if ((dir = opendir(conf_logdir)) == NULL) {
-       error("could not open log directory \"%s\": %s", conf_logdir, strerror(errno));
-    }
-    while ((adir = readdir(dir)) != NULL) {
+
+    if ((dir = opendir(conf_logdir)) == NULL)
+       error("could not open log directory \"%s\": %s", conf_logdir,strerror(errno));
+    while ((adir=readdir(dir)) != NULL) {
        if(strncmp(adir->d_name,"log.",4)==0) {
-           useful = 0;
-           for (name = output_find_log; *name != NULL; name++) {
-               if(strncmp(adir->d_name, *name, 12) == 0) {
-                   useful = 1;
+           useful=0;
+           for (name=output_find_log;*name !=NULL; name++) {
+               if(strncmp(adir->d_name,*name,12)==0) {
+                   useful=1;
                }
            }
-           logname = newvstralloc(logname,
-                                  conf_logdir, "/", adir->d_name, NULL);
-           if(stat(logname, &stat_log) == 0) {
+           logname=newvstralloc(logname,
+                                conf_logdir, "/" ,adir->d_name, NULL);
+           if(stat(logname,&stat_log)==0) {
                if(stat_log.st_mtime > date_keep) {
                    useful = 1;
                }
            }
-           if(! useful) {
+           if(useful == 0) {
                oldfile = newvstralloc(oldfile,
                                       conf_logdir, "/", adir->d_name, NULL);
                newfile = newvstralloc(newfile,
                                       olddir, "/", adir->d_name, NULL);
-               if(rename(oldfile, newfile) != 0) {
+               if (rename(oldfile,newfile) != 0)
                    error("could not rename \"%s\" to \"%s\": %s",
                          oldfile, newfile, strerror(errno));
-               }
            }
        }
     }
index 9af9118e9c335788c59cf62526fb90718406f74b..809445131593747b6d1147af25b251694c928ff9 100644 (file)
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-#      $Id: amverify.sh.in,v 1.7.2.13.4.5.2.6.2.3 2005/09/15 13:26:45 martinea Exp $
+#      $Id: amverify.sh.in,v 1.35 2006/03/16 17:32:32 ktill Exp $
 #
 # (C) 1996 by ICEM Systems GmbH
 # Author: Axel Zinser (fifi@icem.de)
@@ -119,8 +119,8 @@ doonefile() {
                echo "** No header" > $TEMP/errors
        else
                set X $HEADER
-               shift
-               shift 9
+               # XXX meh, while[] is dangerous, what about a bad header?
+               while [ X"$1" != X"program" ]; do shift; done
                if [ X"$1" = X"program" -a X"$2" != X"" ]; then
                        if [ X"$TAR" != X"" \
                             -a \( X"`basename $2`" = X"`basename $TAR`" \
@@ -158,7 +158,13 @@ doonefile() {
                        echo "** Cannot find dump type" > $TEMP/errors
                fi
        fi
-       if [ X"$CMD" != X"" ]; then
+       echo $CMD > $TEMP/onefile.cmd
+       if [ X"`echo $HEADER | grep '^AMANDA: SPLIT_FILE'`" != X"" ]; then
+           result=500
+           set X $HEADER
+           shift 7
+           echo $1 | cut -f7 -d' ' > $TEMP/onefile.partnum
+       elif [ X"$CMD" != X"" ]; then
                if [ -x $CMD ]; then
                        $CMD $ARGS > /dev/null 2> $TEMP/errors
                        result=$?
@@ -346,6 +352,7 @@ report ""
 
 # ----------------------------------------------------------------------------
 
+SPLIT_DUMPS= # this will keep track of split dumps that we'll tally later
 while [ $SLOT -lt $SLOTS ]; do
        SLOT=`expr $SLOT + 1`
        #
@@ -432,11 +439,21 @@ while [ $SLOT -lt $SLOTS ]; do
                # amrestore:   0: restoring sundae._mnt_sol1_usr.19961127.1
                if [ X"$FILE" != X"" -a X"$RESULT" = X"0" ]; then
                        report "Checked $FILE"
+               elif [ X"$FILE" != X"" -a X"$RESULT" = X"500" ]; then
+                       report "Skipped `cat $TEMP/onefile.cmd` check on partial dump $FILE"
+                       dump="`echo $FILE | cut -d'.' -f'1,2,3,4'`"
+                       cat $TEMP/onefile.partnum >> $TEMP/$dump.parts
+                       if [ X"`echo $SPLIT_DUMPS | grep $dump`" = X"" ]; then
+                           SPLIT_DUMPS="$dump $SPLIT_DUMPS"
+                       fi
                elif [ X"$FILE" != X"" -a X"$RESULT" = X"999" ]; then
                        report "Skipped $FILE (`cat $TEMP/errors`)"
                elif [ -n "$EOF" ]; then
                        report "End-of-Tape detected."
                        break
+               elif [ -n "$EOI" ]; then
+                        report "End-of-Information detected."
+                        break
                else
                        report "** Error detected ($FILE)"
                        echo "$VOLUME ($FILE):" >>$DEFECTS
@@ -463,6 +480,8 @@ while [ $SLOT -lt $SLOTS ]; do
              $TEMP/amtape.out \
              $TEMP/amrestore.out \
              $TEMP/errors \
+             $TEMP/onefile.cmd \
+             $TEMP/onefile.partnum \
              $TEMP/onefile.errors
 done
 
@@ -470,6 +489,44 @@ done
        && $Echoe "Errors found: " \
        && cat $DEFECTS
 
+# Work out whether any split dumps we saw had all their parts
+for dump in $SPLIT_DUMPS;do
+    report ""
+    numparts=0
+    max=0
+    max_known=0
+    missing=0
+    # figure out 
+    for part in `cat $TEMP/$dump.parts`;do
+       cur="`echo $part | cut -d/ -f1`"
+       max="`echo $part | cut -d/ -f2`"
+       if [ $max != "UNKNOWN" ]; then
+           numparts=$max
+           max_known=1
+           break;
+       fi
+       if [ $cur -gt $numparts ]; then
+           numparts=$cur
+       fi
+    done
+    report "Split dump $dump should have $numparts total pieces"
+    if [ $max_known != 1 ]; then
+       report "NOTE: Header field for total pieces was UNKNOWN, $numparts is best guess"
+    fi
+    part=1
+    while [ $part -lt $numparts ];do
+       part=`expr $part + 1`
+       if [ X"`grep \"^$part/\" $TEMP/$dump.parts`" = X"" ];then
+           report "Spanning chunk part $part is missing!"
+           missing=`expr $missing + 1`
+       fi
+    done
+    if [ $missing = 0 ];then
+       report "All parts found"        
+    fi
+    rm -f $TEMP/$dump.parts
+done
+
 sendreport
 
 exit 0
index 9a0cff0c11b850aebba1883fcb9a7681a48c03bb..c4e2935a0a69a4942b991e00d9ea8a52356230d4 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: changer.c,v 1.14.4.6.4.1.2.3 2003/02/28 19:23:25 martinea Exp $
+ * $Id: changer.c,v 1.29 2006/01/14 04:37:19 paddy_s Exp $
  *
  * interface routines for tape changers
  */
 #include "amanda.h"
+#include "util.h"
 #include "conffile.h"
 #include "version.h"
 
@@ -146,8 +147,8 @@ char *inslotstr, **outslotstr, **devicename;
     int rc;
 
     rc = run_changer_command("-slot", inslotstr, outslotstr, &rest);
-    if(rc) return rc;
 
+    if(rc) return rc;
     if(*rest == '\0') return report_bad_resultstr();
 
     *devicename = newstralloc(*devicename, rest);
@@ -203,49 +204,25 @@ char **curslotstr;
 
 /* ---------------------------- */
 
-void changer_scan(user_init, user_slot)
-int (*user_init) P((int rc, int nslots, int backwards));
-int (*user_slot) P((int rc, char *slotstr, char *device));
-{
-    char *slotstr, *device = NULL, *curslotstr = NULL;
-    int nslots, checked, backwards, rc, done;
-
-    rc = changer_info(&nslots, &curslotstr, &backwards);
-    done = user_init(rc, nslots, backwards);
-    amfree(curslotstr);
-
-    slotstr = "current";
-    checked = 0;
-
-    while(!done && checked < nslots) {
-       rc = changer_loadslot(slotstr, &curslotstr, &device);
-       if(rc > 0)
-           done = user_slot(rc, curslotstr, device);
-       else if(!done)
-           done = user_slot(0,  curslotstr, device);
-       amfree(curslotstr);
-       amfree(device);
-
-       checked += 1;
-       slotstr = "next";
-    }
-}
-
 /* This function first uses searchlabel and changer_search, if
    the library is able to find a tape itself. If it is not, or if 
-   the tape could not be found, then the normal scan is done like 
-   in changer_scan.
+   the tape could not be found, then the normal scan is done.
+   See interface documentation in changer.h.
 */
-void changer_find(user_init, user_slot, searchlabel)
-int (*user_init) P((int rc, int nslots, int backwards));
-int (*user_slot) P((int rc, char *slotstr, char *device));
-char *searchlabel;
+void changer_find(user_data, user_init, user_slot, searchlabel)
+     void *user_data;
+     int (*user_init) P((void *user_data, int rc, int nslots, int backwards,
+                         int searchable));
+     int (*user_slot) P((void *user_data, int rc, char *slotstr,
+                         char *device));
+     char *searchlabel;
 {
     char *slotstr, *device = NULL, *curslotstr = NULL;
     int nslots, checked, backwards, rc, done, searchable;
 
     rc = changer_query(&nslots, &curslotstr, &backwards, &searchable);
-    done = user_init(rc, nslots, backwards);
+    done = user_init(user_data, rc, nslots, backwards, searchable);
     amfree(curslotstr);
    
     if (searchlabel != NULL)
@@ -260,7 +237,7 @@ char *searchlabel;
     if ((searchlabel!=NULL) && searchable && !done){
       rc=changer_search(searchlabel,&curslotstr,&device);
       if(rc == 0)
-        done = user_slot(rc,curslotstr,device);
+        done = user_slot(user_data, rc,curslotstr,device);
     }
  
     slotstr = "current";
@@ -269,9 +246,9 @@ char *searchlabel;
     while(!done && checked < nslots) {
        rc = changer_loadslot(slotstr, &curslotstr, &device);
        if(rc > 0)
-           done = user_slot(rc, curslotstr, device);
+           done = user_slot(user_data, rc, curslotstr, device);
        else if(!done)
-           done = user_slot(0,  curslotstr, device);
+           done = user_slot(user_data, 0,  curslotstr, device);
        amfree(curslotstr);
        amfree(device);
 
@@ -282,22 +259,23 @@ char *searchlabel;
 
 /* ---------------------------- */
 
-void changer_current(user_init, user_slot)
-int (*user_init) P((int rc, int nslots, int backwards));
-int (*user_slot) P((int rc, char *slotstr, char *device));
+void changer_current(user_data, user_init, user_slot)
+     void *user_data;
+int (*user_init) P((void *ud, int rc, int nslots, int backwards, int searchable));
+int (*user_slot) P((void *ud, int rc, char *slotstr, char *device));
 {
     char *device = NULL, *curslotstr = NULL;
-    int nslots, backwards, rc, done;
+    int nslots, backwards, rc, done, searchable;
 
-    rc = changer_info(&nslots, &curslotstr, &backwards);
-    done = user_init(rc, nslots, backwards);
+    rc = changer_query(&nslots, &curslotstr, &backwards, &searchable);
+    done = user_init(user_data, rc, nslots, backwards, searchable);
     amfree(curslotstr);
 
     rc = changer_loadslot("current", &curslotstr, &device);
     if(rc > 0) {
-       done = user_slot(rc, curslotstr, device);
+       done = user_slot(user_data, rc, curslotstr, device);
     } else if(!done) {
-       done = user_slot(0,  curslotstr, device);
+       done = user_slot(user_data, 0,  curslotstr, device);
     }
     amfree(curslotstr);
     amfree(device);
@@ -315,7 +293,7 @@ static int changer_command(cmd, arg)
     char num1[NUM_STR_SIZE];
     char num2[NUM_STR_SIZE];
     char *cmdstr;
-    pid_t pid, changer_pid;
+    pid_t pid, changer_pid = 0;
 
     if (*tapechanger != '/') {
        tapechanger = vstralloc(libexecdir, "/", tapechanger, versionsuffix(),
@@ -345,8 +323,8 @@ static int changer_command(cmd, arg)
        goto failed;
     }
     if(fd[0] < 0 || fd[0] >= FD_SETSIZE) {
-       ap_snprintf(num1, sizeof(num1), "%d", fd[0]);
-       ap_snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1);
+       snprintf(num1, sizeof(num1), "%d", fd[0]);
+       snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1);
        changer_resultstr = vstralloc ("<error> ",
                                       "could not create pipe for \"",
                                       cmdstr,
@@ -361,8 +339,8 @@ static int changer_command(cmd, arg)
        goto done;
     }
     if(fd[1] < 0 || fd[1] >= FD_SETSIZE) {
-       ap_snprintf(num1, sizeof(num1), "%d", fd[1]);
-       ap_snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1);
+       snprintf(num1, sizeof(num1), "%d", fd[1]);
+       snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1);
        changer_resultstr = vstralloc ("<error> ",
                                       "could not create pipe for \"",
                                       cmdstr,
@@ -395,7 +373,7 @@ static int changer_command(cmd, arg)
                                           "\": ",
                                           strerror(errno),
                                           NULL);
-           (void)write(fd[1], changer_resultstr, strlen(changer_resultstr));
+           (void)fullwrite(fd[1], changer_resultstr, strlen(changer_resultstr));
            exit(1);
        }
        aclose(fd[0]);
@@ -407,7 +385,7 @@ static int changer_command(cmd, arg)
                                           "\": ",
                                           strerror(errno),
                                           NULL);
-           (void)write(2, changer_resultstr, strlen(changer_resultstr));
+           (void)fullwrite(2, changer_resultstr, strlen(changer_resultstr));
            exit(1);
        }
        if(arg) {
@@ -421,7 +399,7 @@ static int changer_command(cmd, arg)
                                       "\": ",
                                       strerror(errno),
                                       NULL);
-       (void)write(2, changer_resultstr, strlen(changer_resultstr));
+       (void)fullwrite(2, changer_resultstr, strlen(changer_resultstr));
        exit(1);
     default:
        aclose(fd[1]);
@@ -451,7 +429,7 @@ static int changer_command(cmd, arg)
                goto done;
            }
        } else if (pid != changer_pid) {
-           ap_snprintf(num1, sizeof(num1), "%ld", (long)pid);
+           snprintf(num1, sizeof(num1), "%ld", (long)pid);
            changer_resultstr = vstralloc ("<error> ",
                                           "wait for \"",
                                           tapechanger,
@@ -467,7 +445,7 @@ static int changer_command(cmd, arg)
 
     /* mark out-of-control changers as fatal error */
     if(WIFSIGNALED(wait_exitcode)) {
-       ap_snprintf(num1, sizeof(num1), "%d", WTERMSIG(wait_exitcode));
+       snprintf(num1, sizeof(num1), "%d", WTERMSIG(wait_exitcode));
        changer_resultstr = newvstralloc (changer_resultstr,
                                          "<error> ",
                                          changer_resultstr,
index 09d9ee9eeccca8bbd56bae19624e0154e83e0401..19734080b84abaf0adca71b3d1cd68ebd78015ef 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: changer.h,v 1.6.4.3 1999/09/08 23:27:53 jrj Exp $
+ * $Id: changer.h,v 1.12 2005/12/21 19:07:50 paddy_s Exp $
  *
  * interface routines for tape changers
  */
@@ -43,10 +43,55 @@ int changer_query P((int *nslotsp, char **curslotstr, int *backwards,
                     int *searchable));
 int changer_search P((char *searchlabel, char **outslotstr, char **devicename));
 int changer_loadslot P((char *inslotstr, char **outslotstr, char **devicename));
-void changer_current P((int (*user_init)(int rc, int nslots, int backwards),
-                    int (*user_slot)(int rc, char *slotstr, char *device)));
-void changer_scan P((int (*user_init)(int rc, int nslots, int backwards),
-                    int (*user_slot)(int rc, char *slotstr, char *device)));
-void changer_find P((int (*user_init)(int rc, int nslots, int backwards),
-                    int (*user_slot)(int rc, char *slotstr, char *device),
+void changer_current P((void *user_data,
+                        int (*user_init)(void *user_data,
+                                         int rc, int nslots, int backwards,
+                                         int searchable),
+                    int (*user_slot)(void *user_data,
+                                      int rc, char *slotstr, char *device)));
+
+
+/* USAGE: changer_find(user_data, init_fxn, slot_fxn, searchlabel)
+ *
+ * Searches the changer. If searchlabel is not NULL, and the changer has
+ * barcode support, then changer_find will load that tape
+ * first. Otherwise, changer_find will search through the tape drive
+ * one by one until user_slot() returns nonzero.
+ *
+ * Parameters: user_data: A pointer which is not interpreted by
+ *                        changer_find, but passed back to the
+ *                        callback functions user_data and user_slot.
+ *                        You can use this structure instead of
+ *                        globals.
+ *             user_init: This function is called right away. Its
+ *                        arguments are:
+ *                        user_data: (as above)
+ *                        rc:     The results of the changer -info
+ *                                command.
+ *                        nslots: The number of slots in the changer.
+ *                        backwards: Whether this changer can go
+ *                                backwards or not. Some changers
+ *                                can only search in one direction,
+ *                                and then the operator must reload
+ *                                the tapes.
+ *                        searchable: Whether this changer has a
+ *                                barcode reader or similar device.
+ *             user_slot: This function is called for every slot.
+ *                        Searching stops when it returns
+ *                        nonzero. Arguments are:
+ *                        user_data: (as above)
+ *                        rc:     The results of the changer -slot
+ *                                command.
+ *                        slotstr: The slot which was loaded
+ *                        device: The tape device to use to read this slot.
+ */
+
+
+
+void changer_find P((void *user_data,
+                     int (*user_init)(void *user_data, int rc,
+                                      int nslots, int backwards,
+                                      int searchable),
+                    int (*user_slot)(void *user_data, int rc,
+                                      char *slotstr, char *device),
                      char *searchlabel));
diff --git a/server-src/chunker.c b/server-src/chunker.c
new file mode 100644 (file)
index 0000000..fc783ba
--- /dev/null
@@ -0,0 +1,826 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-1999 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/* $Id: chunker.c,v 1.25 2006/03/21 13:23:35 martinea Exp $
+ *
+ * requests remote amandad processes to dump filesystems
+ */
+#include "amanda.h"
+#include "arglist.h"
+#include "clock.h"
+#include "conffile.h"
+#include "event.h"
+#include "logfile.h"
+#include "packet.h"
+#include "protocol.h"
+#include "security.h"
+#include "stream.h"
+#include "token.h"
+#include "version.h"
+#include "fileheader.h"
+#include "amfeatures.h"
+#include "server_util.h"
+#include "util.h"
+#include "holding.h"
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#define CONNECT_TIMEOUT        5*60
+
+#define STARTUP_TIMEOUT 60
+
+struct databuf {
+    int fd;                    /* file to flush to */
+    char *filename;            /* name of what fd points to */
+    int filename_seq;          /* for chunking */
+    long split_size;           /* when to chunk */
+    long chunk_size;           /* size of each chunk */
+    long use;                  /* size to use on this disk */
+    char buf[DISK_BLOCK_BYTES];
+    char *datain;              /* data buffer markers */
+    char *dataout;
+    char *datalimit;
+};
+
+static char *handle = NULL;
+
+static char *errstr = NULL;
+static int abort_pending;
+static long dumpsize, headersize;
+static long dumpbytes;
+static long filesize;
+
+static char *hostname = NULL;
+static char *diskname = NULL;
+static char *options = NULL;
+static char *progname = NULL;
+static int level;
+static char *dumpdate = NULL;
+static char *datestamp;
+static int command_in_transit;
+
+static dumpfile_t file;
+
+/* local functions */
+int main P((int, char **));
+static int write_tapeheader P((int, dumpfile_t *));
+static void databuf_init P((struct databuf *, int, char *, long, long));
+static int databuf_flush P((struct databuf *));
+
+static int startup_chunker P((char *, long, long, struct databuf *));
+static int do_chunk P((int, struct databuf *));
+
+
+int
+main(main_argc, main_argv)
+    int main_argc;
+    char **main_argv;
+{
+    static struct databuf db;
+    struct cmdargs cmdargs;
+    cmd_t cmd;
+    int infd;
+    unsigned long malloc_hist_1, malloc_size_1;
+    unsigned long malloc_hist_2, malloc_size_2;
+    char *conffile;
+    char *q = NULL;
+    char *filename;
+    long chunksize, use;
+    times_t runtime;
+    am_feature_t *their_features = NULL;
+    int a;
+
+    safe_fd(-1, 0);
+
+    set_pname("chunker");
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    malloc_size_1 = malloc_inuse(&malloc_hist_1);
+
+    erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE);
+    set_logerror(logerror);
+
+    if (main_argc > 1) {
+       config_name = stralloc(main_argv[1]);
+       config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
+    } else {
+       char my_cwd[STR_SIZE];
+
+       if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) {
+           error("cannot determine current working directory");
+       }
+       config_dir = stralloc2(my_cwd, "/");
+       if ((config_name = strrchr(my_cwd, '/')) != NULL) {
+           config_name = stralloc(config_name + 1);
+       }
+    }
+
+    safe_cd();
+
+    conffile = stralloc2(config_dir, CONFFILE_NAME);
+    if(read_conffile(conffile)) {
+       error("errors processing config file \"%s\"", conffile);
+    }
+    amfree(conffile);
+
+    fprintf(stderr,
+           "%s: pid %ld executable %s version %s\n",
+           get_pname(), (long) getpid(),
+           main_argv[0], version());
+    fflush(stderr);
+
+    /* now, make sure we are a valid user */
+
+    if (getpwuid(getuid()) == NULL)
+       error("can't get login name for my uid %ld", (long)getuid());
+
+    signal(SIGPIPE, SIG_IGN);
+    signal(SIGCHLD, SIG_IGN);
+
+    datestamp = construct_datestamp(NULL);
+
+/*    do {*/
+       cmd = getcmd(&cmdargs);
+
+       switch(cmd) {
+       case QUIT:
+           break;
+
+       case PORT_WRITE:
+           /*
+            * PORT-WRITE
+            *   handle
+            *   filename
+            *   host
+            *   features
+            *   disk
+            *   level
+            *   dumpdate
+            *   chunksize
+            *   progname
+            *   use
+            *   options
+            */
+           cmdargs.argc++;                     /* true count of args */
+           a = 2;
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: handle]");
+           }
+           handle = newstralloc(handle, cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: filename]");
+           }
+           filename = cmdargs.argv[a++];
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: hostname]");
+           }
+           hostname = newstralloc(hostname, cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: features]");
+           }
+           am_release_feature_set(their_features);
+           their_features = am_string_to_feature(cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: diskname]");
+           }
+           diskname = newstralloc(diskname, cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: level]");
+           }
+           level = atoi(cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: dumpdate]");
+           }
+           dumpdate = newstralloc(dumpdate, cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: chunksize]");
+           }
+           chunksize = atoi(cmdargs.argv[a++]);
+           chunksize = am_floor(chunksize, DISK_BLOCK_KB);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: progname]");
+           }
+           progname = newstralloc(progname, cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: use]");
+           }
+           use = am_floor(atoi(cmdargs.argv[a++]), DISK_BLOCK_KB);
+
+           if(a >= cmdargs.argc) {
+               error("error [chunker PORT-WRITE: not enough args: options]");
+           }
+           options = newstralloc(options, cmdargs.argv[a++]);
+
+           if(a != cmdargs.argc) {
+               error("error [chunker PORT-WRITE: too many args: %d != %d]",
+                     cmdargs.argc, a);
+           }
+
+           if((infd = startup_chunker(filename, use, chunksize, &db)) < 0) {
+               q = squotef("[chunker startup failed: %s]", errstr);
+               putresult(TRYAGAIN, "%s %s\n", handle, q);
+               error("startup_chunker failed");
+           }
+           command_in_transit = -1;
+           if(infd >= 0 && do_chunk(infd, &db)) {
+               char kb_str[NUM_STR_SIZE];
+               char kps_str[NUM_STR_SIZE];
+               double rt;
+
+               runtime = stopclock();
+               rt = runtime.r.tv_sec+runtime.r.tv_usec/1000000.0;
+               snprintf(kb_str, sizeof(kb_str), "%ld", dumpsize - headersize);
+               snprintf(kps_str, sizeof(kps_str), "%3.1f",
+                               rt ? dumpsize / rt : 0.0);
+               errstr = newvstralloc(errstr,
+                                     "sec ", walltime_str(runtime),
+                                     " kb ", kb_str,
+                                     " kps ", kps_str,
+                                     NULL);
+               q = squotef("[%s]", errstr);
+               if(command_in_transit != -1)
+                   cmd = command_in_transit;
+               else
+                   cmd = getcmd(&cmdargs);
+               switch(cmd) {
+               case DONE:
+                   putresult(DONE, "%s %ld %s\n",
+                             handle, dumpsize - headersize, q);
+                   log_add(L_SUCCESS, "%s %s %s %d [%s]",
+                           hostname, diskname, datestamp, level, errstr);
+                   break;
+               case BOGUS:
+               case TRYAGAIN:
+               case FAILED:
+               case ABORT_FINISHED:
+                   if(dumpsize > DISK_BLOCK_KB) {
+                       putresult(PARTIAL, "%s %ld %s\n",
+                                 handle, dumpsize - headersize, q);
+                       log_add(L_PARTIAL, "%s %s %s %d [%s]",
+                               hostname, diskname, datestamp, level, errstr);
+                   }
+                   else {
+                       errstr = newvstralloc(errstr,
+                                             "dumper returned ",
+                                             cmdstr[cmd],
+                                             NULL);
+                       amfree(q);
+                       q = squotef("[%s]",errstr);
+                       putresult(FAILED, "%s %s\n", handle, q);
+                       log_add(L_FAIL, "%s %s %s %d [%s]",
+                               hostname, diskname, datestamp, level, errstr);
+                   }
+               default: break;
+               }
+               amfree(q);
+           } else if(infd != -2) {
+               if(!abort_pending) {
+                   if(q == NULL) {
+                       q = squotef("[%s]", errstr);
+                   }
+                   putresult(FAILED, "%s %s\n", handle, q);
+                   log_add(L_FAIL, "%s %s %s %d [%s]",
+                           hostname, diskname, datestamp, level, errstr);
+                   amfree(q);
+               }
+           }
+           break;
+
+       default:
+           if(cmdargs.argc >= 1) {
+               q = squote(cmdargs.argv[1]);
+           } else if(cmdargs.argc >= 0) {
+               q = squote(cmdargs.argv[0]);
+           } else {
+               q = stralloc("(no input?)");
+           }
+           putresult(BAD_COMMAND, "%s\n", q);
+           amfree(q);
+           break;
+       }
+
+/*    } while(cmd != QUIT); */
+
+    amfree(errstr);
+    amfree(datestamp);
+    amfree(handle);
+    amfree(hostname);
+    amfree(diskname);
+    amfree(dumpdate);
+    amfree(progname);
+    amfree(options);
+    amfree(config_dir);
+    amfree(config_name);
+    am_release_feature_set(their_features);
+    their_features = NULL;
+
+    malloc_size_2 = malloc_inuse(&malloc_hist_2);
+
+    if (malloc_size_1 != malloc_size_2)
+       malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
+
+    exit(0);
+}
+
+/*
+ * Returns a file descriptor to the incoming port
+ * on success, or -1 on error.
+ */
+static int
+startup_chunker(filename, use, chunksize, db)
+    char *filename;
+    long use;
+    long chunksize;
+    struct databuf *db;
+{
+    int infd, outfd;
+    char *tmp_filename, *pc;
+    int data_port, data_socket;
+
+    data_port = 0;
+    data_socket = stream_server(&data_port, -1, STREAM_BUFSIZE);
+
+    if(data_socket < 0) {
+       errstr = stralloc2("error creating stream server: ", strerror(errno));
+       return -1;
+    }
+
+    putresult(PORT, "%d\n", data_port);
+
+    infd = stream_accept(data_socket, CONNECT_TIMEOUT, -1, NETWORK_BLOCK_BYTES);
+    if(infd == -1) {
+       errstr = stralloc2("error accepting stream: ", strerror(errno));
+       return -1;
+    }
+
+    tmp_filename = vstralloc(filename, ".tmp", NULL);
+    pc = strrchr(tmp_filename, '/');
+    *pc = '\0';
+    mkholdingdir(tmp_filename);
+    *pc = '/';
+    if ((outfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) {
+       int save_errno = errno;
+
+       errstr = squotef("holding file \"%s\": %s",
+                        tmp_filename,
+                        strerror(errno));
+       amfree(tmp_filename);
+       aclose(infd);
+       if(save_errno == ENOSPC) {
+           putresult(NO_ROOM, "%s %lu", handle, use);
+           return -2;
+       } else {
+           return -1;
+       }
+    }
+    amfree(tmp_filename);
+    databuf_init(db, outfd, filename, use, chunksize);
+    db->filename_seq++;
+    return infd;
+}
+
+static int
+do_chunk(infd, db)
+    int infd;
+    struct databuf *db;
+{
+    int nread;
+    char header_buf[DISK_BLOCK_BYTES];
+
+    startclock();
+
+    dumpsize = headersize = dumpbytes = filesize = 0;
+
+    /*
+     * The first thing we should receive is the file header, which we
+     * need to save into "file", as well as write out.  Later, the
+     * chunk code will rewrite it.
+     */
+    nread = fullread(infd, header_buf, sizeof(header_buf));
+    if (nread != DISK_BLOCK_BYTES) {
+       char number1[NUM_STR_SIZE];
+       char number2[NUM_STR_SIZE];
+
+       if(nread < 0) {
+           errstr = stralloc2("cannot read header: ", strerror(errno));
+       } else {
+           snprintf(number1, sizeof(number1), "%d", nread);
+           snprintf(number2, sizeof(number2), "%d", DISK_BLOCK_BYTES);
+           errstr = vstralloc("cannot read header: got ",
+                              number1,
+                              " instead of ",
+                              number2,
+                              NULL);
+       }
+       return 0;
+    }
+    parse_file_header(header_buf, &file, nread);
+    if(write_tapeheader(db->fd, &file)) {
+       int save_errno = errno;
+
+       errstr = squotef("write_tapeheader file \"%s\": %s",
+                        db->filename, strerror(errno));
+       if(save_errno == ENOSPC) {
+           putresult(NO_ROOM, "%s %lu\n", handle, 
+                     db->use+db->split_size-dumpsize);
+       }
+       return 0;
+    }
+    dumpsize += DISK_BLOCK_KB;
+    filesize = DISK_BLOCK_KB;
+    headersize += DISK_BLOCK_KB;
+
+    /*
+     * We've written the file header.  Now, just write data until the
+     * end.
+     */
+    while ((nread = fullread(infd, db->buf, db->datalimit - db->datain)) > 0) {
+       db->datain += nread;
+       while(db->dataout < db->datain) {
+           if(!databuf_flush(db)) {
+               return 0;
+           }
+       }
+    }
+    while(db->dataout < db->datain) {
+       if(!databuf_flush(db)) {
+           return 0;
+       }
+    }
+    if(dumpbytes > 0) {
+       dumpsize++;                     /* count partial final KByte */
+       filesize++;
+    }
+    return 1;
+}
+
+/*
+ * Initialize a databuf.  Takes a writeable file descriptor.
+ */
+static void
+databuf_init(db, fd, filename, use, chunk_size)
+    struct databuf *db;
+    int fd;
+    char *filename;
+    long use;
+    long chunk_size;
+{
+    db->fd = fd;
+    db->filename = stralloc(filename);
+    db->filename_seq = 0;
+    db->chunk_size = chunk_size;
+    db->split_size = (db->chunk_size > use) ? use : db->chunk_size;
+    db->use = (use>db->split_size) ? use - db->split_size : 0;
+    db->datain = db->dataout = db->buf;
+    db->datalimit = db->buf + sizeof(db->buf);
+}
+
+
+/*
+ * Write out the buffer to the backing file
+ */
+static int
+databuf_flush(db)
+    struct databuf *db;
+{
+    struct cmdargs cmdargs;
+    int rc = 1;
+    int written;
+    long left_in_chunk;
+    char *arg_filename = NULL;
+    char *new_filename = NULL;
+    char *tmp_filename = NULL;
+    char sequence[NUM_STR_SIZE];
+    int newfd;
+    filetype_t save_type;
+    char *q;
+    int a;
+    char *pc;
+
+    /*
+     * If there's no data, do nothing.
+     */
+    if (db->dataout >= db->datain) {
+       goto common_exit;
+    }
+
+    /*
+     * See if we need to split this file.
+     */
+    while (db->split_size > 0 && dumpsize >= db->split_size) {
+       if( db->use == 0 ) {
+           /*
+            * Probably no more space on this disk.  Request some more.
+            */
+           cmd_t cmd;
+
+           putresult(RQ_MORE_DISK, "%s\n", handle);
+           cmd = getcmd(&cmdargs);
+           if(command_in_transit == -1 &&
+              (cmd == DONE || cmd == TRYAGAIN || cmd == FAILED)) {
+               command_in_transit = cmd;
+               cmd = getcmd(&cmdargs);
+           }
+           if(cmd == CONTINUE) {
+               /*
+                * CONTINUE
+                *   serial
+                *   filename
+                *   chunksize
+                *   use
+                */
+               cmdargs.argc++;                 /* true count of args */
+               a = 3;
+
+               if(a >= cmdargs.argc) {
+                   error("error [chunker CONTINUE: not enough args: filename]");
+               }
+               arg_filename = newstralloc(arg_filename, cmdargs.argv[a++]);
+
+               if(a >= cmdargs.argc) {
+                   error("error [chunker CONTINUE: not enough args: chunksize]");
+               }
+               db->chunk_size = atoi(cmdargs.argv[a++]);
+               db->chunk_size = am_floor(db->chunk_size, DISK_BLOCK_KB);
+
+               if(a >= cmdargs.argc) {
+                   error("error [chunker CONTINUE: not enough args: use]");
+               }
+               db->use = atoi(cmdargs.argv[a++]);
+
+               if(a != cmdargs.argc) {
+                   error("error [chunker CONTINUE: too many args: %d != %d]",
+                         cmdargs.argc, a);
+               }
+
+               if(strcmp(db->filename, arg_filename) == 0) {
+                   /*
+                    * Same disk, so use what room is left up to the
+                    * next chunk boundary or the amount we were given,
+                    * whichever is less.
+                    */
+                   left_in_chunk = db->chunk_size - filesize;
+                   if(left_in_chunk > db->use) {
+                       db->split_size += db->use;
+                       db->use = 0;
+                   } else {
+                       db->split_size += left_in_chunk;
+                       db->use -= left_in_chunk;
+                   }
+                   if(left_in_chunk > 0) {
+                       /*
+                        * We still have space in this chunk.
+                        */
+                       break;
+                   }
+               } else {
+                   /*
+                    * Different disk, so use new file.
+                    */
+                   db->filename = newstralloc(db->filename, arg_filename);
+               }
+           } else if(cmd == ABORT) {
+               abort_pending = 1;
+               errstr = newstralloc(errstr, "ERROR");
+               putresult(ABORT_FINISHED, "%s\n", handle);
+               rc = 0;
+               goto common_exit;
+           } else {
+               if(cmdargs.argc >= 1) {
+                   q = squote(cmdargs.argv[1]);
+               } else if(cmdargs.argc >= 0) {
+                   q = squote(cmdargs.argv[0]);
+               } else {
+                   q = stralloc("(no input?)");
+               }
+               error("error [bad command after RQ-MORE-DISK: \"%s\"]", q);
+           }
+       }
+
+       /*
+        * Time to use another file.
+        */
+
+       /*
+        * First, open the new chunk file, and give it a new header
+        * that has no cont_filename pointer.
+        */
+       snprintf(sequence, sizeof(sequence), "%d", db->filename_seq);
+       new_filename = newvstralloc(new_filename,
+                                   db->filename,
+                                   ".",
+                                   sequence,
+                                   NULL);
+       tmp_filename = newvstralloc(tmp_filename,
+                                   new_filename,
+                                   ".tmp",
+                                   NULL);
+       pc = strrchr(tmp_filename, '/');
+       *pc = '\0';
+       mkholdingdir(tmp_filename);
+       *pc = '/';
+       newfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+       if (newfd == -1) {
+           int save_errno = errno;
+
+           if(save_errno == ENOSPC) {
+               putresult(NO_ROOM, "%s %lu\n",
+                         handle, 
+                         db->use+db->split_size-dumpsize);
+               db->use = 0;                    /* force RQ_MORE_DISK */
+               db->split_size = dumpsize;
+               continue;
+           }
+           errstr = squotef("creating chunk holding file \"%s\": %s",
+                            tmp_filename,
+                            strerror(errno));
+           aclose(db->fd);
+           rc = 0;
+           goto common_exit;
+       }
+       save_type = file.type;
+       file.type = F_CONT_DUMPFILE;
+       file.cont_filename[0] = '\0';
+       if(write_tapeheader(newfd, &file)) {
+           int save_errno = errno;
+
+           aclose(newfd);
+           if(save_errno == ENOSPC) {
+               putresult(NO_ROOM, "%s %lu\n",
+                         handle, 
+                         db->use+db->split_size-dumpsize);
+               db->use = 0;                    /* force RQ_MORE DISK */
+               db->split_size = dumpsize;
+               continue;
+           }
+           errstr = squotef("write_tapeheader file \"%s\": %s",
+                            tmp_filename,
+                            strerror(errno));
+           rc = 0;
+           goto common_exit;
+       }
+
+       /*
+        * Now, update the header of the current file to point
+        * to the next chunk, and then close it.
+        */
+       if (lseek(db->fd, (off_t)0, SEEK_SET) < 0) {
+           errstr = squotef("lseek holding file \"%s\": %s",
+                            db->filename,
+                            strerror(errno));
+           aclose(newfd);
+           rc = 0;
+           goto common_exit;
+       }
+
+       file.type = save_type;
+       strncpy(file.cont_filename, new_filename, sizeof(file.cont_filename));
+       file.cont_filename[sizeof(file.cont_filename)] = '\0';
+       if(write_tapeheader(db->fd, &file)) {
+           errstr = squotef("write_tapeheader file \"%s\": %s",
+                            db->filename,
+                            strerror(errno));
+           aclose(newfd);
+           unlink(tmp_filename);
+           rc = 0;
+           goto common_exit;
+       }
+       file.type = F_CONT_DUMPFILE;
+
+       /*
+        * Now shift the file descriptor.
+        */
+       aclose(db->fd);
+       db->fd = newfd;
+       newfd = -1;
+
+       /*
+        * Update when we need to chunk again
+        */
+       if(db->use <= DISK_BLOCK_KB) {
+           /*
+            * Cheat and use one more block than allowed so we can make
+            * some progress.
+            */
+           db->split_size += 2 * DISK_BLOCK_KB;
+           db->use = 0;
+       } else if(db->chunk_size > db->use) {
+           db->split_size += db->use;
+           db->use = 0;
+       } else {
+           db->split_size += db->chunk_size;
+           db->use -= db->chunk_size;
+       }
+
+
+       amfree(tmp_filename);
+       amfree(new_filename);
+       dumpsize += DISK_BLOCK_KB;
+       filesize = DISK_BLOCK_KB;
+       headersize += DISK_BLOCK_KB;
+       db->filename_seq++;
+    }
+
+    /*
+     * Write out the buffer
+     */
+    written = fullwrite(db->fd, db->dataout, db->datain - db->dataout);
+    if (written > 0) {
+       db->dataout += written;
+       dumpbytes += written;
+    }
+    dumpsize += (dumpbytes / 1024);
+    filesize += (dumpbytes / 1024);
+    dumpbytes %= 1024;
+    if (written < 0) {
+       if (errno != ENOSPC) {
+           errstr = squotef("data write: %s", strerror(errno));
+           rc = 0;
+           goto common_exit;
+       }
+
+       /*
+        * NO-ROOM is informational only.  Later, RQ_MORE_DISK will be
+        * issued to use another holding disk.
+        */
+       putresult(NO_ROOM, "%s %lu\n", handle, db->use+db->split_size-dumpsize);
+       db->use = 0;                            /* force RQ_MORE_DISK */
+       db->split_size = dumpsize;
+       goto common_exit;
+    }
+    if (db->datain == db->dataout) {
+       /*
+        * We flushed the whole buffer so reset to use it all.
+        */
+       db->datain = db->dataout = db->buf;
+    }
+
+common_exit:
+
+    amfree(new_filename);
+    amfree(tmp_filename);
+    amfree(arg_filename);
+    return rc;
+}
+
+
+/*
+ * Send an Amanda dump header to the output file.
+ */
+static int
+write_tapeheader(outfd, file)
+    int outfd;
+    dumpfile_t *file;
+{
+    char buffer[DISK_BLOCK_BYTES];
+    int written;
+
+    file->blocksize = DISK_BLOCK_BYTES;
+    build_header(buffer, file, sizeof(buffer));
+
+    written = fullwrite(outfd, buffer, sizeof(buffer));
+    if(written == sizeof(buffer)) return 0;
+    if(written < 0) return written;
+    errno = ENOSPC;
+    return -1;
+}
index f921c39f591616390477bb0bcaa4a91f0b8a1c9e..f80137263e7113ce14f64f53eeacce33b2efb846 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: conffile.c,v 1.54.2.16.2.5.2.20.2.10 2005/09/30 19:13:36 martinea Exp $
+ * $Id: conffile.c,v 1.127 2006/03/15 16:26:13 martinea Exp $
  *
  * read configuration file
  */
 
 /* internal types and variables */
 
-/*
- * XXX - this is used by the krb4 stuff.
- * Hopefully nobody will need this here.  (not very likely).  -kovert
- */
-#if defined(INTERFACE)
-#  undef INTERFACE
-#endif
-
 typedef enum {
     UNKNOWN, ANY, COMMA, LBRACE, RBRACE, NL, END,
-    IDENT, INT, LONG, BOOL, REAL, STRING, TIME,
+    IDENT, INT, LONG, AM64, BOOL, REAL, STRING, TIME,
 
     /* config parameters */
     INCLUDEFILE,
@@ -79,19 +71,25 @@ typedef enum {
     PRINTER, AUTOFLUSH, RESERVE, MAXDUMPSIZE,
     COLUMNSPEC, 
     AMRECOVER_DO_FSF, AMRECOVER_CHECK_LABEL, AMRECOVER_CHANGER,
+    LABEL_NEW_TAPES,
 
     TAPERALGO, FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST, LAST,
     DISPLAYUNIT,
 
+    /* kerberos 5 */
+    KRB5KEYTAB, KRB5PRINCIPAL, 
+
     /* holding disk */
     COMMENT, DIRECTORY, USE, CHUNKSIZE,
 
     /* dump type */
     /*COMMENT,*/ PROGRAM, DUMPCYCLE, RUNSPERCYCLE, MAXCYCLE, MAXDUMPS,
     OPTIONS, PRIORITY, FREQUENCY, INDEX, MAXPROMOTEDAY,
-    STARTTIME, COMPRESS, AUTH, STRATEGY, ESTIMATE,
+    STARTTIME, COMPRESS, ENCRYPT, AUTH, STRATEGY, ESTIMATE,
     SKIP_INCR, SKIP_FULL, RECORD, HOLDING,
-    EXCLUDE, INCLUDE, KENCRYPT, IGNORE, COMPRATE,
+    EXCLUDE, INCLUDE, KENCRYPT, IGNORE, COMPRATE, TAPE_SPLITSIZE,
+    SPLIT_DISKBUFFER, FALLBACK_SPLITSIZE, SRVCOMPPROG, CLNTCOMPPROG,
+    SRV_ENCRYPT, CLNT_ENCRYPT, SRV_DECRYPT_OPT, CLNT_DECRYPT_OPT,
 
     /* tape type */
     /*COMMENT,*/ BLOCKSIZE, FILE_PAD, LBL_TEMPL, FILEMARK, LENGTH, SPEED,
@@ -102,15 +100,12 @@ typedef enum {
     /* dump options (obsolete) */
     EXCLUDE_FILE, EXCLUDE_LIST,
 
-    /* compress, estimate */
-    NONE, FAST, BEST, SERVER, CLIENT, CALCSIZE,
+    /* compress, estimate, encryption */
+    NONE, FAST, BEST, SERVER, CLIENT, CALCSIZE, CUSTOM,
 
     /* priority */
     LOW, MEDIUM, HIGH,
 
-    /* authentication */
-    KRB4_AUTH, BSD_AUTH,
-
     /* dump strategy */
     SKIP, STANDARD, NOFULL, NOINC, HANOI, INCRONLY,
 
@@ -136,6 +131,7 @@ keytab_t *keytable;
 typedef union {
     int i;
     long l;
+    am64_t am64;
     double r;
     char *s;
 } val_t;
@@ -148,12 +144,12 @@ ColumnInfo ColumnData[] = {
     { "Disk",       1, 11, 11, 0, "%-*.*s", "DISK" },
     { "Level",      1, 1,  1,  0, "%*.*d",  "L" },
     { "OrigKB",     1, 7,  0,  0, "%*.*f",  "ORIG-KB" },
-    { "OutKB",      0, 7,  0,  0, "%*.*f",  "OUT-KB" },
-    { "Compress",   0, 6,  1,  0, "%*.*f",  "COMP%" },
-    { "DumpTime",   0, 7,  7,  0, "%*.*s",  "MMM:SS" },
-    { "DumpRate",   0, 6,  1,  0, "%*.*f",  "KB/s" },
+    { "OutKB",      1, 7,  0,  0, "%*.*f",  "OUT-KB" },
+    { "Compress",   1, 6,  1,  0, "%*.*f",  "COMP%" },
+    { "DumpTime",   1, 7,  7,  0, "%*.*s",  "MMM:SS" },
+    { "DumpRate",   1, 6,  1,  0, "%*.*f",  "KB/s" },
     { "TapeTime",   1, 6,  6,  0, "%*.*s",  "MMM:SS" },
-    { "TapeRate",   0, 6,  1,  0, "%*.*f",  "KB/s" },
+    { "TapeRate",   1, 6,  1,  0, "%*.*f",  "KB/s" },
     { NULL,         0, 0,  0,  0, NULL,     NULL }
 };
 
@@ -216,6 +212,9 @@ static val_t conf_amrecover_do_fsf;
 static val_t conf_amrecover_check_label;
 static val_t conf_taperalgo;
 static val_t conf_displayunit;
+static val_t conf_krb5keytab;
+static val_t conf_krb5principal;
+static val_t conf_label_new_tapes;
 
 /* reals */
 static val_t conf_bumpmult;
@@ -274,6 +273,9 @@ static int seen_amrecover_check_label;
 static int seen_amrecover_changer;
 static int seen_taperalgo;
 static int seen_displayunit;
+static int seen_krb5keytab;
+static int seen_krb5principal;
+static int seen_label_new_tapes;
 
 static int allow_overwrites;
 static int token_pushed;
@@ -312,8 +314,8 @@ static void copy_interface P((void));
 static void get_dumpopts P((void));
 static void get_comprate P((void));
 static void get_compress P((void));
+static void get_encrypt P((void));
 static void get_priority P((void));
-static void get_auth P((void));
 static void get_strategy P((void));
 static void get_estimate P((void));
 static void get_exclude P((void));
@@ -322,7 +324,9 @@ static void get_taperalgo P((val_t *c_taperalgo, int *s_taperalgo));
 
 static void get_simple P((val_t *var, int *seen, tok_t type));
 static int get_time P((void));
-static long get_number P((void));
+static int get_int P((void));
+static long get_long P((void));
+static am64_t get_am64_t P((void));
 static int get_bool P((void));
 static void ckseen P((int *seen));
 static void parserror P((char *format, ...))
@@ -425,7 +429,10 @@ struct byname {
     { "DISPLAYUNIT", CNF_DISPLAYUNIT, STRING },
     { "AUTOFLUSH", CNF_AUTOFLUSH, BOOL },
     { "RESERVE", CNF_RESERVE, INT },
-    { "MAXDUMPSIZE", CNF_MAXDUMPSIZE, INT },
+    { "MAXDUMPSIZE", CNF_MAXDUMPSIZE, AM64 },
+    { "KRB5KEYTAB", CNF_KRB5KEYTAB, STRING },
+    { "KRB5PRINCIPAL", CNF_KRB5PRINCIPAL, STRING },
+    { "LABEL_NEW_TAPES", CNF_LABEL_NEW_TAPES, STRING },
     { NULL }
 };
 
@@ -441,7 +448,7 @@ char *str;
     tmpstr = stralloc(str);
     s = tmpstr;
     while((ch = *s++) != '\0') {
-       if(islower((int) ch)) s[-1] = toupper(ch);
+       if(islower((int)ch)) s[-1] = toupper(ch);
     }
 
     for(np = byname_table; np->name != NULL; np++)
@@ -450,7 +457,7 @@ char *str;
     if(np->name == NULL) return NULL;
 
     if(np->typ == INT) {
-       ap_snprintf(number, sizeof(number), "%d", getconf_int(np->parm));
+       snprintf(number, sizeof(number), "%d", getconf_int(np->parm));
        tmpstr = newstralloc(tmpstr, number);
     } else if(np->typ == BOOL) {
        if(getconf_int(np->parm) == 0) {
@@ -460,7 +467,7 @@ char *str;
            tmpstr = newstralloc(tmpstr, "on");
        }
     } else if(np->typ == REAL) {
-       ap_snprintf(number, sizeof(number), "%f", getconf_real(np->parm));
+       snprintf(number, sizeof(number), "%f", getconf_real(np->parm));
        tmpstr = newstralloc(tmpstr, number);
     } else {
        tmpstr = newstralloc(tmpstr, getconf_str(np->parm));
@@ -518,6 +525,9 @@ confparm_t parm;
     case CNF_AMRECOVER_CHANGER: return seen_amrecover_changer;
     case CNF_TAPERALGO: return seen_taperalgo;
     case CNF_DISPLAYUNIT: return seen_displayunit;
+    case CNF_KRB5KEYTAB: return seen_krb5keytab;
+    case CNF_KRB5PRINCIPAL: return seen_krb5principal;
+    case CNF_LABEL_NEW_TAPES: return seen_label_new_tapes;
     default: return 0;
     }
 }
@@ -547,7 +557,6 @@ confparm_t parm;
     case CNF_TAPEBUFS: r = conf_tapebufs.i; break;
     case CNF_AUTOFLUSH: r = conf_autoflush.i; break;
     case CNF_RESERVE: r = conf_reserve.i; break;
-    case CNF_MAXDUMPSIZE: r = conf_maxdumpsize.i; break;
     case CNF_AMRECOVER_DO_FSF: r = conf_amrecover_do_fsf.i; break;
     case CNF_AMRECOVER_CHECK_LABEL: r = conf_amrecover_check_label.i; break;
     case CNF_TAPERALGO: r = conf_taperalgo.i; break;
@@ -559,6 +568,21 @@ confparm_t parm;
     return r;
 }
 
+am64_t getconf_am64(parm)
+confparm_t parm;
+{
+    am64_t r = 0;
+
+    switch(parm) {
+    case CNF_MAXDUMPSIZE: r = conf_maxdumpsize.am64; break;
+
+    default:
+       error("error [unknown getconf_am64 parm: %d]", parm);
+       /* NOTREACHED */
+    }
+    return r;
+}
+
 double getconf_real(parm)
 confparm_t parm;
 {
@@ -604,6 +628,9 @@ confparm_t parm;
     case CNF_COLUMNSPEC: r = conf_columnspec.s; break;
     case CNF_AMRECOVER_CHANGER: r = conf_amrecover_changer.s; break;
     case CNF_DISPLAYUNIT: r = conf_displayunit.s; break;
+    case CNF_KRB5PRINCIPAL: r = conf_krb5principal.s; break;
+    case CNF_KRB5KEYTAB: r = conf_krb5keytab.s; break;
+    case CNF_LABEL_NEW_TAPES: r = conf_label_new_tapes.s; break;
 
     default:
        error("error [unknown getconf_str parm: %d]", parm);
@@ -724,6 +751,10 @@ static void init_defaults()
     conf_amrecover_changer.s = stralloc("");
     conf_printer.s = stralloc("");
     conf_displayunit.s = stralloc("k");
+    conf_label_new_tapes.s = stralloc("");
+
+    conf_krb5keytab.s = stralloc("/.amanda-v5-keytab");
+    conf_krb5principal.s = stralloc("service/amanda");
 
     conf_dumpcycle.i   = 10;
     conf_runspercycle.i        = 0;
@@ -744,9 +775,9 @@ static void init_defaults()
     conf_tapebufs.i     = 20;
     conf_autoflush.i   = 0;
     conf_reserve.i     = 100;
-    conf_maxdumpsize.i = -1;
-    conf_amrecover_do_fsf.i = 0;
-    conf_amrecover_check_label.i = 0;
+    conf_maxdumpsize.am64      = -1;
+    conf_amrecover_do_fsf.i = 1;
+    conf_amrecover_check_label.i = 1;
     conf_taperalgo.i = 0;
 
     /* defaults for internal variables */
@@ -796,6 +827,10 @@ static void init_defaults()
     seen_amrecover_changer = 0;
     seen_taperalgo = 0;
     seen_displayunit = 0;
+    seen_krb5keytab = 0;
+    seen_krb5principal = 0;
+    seen_label_new_tapes = 0;
+
     line_num = got_parserror = 0;
     allow_overwrites = 0;
     token_pushed = 0;
@@ -849,6 +884,11 @@ static void init_defaults()
     dpcur.compress = COMP_BEST; dpcur.s_compress = -1;
     save_dumptype();
 
+    init_dumptype_defaults();
+    dpcur.name = "COMPRESS-CUST"; dpcur.seen = -1;
+    dpcur.compress = COMP_CUST; dpcur.s_compress = -1;
+    save_dumptype();
+
     init_dumptype_defaults();
     dpcur.name = "SRVCOMPRESS"; dpcur.seen = -1;
     dpcur.compress = COMP_SERV_FAST; dpcur.s_compress = -1;
@@ -856,12 +896,14 @@ static void init_defaults()
 
     init_dumptype_defaults();
     dpcur.name = "BSD-AUTH"; dpcur.seen = -1;
-    dpcur.auth = AUTH_BSD; dpcur.s_auth = -1;
+    amfree(dpcur.security_driver);
+    dpcur.security_driver = stralloc("BSD"); dpcur.s_security_driver = -1;
     save_dumptype();
 
     init_dumptype_defaults();
     dpcur.name = "KRB4-AUTH"; dpcur.seen = -1;
-    dpcur.auth = AUTH_KRB4; dpcur.s_auth = -1;
+    amfree(dpcur.security_driver);
+    dpcur.security_driver = stralloc("KRB4"); dpcur.s_security_driver = -1;
     save_dumptype();
 
     init_dumptype_defaults();
@@ -975,6 +1017,9 @@ keytab_t main_keytable[] = {
     { "AMRECOVER_CHANGER", AMRECOVER_CHANGER },
     { "TAPERALGO", TAPERALGO },
     { "DISPLAYUNIT", DISPLAYUNIT },
+    { "KRB5KEYTAB", KRB5KEYTAB },
+    { "KRB5PRINCIPAL", KRB5PRINCIPAL },
+    { "LABEL_NEW_TAPES", LABEL_NEW_TAPES },
     { NULL, IDENT }
 };
 
@@ -1016,7 +1061,7 @@ static int read_confline()
                    }
                    break;
     case RUNTAPES:  get_simple(&conf_runtapes,  &seen_runtapes,  INT);
-                   if(conf_runtapes.i < 1) {
+                   if(conf_runtapes.i < 0) {
                        parserror("runtapes must be positive");
                    }
                    break;
@@ -1093,7 +1138,7 @@ static int read_confline()
                        parserror("reserve must be between 0 and 100");
                    }
                    break;
-    case MAXDUMPSIZE:get_simple(&conf_maxdumpsize,&seen_maxdumpsize,INT); break;
+    case MAXDUMPSIZE:get_simple(&conf_maxdumpsize,&seen_maxdumpsize,AM64); break;
     case COLUMNSPEC:get_simple(&conf_columnspec,&seen_columnspec,STRING); break;
 
     case AMRECOVER_DO_FSF: get_simple(&conf_amrecover_do_fsf,&seen_amrecover_do_fsf, BOOL); break;
@@ -1127,6 +1172,10 @@ static int read_confline()
                      }
                      break;
 
+    /* kerberos 5 bits.  only useful when kerberos 5 built in... */
+    case KRB5KEYTAB:    get_simple(&conf_krb5keytab,   &seen_krb5keytab,   STRING); break;
+    case KRB5PRINCIPAL: get_simple(&conf_krb5principal,&seen_krb5principal,STRING); break;
+
     case LOGFILE: /* XXX - historical */
        /* truncate the filename part and pretend he said "logdir" */
        {
@@ -1166,7 +1215,7 @@ static int read_confline()
        {
            int i;
 
-           i = get_number();
+           i = get_int();
            i = (i / DISK_BLOCK_KB) * DISK_BLOCK_KB;
 
            if(!seen_disksize) {
@@ -1191,6 +1240,9 @@ static int read_confline()
        else if(tok == INTERFACE) get_interface();
        else parserror("DUMPTYPE, INTERFACE or TAPETYPE expected");
        break;
+    case LABEL_NEW_TAPES:
+        get_simple(&conf_label_new_tapes, &seen_label_new_tapes, STRING);
+        break;
 
     case NL:   /* empty line */
        break;
@@ -1317,6 +1369,9 @@ keytab_t dumptype_keytable[] = {
     { "COMMENT", COMMENT },
     { "COMPRATE", COMPRATE },
     { "COMPRESS", COMPRESS },
+    { "ENCRYPT", ENCRYPT },
+    { "SERVER_DECRYPT_OPTION", SRV_DECRYPT_OPT },
+    { "CLIENT_DECRYPT_OPTION", CLNT_DECRYPT_OPT },
     { "DUMPCYCLE", DUMPCYCLE },
     { "EXCLUDE", EXCLUDE },
     { "FREQUENCY", FREQUENCY },        /* XXX - historical */
@@ -1336,7 +1391,14 @@ keytab_t dumptype_keytable[] = {
     { "SKIP-INCR", SKIP_INCR },
     { "STARTTIME", STARTTIME },
     { "STRATEGY", STRATEGY },
+    { "TAPE_SPLITSIZE", TAPE_SPLITSIZE },
+    { "SPLIT_DISKBUFFER", SPLIT_DISKBUFFER },
+    { "FALLBACK_SPLITSIZE", FALLBACK_SPLITSIZE },
     { "ESTIMATE", ESTIMATE },
+    { "SERVER_CUSTOM_COMPRESS", SRVCOMPPROG },
+    { "CLIENT_CUSTOM_COMPRESS", CLNTCOMPPROG },
+    { "SERVER_ENCRYPT", SRV_ENCRYPT },
+    { "CLIENT_ENCRYPT", CLNT_ENCRYPT },
     { NULL, IDENT }
 };
 
@@ -1396,7 +1458,8 @@ dumptype_t *read_dumptype(name, from, fname, linenum)
        switch(tok) {
 
        case AUTH:
-           get_auth();
+           get_simple((val_t *)&dpcur.security_driver,
+               &dpcur.s_security_driver, STRING);
            break;
        case COMMENT:
            get_simple((val_t *)&dpcur.comment, &dpcur.s_comment, STRING);
@@ -1407,6 +1470,15 @@ dumptype_t *read_dumptype(name, from, fname, linenum)
        case COMPRESS:
            get_compress();
            break;
+       case ENCRYPT:
+           get_encrypt();
+           break;
+       case SRV_DECRYPT_OPT:
+           get_simple((val_t *)&dpcur.srv_decrypt_opt, &dpcur.s_srv_decrypt_opt, STRING);
+           break;
+       case CLNT_DECRYPT_OPT:
+           get_simple((val_t *)&dpcur.clnt_decrypt_opt, &dpcur.s_clnt_decrypt_opt, STRING);
+           break;
        case DUMPCYCLE:
            get_simple((val_t *)&dpcur.dumpcycle, &dpcur.s_dumpcycle, INT);
            if(dpcur.dumpcycle < 0) {
@@ -1485,9 +1557,6 @@ dumptype_t *read_dumptype(name, from, fname, linenum)
            break;
        case PROGRAM:
            get_simple((val_t *)&dpcur.program, &dpcur.s_program, STRING);
-           if(strcmp(dpcur.program, "DUMP")
-              && strcmp(dpcur.program, "GNUTAR"))
-               parserror("backup program \"%s\" unknown", dpcur.program);
            break;
        case RECORD:
            get_simple(&tmpval, &dpcur.s_record, BOOL);
@@ -1513,7 +1582,33 @@ dumptype_t *read_dumptype(name, from, fname, linenum)
        case IDENT:
            copy_dumptype();
            break;
-
+       case TAPE_SPLITSIZE:
+           get_simple((val_t *)&dpcur.tape_splitsize,  &dpcur.s_tape_splitsize,  INT);
+           if(dpcur.tape_splitsize < 0) {
+             parserror("tape_splitsize must be >= 0");
+           }
+           break;
+       case SPLIT_DISKBUFFER:
+           get_simple((val_t *)&dpcur.split_diskbuffer, &dpcur.s_split_diskbuffer, STRING);
+           break;
+       case FALLBACK_SPLITSIZE:
+           get_simple((val_t *)&dpcur.fallback_splitsize,  &dpcur.s_fallback_splitsize,  INT);
+           if(dpcur.fallback_splitsize < 0) {
+             parserror("fallback_splitsize must be >= 0");
+           }
+           break;
+       case SRVCOMPPROG:
+           get_simple((val_t *)&dpcur.srvcompprog, &dpcur.s_srvcompprog, STRING);
+           break;
+        case CLNTCOMPPROG:
+           get_simple((val_t *)&dpcur.clntcompprog, &dpcur.s_clntcompprog, STRING);
+           break;
+       case SRV_ENCRYPT:
+           get_simple((val_t *)&dpcur.srv_encrypt, &dpcur.s_srv_encrypt, STRING);
+           break;
+        case CLNT_ENCRYPT:
+           get_simple((val_t *)&dpcur.clnt_encrypt, &dpcur.s_clnt_encrypt, STRING);
+           break;
        case RBRACE:
            done = 1;
            break;
@@ -1560,6 +1655,10 @@ static void init_dumptype_defaults()
 {
     dpcur.comment = stralloc("");
     dpcur.program = stralloc("DUMP");
+    dpcur.srvcompprog = stralloc("");
+    dpcur.clntcompprog = stralloc("");
+    dpcur.srv_encrypt = stralloc("");
+    dpcur.clnt_encrypt = stralloc("");
     dpcur.exclude_file = NULL;
     dpcur.exclude_list = NULL;
     dpcur.include_file = NULL;
@@ -1575,23 +1674,33 @@ static void init_dumptype_defaults()
     dpcur.bumpdays = conf_bumpdays.i;
     dpcur.bumpmult = conf_bumpmult.r;
     dpcur.start_t = 0;
-
-    dpcur.auth = AUTH_BSD;
+    dpcur.security_driver = stralloc("BSD");
 
     /* options */
     dpcur.record = 1;
     dpcur.strategy = DS_STANDARD;
     dpcur.estimate = ES_CLIENT;
     dpcur.compress = COMP_FAST;
+    dpcur.encrypt = ENCRYPT_NONE;
+    dpcur.srv_decrypt_opt = stralloc("-d");
+    dpcur.clnt_decrypt_opt = stralloc("-d");
     dpcur.comprate[0] = dpcur.comprate[1] = 0.50;
     dpcur.skip_incr = dpcur.skip_full = 0;
     dpcur.no_hold = 0;
     dpcur.kencrypt = 0;
     dpcur.ignore = 0;
     dpcur.index = 0;
+    dpcur.tape_splitsize = 0;
+    dpcur.split_diskbuffer = NULL;
+    dpcur.fallback_splitsize = 10 * 1024;
 
     dpcur.s_comment = 0;
     dpcur.s_program = 0;
+    dpcur.s_srvcompprog = 0;
+    dpcur.s_clntcompprog = 0;
+    dpcur.s_clnt_encrypt= 0;
+    dpcur.s_srv_encrypt= 0;
+
     dpcur.s_exclude_file = 0;
     dpcur.s_exclude_list = 0;
     dpcur.s_include_file = 0;
@@ -1607,11 +1716,14 @@ static void init_dumptype_defaults()
     dpcur.s_bumpdays = 0;
     dpcur.s_bumpmult = 0;
     dpcur.s_start_t = 0;
-    dpcur.s_auth = 0;
+    dpcur.s_security_driver = 0;
     dpcur.s_record = 0;
     dpcur.s_strategy = 0;
     dpcur.s_estimate = 0;
     dpcur.s_compress = 0;
+    dpcur.s_encrypt = 0;
+    dpcur.s_srv_decrypt_opt = 0;
+    dpcur.s_clnt_decrypt_opt = 0;
     dpcur.s_comprate = 0;
     dpcur.s_skip_incr = 0;
     dpcur.s_skip_full = 0;
@@ -1619,6 +1731,9 @@ static void init_dumptype_defaults()
     dpcur.s_kencrypt = 0;
     dpcur.s_ignore = 0;
     dpcur.s_index = 0;
+    dpcur.s_tape_splitsize = 0;
+    dpcur.s_split_diskbuffer = 0;
+    dpcur.s_fallback_splitsize = 0;
 }
 
 static void save_dumptype()
@@ -1660,6 +1775,36 @@ static void copy_dumptype()
        dpcur.program = newstralloc(dpcur.program, dt->program);
        dpcur.s_program = dt->s_program;
     }
+    if(dt->s_security_driver) {
+       dpcur.security_driver = newstralloc(dpcur.security_driver,
+                                           dt->security_driver);
+       dpcur.s_security_driver = dt->s_security_driver;
+    }
+    if(dt->s_srvcompprog) {
+       dpcur.srvcompprog = newstralloc(dpcur.srvcompprog, dt->srvcompprog);
+       dpcur.s_srvcompprog = dt->s_srvcompprog;
+    }
+    if(dt->s_clntcompprog) {
+       dpcur.clntcompprog = newstralloc(dpcur.clntcompprog, dt->clntcompprog);
+       dpcur.s_clntcompprog = dt->s_clntcompprog;
+    }
+    if(dt->s_srv_encrypt) {
+       dpcur.srv_encrypt = newstralloc(dpcur.srv_encrypt, dt->srv_encrypt);
+       dpcur.s_srv_encrypt = dt->s_srv_encrypt;
+    }
+    if(dt->s_clnt_encrypt) {
+       dpcur.clnt_encrypt = newstralloc(dpcur.clnt_encrypt, dt->clnt_encrypt);
+       dpcur.s_clnt_encrypt = dt->s_clnt_encrypt;
+    }
+    if(dt->s_srv_decrypt_opt) {
+       dpcur.srv_decrypt_opt = newstralloc(dpcur.srv_decrypt_opt, dt->srv_decrypt_opt);
+       dpcur.s_srv_decrypt_opt = dt->s_srv_decrypt_opt;
+    }
+    if(dt->s_clnt_decrypt_opt) {
+       dpcur.clnt_decrypt_opt = newstralloc(dpcur.clnt_decrypt_opt, dt->clnt_decrypt_opt);
+       dpcur.s_clnt_decrypt_opt = dt->s_clnt_decrypt_opt;
+    }
+
     if(dt->s_exclude_file) {
        dpcur.exclude_file = duplicate_sl(dt->exclude_file);
        dpcur.s_exclude_file = dt->s_exclude_file;
@@ -1687,11 +1832,11 @@ static void copy_dumptype()
     dtcopy(bumpdays, s_bumpdays);
     dtcopy(bumpmult, s_bumpmult);
     dtcopy(start_t, s_start_t);
-    dtcopy(auth, s_auth);
     dtcopy(record, s_record);
     dtcopy(strategy, s_strategy);
     dtcopy(estimate, s_estimate);
     dtcopy(compress, s_compress);
+    dtcopy(encrypt, s_encrypt);
     dtcopy(comprate[0], s_comprate);
     dtcopy(comprate[1], s_comprate);
     dtcopy(skip_incr, s_skip_incr);
@@ -1700,6 +1845,9 @@ static void copy_dumptype()
     dtcopy(kencrypt, s_kencrypt);
     dtcopy(ignore, s_ignore);
     dtcopy(index, s_index);
+    dtcopy(tape_splitsize, s_tape_splitsize);
+    dtcopy(split_diskbuffer, s_split_diskbuffer);
+    dtcopy(fallback_splitsize, s_fallback_splitsize);
 }
 
 keytab_t tapetype_keytable[] = {
@@ -1993,6 +2141,7 @@ static void copy_interface()
 
 keytab_t dumpopts_keytable[] = {
     { "COMPRESS", COMPRESS },
+    { "ENCRYPT", ENCRYPT },
     { "INDEX", INDEX },
     { "EXCLUDE-FILE", EXCLUDE_FILE },
     { "EXCLUDE-LIST", EXCLUDE_LIST },
@@ -2015,15 +2164,16 @@ static void get_dumpopts() /* XXX - for historical compatability */
        get_conftoken(ANY);
        switch(tok) {
        case COMPRESS:   ckseen(&dpcur.s_compress);  dpcur.compress = COMP_FAST; break;
+       case ENCRYPT:   ckseen(&dpcur.s_encrypt);  dpcur.encrypt = ENCRYPT_NONE; break;
        case EXCLUDE_FILE:
            ckseen(&dpcur.s_exclude_file);
            get_conftoken(STRING);
-           dpcur.exclude_file = append_sl(dpcur.exclude_file, stralloc(tokenval.s));
+           dpcur.exclude_file = append_sl(dpcur.exclude_file, tokenval.s);
            break;
        case EXCLUDE_LIST:
            ckseen(&dpcur.s_exclude_list);
            get_conftoken(STRING);
-           dpcur.exclude_list = append_sl(dpcur.exclude_list, stralloc(tokenval.s));
+           dpcur.exclude_list = append_sl(dpcur.exclude_list, tokenval.s);
            break;
        case KENCRYPT:   ckseen(&dpcur.s_kencrypt);  dpcur.kencrypt = 1; break;
        case SKIP_INCR:  ckseen(&dpcur.s_skip_incr); dpcur.skip_incr= 1; break;
@@ -2077,13 +2227,14 @@ keytab_t compress_keytable[] = {
     { "FAST", FAST },
     { "NONE", NONE },
     { "SERVER", SERVER },
+    { "CUSTOM", CUSTOM },
     { NULL, IDENT }
 };
 
 static void get_compress()
 {
     keytab_t *save_kt;
-    int serv, clie, none, fast, best;
+    int serv, clie, none, fast, best, custom;
     int done;
     int comp;
 
@@ -2092,7 +2243,7 @@ static void get_compress()
 
     ckseen(&dpcur.s_compress);
 
-    serv = clie = none = fast = best = 0;
+    serv = clie = none = fast = best = custom  = 0;
 
     done = 0;
     do {
@@ -2103,6 +2254,7 @@ static void get_compress()
        case BEST:   best = 1; break;
        case CLIENT: clie = 1; break;
        case SERVER: serv = 1; break;
+       case CUSTOM: custom=1; break;
        case NL:     done = 1; break;
        default:
            done = 1;
@@ -2111,24 +2263,26 @@ static void get_compress()
     } while(!done);
 
     if(serv + clie == 0) clie = 1;     /* default to client */
-    if(none + fast + best == 0) fast = 1; /* default to fast */
+    if(none + fast + best + custom  == 0) fast = 1; /* default to fast */
 
     comp = -1;
 
     if(!serv && clie) {
-       if(none && !fast && !best) comp = COMP_NONE;
-       if(!none && fast && !best) comp = COMP_FAST;
-       if(!none && !fast && best) comp = COMP_BEST;
+       if(none && !fast && !best && !custom) comp = COMP_NONE;
+       if(!none && fast && !best && !custom) comp = COMP_FAST;
+       if(!none && !fast && best && !custom) comp = COMP_BEST;
+       if(!none && !fast && !best && custom) comp = COMP_CUST;
     }
 
     if(serv && !clie) {
-       if(none && !fast && !best) comp = COMP_NONE;
-       if(!none && fast && !best) comp = COMP_SERV_FAST;
-       if(!none && !fast && best) comp = COMP_SERV_BEST;
+       if(none && !fast && !best && !custom) comp = COMP_NONE;
+       if(!none && fast && !best && !custom) comp = COMP_SERV_FAST;
+       if(!none && !fast && best && !custom) comp = COMP_SERV_BEST;
+       if(!none && !fast && !best && custom) comp = COMP_SERV_CUST;
     }
 
     if(comp == -1) {
-       parserror("NONE, CLIENT FAST, CLIENT BEST, SERVER FAST or SERVER BEST expected");
+       parserror("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected");
        comp = COMP_NONE;
     }
 
@@ -2137,6 +2291,43 @@ static void get_compress()
     keytable = save_kt;
 }
 
+keytab_t encrypt_keytable[] = {
+    { "NONE", NONE },
+    { "CLIENT", CLIENT },
+    { "SERVER", SERVER },
+    { NULL, IDENT }
+};
+
+static void get_encrypt()
+{
+   keytab_t *save_kt;
+   int encrypt;
+
+   save_kt = keytable;
+   keytable = encrypt_keytable;
+
+   ckseen(&dpcur.s_encrypt);
+
+   get_conftoken(ANY);
+   switch(tok) {
+   case NONE:  
+     encrypt = ENCRYPT_NONE; 
+     break;
+   case CLIENT:  
+     encrypt = ENCRYPT_CUST;
+     break;
+   case SERVER: 
+     encrypt = ENCRYPT_SERV_CUST;
+     break;
+   default:
+     parserror("NONE, CLIENT or SERVER expected");
+     encrypt = ENCRYPT_NONE;
+   }
+
+   dpcur.encrypt = encrypt;
+   keytable = save_kt; 
+}
+
 keytab_t taperalgo_keytable[] = {
     { "FIRST", FIRST },
     { "FIRSTFIT", FIRSTFIT },
@@ -2205,39 +2396,6 @@ static void get_priority()
     keytable = save_kt;
 }
 
-keytab_t auth_keytable[] = {
-    { "BSD", BSD_AUTH },
-    { "KRB4", KRB4_AUTH },
-    { NULL, IDENT }
-};
-
-static void get_auth()
-{
-    auth_t auth;
-    keytab_t *save_kt;
-
-    save_kt = keytable;
-    keytable = auth_keytable;
-
-    ckseen(&dpcur.s_auth);
-
-    get_conftoken(ANY);
-    switch(tok) {
-    case BSD_AUTH:
-       auth = AUTH_BSD;
-       break;
-    case KRB4_AUTH:
-       auth = AUTH_KRB4;
-       break;
-    default:
-       parserror("BSD or KRB4 expected");
-       auth = AUTH_BSD;
-    }
-    dpcur.auth = auth;
-
-    keytable = save_kt;
-}
-
 keytab_t strategy_keytable[] = {
     { "HANOI", HANOI },
     { "NOFULL", NOFULL },
@@ -2471,10 +2629,13 @@ tok_t type;
        malloc_mark(var->s);
        break;
     case INT:
-       var->i = get_number();
+       var->i = get_int();
        break;
     case LONG:
-       var->l = get_number();
+       var->l = get_long();
+       break;
+    case AM64:
+       var->am64 = get_am64_t();
        break;
     case BOOL:
        var->i = get_bool();
@@ -2552,9 +2713,9 @@ keytab_t numb_keytable[] = {
     { NULL, IDENT }
 };
 
-static long get_number()
+static int get_int()
 {
-    long val;
+    int val;
     keytab_t *save_kt;
 
     save_kt = keytable;
@@ -2563,11 +2724,13 @@ static long get_number()
     get_conftoken(ANY);
 
     switch(tok) {
-    case INT:
-       val = (long) tokenval.i;
+    case AM64:
+       if(abs(tokenval.am64) > INT_MAX)
+           parserror("value too large");
+       val = (int) tokenval.am64;
        break;
     case INFINITY:
-       val = (long) BIGINT;
+       val = (int) BIGINT;
        break;
     default:
        parserror("an integer expected");
@@ -2583,12 +2746,128 @@ static long get_number()
     case MULT1K:
        break;
     case MULT7:
+       if(abs(val) > INT_MAX/7)
+           parserror("value too large");
+       val *= 7;
+       break;
+    case MULT1M:
+       if(abs(val) > INT_MAX/1024)
+           parserror("value too large");
+       val *= 1024;
+       break;
+    case MULT1G:
+       if(abs(val) > INT_MAX/(1024*1024))
+           parserror("value too large");
+       val *= 1024*1024;
+       break;
+    default:   /* it was not a multiplier */
+       unget_conftoken();
+    }
+
+    keytable = save_kt;
+
+    return val;
+}
+
+static long get_long()
+{
+    long val;
+    keytab_t *save_kt;
+
+    save_kt = keytable;
+    keytable = numb_keytable;
+
+    get_conftoken(ANY);
+
+    switch(tok) {
+    case AM64:
+       if(tokenval.am64 > LONG_MAX || tokenval.am64 < LONG_MIN)
+           parserror("value too large");
+       val = (long) tokenval.am64;
+       break;
+    case INFINITY:
+       val = (long) LONG_MAX;
+       break;
+    default:
+       parserror("a long expected");
+       val = 0;
+    }
+
+    /* get multiplier, if any */
+    get_conftoken(ANY);
+
+    switch(tok) {
+    case NL:                   /* multiply by one */
+    case MULT1:
+    case MULT1K:
+       break;
+    case MULT7:
+       if(val > LONG_MAX/7 || val < LONG_MIN/7)
+           parserror("value too large");
+       val *= 7;
+       break;
+    case MULT1M:
+       if(val > LONG_MAX/1024 || val < LONG_MIN/7)
+           parserror("value too large");
+       val *= 1024;
+       break;
+    case MULT1G:
+       if(val > LONG_MAX/(1024*1024) || val < LONG_MIN/(1024*1024))
+           parserror("value too large");
+       val *= 1024*1024;
+       break;
+    default:   /* it was not a multiplier */
+       unget_conftoken();
+    }
+
+    keytable = save_kt;
+
+    return val;
+}
+
+static am64_t get_am64_t()
+{
+    am64_t val;
+    keytab_t *save_kt;
+
+    save_kt = keytable;
+    keytable = numb_keytable;
+
+    get_conftoken(ANY);
+
+    switch(tok) {
+    case AM64:
+       val = tokenval.am64;
+       break;
+    case INFINITY:
+       val = AM64_MAX;
+       break;
+    default:
+       parserror("a am64 expected %d", tok);
+       val = 0;
+    }
+
+    /* get multiplier, if any */
+    get_conftoken(ANY);
+
+    switch(tok) {
+    case NL:                   /* multiply by one */
+    case MULT1:
+    case MULT1K:
+       break;
+    case MULT7:
+       if(val > AM64_MAX/7 || val < AM64_MIN/7)
+           parserror("value too large");
        val *= 7;
        break;
     case MULT1M:
+       if(val > AM64_MAX/1024 || val < AM64_MIN/1024)
+           parserror("value too large");
        val *= 1024;
        break;
     case MULT1G:
+       if(val > AM64_MAX/(1024*1024) || val < AM64_MIN/(1024*1024))
+           parserror("value too large");
        val *= 1024*1024;
        break;
     default:   /* it was not a multiplier */
@@ -2696,7 +2975,8 @@ static void unget_conftoken()
 static void get_conftoken(exp)
 tok_t exp;
 {
-    int ch, i, d;
+    int ch, d;
+    am64_t am64;
     char *buf;
     int token_overflow;
 
@@ -2707,6 +2987,7 @@ tok_t exp;
        /* If it looked like a key word before then look it
        ** up again in the current keyword table. */
        switch(tok) {
+       case LONG:    case AM64:
        case INT:     case REAL:    case STRING:
        case LBRACE:  case RBRACE:  case COMMA:
        case NL:      case END:     case UNKNOWN:
@@ -2758,34 +3039,42 @@ tok_t exp;
            negative_number: /* look for goto negative_number below */
                sign = -1;
            }
-           tokenval.i = 0;
+           tokenval.am64 = 0;
            do {
-               tokenval.i = tokenval.i * 10 + (ch - '0');
+               tokenval.am64 = tokenval.am64 * 10 + (ch - '0');
                ch = getc(conf);
            } while(isdigit(ch));
            if(ch != '.') {
-               if(exp != REAL) {
+               if(exp == INT) {
                    tok = INT;
                    tokenval.i *= sign;
+               }
+               else if(exp == LONG) {
+                   tok = LONG;
+                   tokenval.l *= sign;
+               }
+               else if(exp != REAL) {
+                   tok = AM64;
+                   tokenval.am64 *= sign;
                } else {
                    /* automatically convert to real when expected */
-                   i = tokenval.i;
-                   tokenval.r = sign * (double) i;
+                   am64 = tokenval.am64;
+                   tokenval.r = sign * (double) am64;
                    tok = REAL;
                }
            }
            else {
                /* got a real number, not an int */
-               i = tokenval.i;
-               tokenval.r = sign * (double) i;
-               i=0; d=1;
+               am64 = tokenval.am64;
+               tokenval.r = sign * (double) am64;
+               am64=0; d=1;
                ch = getc(conf);
                while(isdigit(ch)) {
-                   i = i * 10 + (ch - '0');
+                   am64 = am64 * 10 + (ch - '0');
                    d = d * 10;
                    ch = getc(conf);
                }
-               tokenval.r += sign * ((double)i)/d;
+               tokenval.r += sign * ((double)am64)/d;
                tok = REAL;
            }
            ungetc(ch,conf);
@@ -2873,8 +3162,12 @@ int ColumnDataCount()
 
 /* conversion from string to table index
  */
-int StringToColumn(char *s) {
+int
+StringToColumn(s)
+    char *s;
+{
     int cn;
+
     for (cn=0; ColumnData[cn].Name != NULL; cn++) {
        if (strcasecmp(s, ColumnData[cn].Name) == 0) {
            break;
@@ -2883,11 +3176,19 @@ int StringToColumn(char *s) {
     return cn;
 }
 
-char LastChar(char *s) {
+char
+LastChar(s)
+    char *s;
+{
     return s[strlen(s)-1];
 }
 
-int SetColumDataFromString(ColumnInfo* ci, char *s, char **errstr) {
+int
+SetColumDataFromString(ci, s, errstr)
+    ColumnInfo* ci;
+    char *s;
+    char **errstr;
+{
     /* Convert from a Columspec string to our internal format
      * of columspec. The purpose is to provide this string
      * as configuration paramter in the amanda.conf file or
@@ -3034,7 +3335,7 @@ dump_configuration(filename)
     printf("conf_tapebufs = %d\n", getconf_int(CNF_TAPEBUFS));
     printf("conf_autoflush  = %d\n", getconf_int(CNF_AUTOFLUSH));
     printf("conf_reserve  = %d\n", getconf_int(CNF_RESERVE));
-    printf("conf_maxdumpsize  = %d\n", getconf_int(CNF_MAXDUMPSIZE));
+    printf("conf_maxdumpsize  = " AM64_FMT "\n", getconf_am64(CNF_MAXDUMPSIZE));
     printf("conf_amrecover_do_fsf  = %d\n", getconf_int(CNF_AMRECOVER_DO_FSF));
     printf("conf_amrecover_check_label  = %d\n", getconf_int(CNF_AMRECOVER_CHECK_LABEL));
     printf("conf_amrecover_changer = \"%s\"\n", getconf_str(CNF_AMRECOVER_CHANGER));
@@ -3046,6 +3347,9 @@ dump_configuration(filename)
     printf("conf_columnspec = \"%s\"\n", getconf_str(CNF_COLUMNSPEC));
     printf("conf_indexdir = \"%s\"\n", getconf_str(CNF_INDEXDIR));
     printf("num_holdingdisks = %d\n", num_holdingdisks);
+    printf("conf_krb5keytab = \"%s\"\n", getconf_str(CNF_KRB5KEYTAB));
+    printf("conf_krb5principal = \"%s\"\n", getconf_str(CNF_KRB5PRINCIPAL));
+    printf("conf_label_new_tapes  = \"%s\"\n", getconf_str(CNF_LABEL_NEW_TAPES));
     for(hp = holdingdisks; hp != NULL; hp = hp->next) {
        printf("\nHOLDINGDISK %s:\n", hp->name);
        printf("        COMMENT \"%s\"\n", hp->comment);
@@ -3069,6 +3373,12 @@ dump_configuration(filename)
        printf("\nDUMPTYPE %s:\n", dp->name);
        printf("        COMMENT \"%s\"\n", dp->comment);
        printf("        PROGRAM \"%s\"\n", dp->program);
+       printf("        SERVER_CUSTOM_COMPRESS \"%s\"\n", dp->srvcompprog);
+       printf("        CLIENT_CUSTOM_COMPRESS \"%s\"\n", dp->clntcompprog);
+       printf("        SERVER_ENCRYPT \"%s\"\n", dp->srv_encrypt);
+       printf("        CLIENT_ENCRYPT \"%s\"\n", dp->clnt_encrypt);
+       printf("        SERVER_DECRYPT_OPTION \"%s\"\n", dp->srv_decrypt_opt);
+       printf("        CLIENT_DECRYPT_OPTION \"%s\"\n", dp->clnt_decrypt_opt);
        printf("        PRIORITY %ld\n", (long)dp->priority);
        printf("        DUMPCYCLE %ld\n", (long)dp->dumpcycle);
        st = dp->start_t;
@@ -3161,19 +3471,35 @@ dump_configuration(filename)
        case COMP_BEST:
            printf("COMPRESS-BEST ");
            break;
+       case COMP_CUST:
+           printf("COMPRESS-CUST ");
+           break;
        case COMP_SERV_FAST:
            printf("SRVCOMP-FAST ");
            break;
        case COMP_SERV_BEST:
            printf("SRVCOMP-BEST ");
            break;
+       case COMP_SERV_CUST:
+           printf("SRVCOMP-CUST ");
+           break;
+       }
+
+       switch(dp->encrypt) {
+       case ENCRYPT_NONE:
+           printf("ENCRYPT-NONE ");
+           break;
+       case ENCRYPT_CUST:
+           printf("ENCRYPT-CUST ");
+           break;
+       case ENCRYPT_SERV_CUST:
+           printf("ENCRYPT-SERV-CUST ");
+           break;
        }
 
        if(!dp->record) printf("NO-");
        printf("RECORD");
-       if(dp->auth == AUTH_BSD) printf(" BSD-AUTH");
-       else if(dp->auth == AUTH_KRB4) printf(" KRB4-AUTH");
-       else printf(" UNKNOWN-AUTH");
+       printf(" %s-AUTH", dp->security_driver);
        if(dp->skip_incr) printf(" SKIP-INCR");
        if(dp->skip_full) printf(" SKIP-FULL");
        if(dp->no_hold) printf(" NO-HOLD");
@@ -3198,6 +3524,7 @@ main(argc, argv)
 {
   char *conffile;
   char *diskfile;
+  disklist_t lst;
   int result;
   unsigned long malloc_hist_1, malloc_size_1;
   unsigned long malloc_hist_2, malloc_size_2;
@@ -3206,6 +3533,9 @@ main(argc, argv)
 
   set_pname("conffile");
 
+  /* Don't die when child closes pipe */
+  signal(SIGPIPE, SIG_IGN);
+
   malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
   startclock();
@@ -3235,10 +3565,10 @@ main(argc, argv)
   conffile = stralloc2(config_dir, CONFFILE_NAME);
   result = read_conffile(conffile);
   if (result == 0) {
-    diskfile = getconf_str(CNF_DISKFILE);
-    if (diskfile != NULL && access(diskfile, R_OK) == 0) {
-      result = (read_diskfile(diskfile) == NULL);
-    }
+      diskfile = getconf_str(CNF_DISKFILE);
+      if (diskfile != NULL && access(diskfile, R_OK) == 0) {
+         result = read_diskfile(diskfile, &lst);
+      }
   }
   dump_configuration(CONFFILE_NAME);
   amfree(conffile);
@@ -3253,3 +3583,19 @@ main(argc, argv)
 }
 
 #endif /* TEST */
+
+char *
+generic_get_security_conf(string, arg)
+       char *string;
+       void *arg;
+{
+       if(!string || !*string)
+               return(NULL);
+
+       if(strcmp(string, "krb5principal")==0) {
+               return(getconf_str(CNF_KRB5PRINCIPAL));
+       } else if(strcmp(string, "krb5keytab")==0) {
+               return(getconf_str(CNF_KRB5KEYTAB));
+       }
+       return(NULL);
+}
index 926a897c640500f641ba076c281ddd7709ff75ef..ef6c165da3400fa0c534501fac36c2db2c0feaac 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: conffile.h,v 1.24.2.8.4.4.2.9.2.5 2005/03/29 16:35:11 martinea Exp $
+ * $Id: conffile.h,v 1.60 2005/12/21 19:07:50 paddy_s Exp $
  *
  * interface for config file reading code
  */
@@ -82,14 +82,12 @@ typedef enum conf_e {
     CNF_AMRECOVER_CHECK_LABEL,
     CNF_AMRECOVER_CHANGER,
     CNF_TAPERALGO,
-    CNF_DISPLAYUNIT
+    CNF_DISPLAYUNIT,
+    CNF_KRB5KEYTAB,
+    CNF_KRB5PRINCIPAL,
+    CNF_LABEL_NEW_TAPES
 } confparm_t;
 
-typedef enum auth_e {
-    AUTH_BSD, AUTH_KRB4
-} auth_t;
-
-
 typedef struct tapetype_s {
     struct tapetype_s *next;
     int seen;
@@ -129,11 +127,22 @@ typedef struct tapetype_s {
 #define ES_CALCSIZE    2       /* calcsize estimate */
 
 /* Compression types */
-#define COMP_NONE      0       /* No compression */
-#define COMP_FAST      1       /* Fast compression on client */
-#define COMP_BEST      2       /* Best compression on client */
-#define COMP_SERV_FAST 3       /* Fast compression on server */
-#define COMP_SERV_BEST 4       /* Best compression on server */
+typedef enum {
+    COMP_NONE,         /* No compression */
+    COMP_FAST,         /* Fast compression on client */
+    COMP_BEST,         /* Best compression on client */
+    COMP_CUST,         /* Custom compression on client */
+    COMP_SERV_FAST,    /* Fast compression on server */
+    COMP_SERV_BEST,    /* Best compression on server */
+    COMP_SERV_CUST     /* Custom compression on server */
+} comp_t;
+
+/* Encryption types */
+typedef enum {
+    ENCRYPT_NONE,              /* No encryption */
+    ENCRYPT_CUST,              /* Custom encryption on client */
+    ENCRYPT_SERV_CUST,         /* Custom encryption on server */
+} encrypt_t;
 
 #define ALGO_FIRST     0
 #define ALGO_FIRSTFIT  1
@@ -149,6 +158,10 @@ typedef struct dumptype_s {
 
     char *comment;
     char *program;
+    char *srvcompprog;
+    char *clntcompprog;
+    char *srv_encrypt;
+    char *clnt_encrypt;
     sl_t *exclude_file;
     sl_t *exclude_list;
     sl_t *include_file;
@@ -159,18 +172,24 @@ typedef struct dumptype_s {
     int dumpcycle;
     int maxcycle;
     int frequency;
+    char *security_driver;
+    int maxdumps;
     int maxpromoteday;
     int bumppercent;
     int bumpsize;
     int bumpdays;
     double bumpmult;
-    auth_t auth;
-    int maxdumps;
     time_t start_t;
     int strategy;
     int estimate;
-    int compress;
+    comp_t compress;
+    encrypt_t encrypt;
+    char *srv_decrypt_opt;
+    char *clnt_decrypt_opt;
     float comprate[2]; /* first is full, second is incremental */
+    long tape_splitsize;
+    char *split_diskbuffer;
+    long fallback_splitsize;
     /* flag options */
     unsigned int record:1;
     unsigned int skip_incr:1;
@@ -183,6 +202,10 @@ typedef struct dumptype_s {
     /* seen flags */
     int s_comment;
     int s_program;
+    int s_srvcompprog;
+    int s_clntcompprog;
+    int s_srv_encrypt;
+    int s_clnt_encrypt;
     int s_exclude_file;
     int s_exclude_list;
     int s_include_file;
@@ -193,7 +216,7 @@ typedef struct dumptype_s {
     int s_dumpcycle;
     int s_maxcycle;
     int s_frequency;
-    int s_auth;
+    int s_security_driver;
     int s_maxdumps;
     int s_maxpromoteday;
     int s_bumppercent;
@@ -204,6 +227,9 @@ typedef struct dumptype_s {
     int s_strategy;
     int s_estimate;
     int s_compress;
+    int s_encrypt;
+    int s_srv_decrypt_opt;
+    int s_clnt_decrypt_opt;
     int s_comprate;
     int s_record;
     int s_skip_incr;
@@ -212,6 +238,9 @@ typedef struct dumptype_s {
     int s_kencrypt;
     int s_ignore;
     int s_index;
+    int s_tape_splitsize;
+    int s_split_diskbuffer;
+    int s_fallback_splitsize;
 } dumptype_t;
 
 /* A network interface */
@@ -282,6 +311,7 @@ extern int num_holdingdisks;
 int read_conffile P((char *filename));
 int getconf_seen P((confparm_t parameter));
 int getconf_int P((confparm_t parameter));
+am64_t getconf_am64 P((confparm_t parameter));
 double getconf_real P((confparm_t parameter));
 char *getconf_str P((confparm_t parameter));
 char *getconf_byname P((char *confname));
@@ -299,4 +329,6 @@ int SetColumDataFromString P((ColumnInfo* ci, char *s, char **errstr));
 
 char *taperalgo2str P((int taperalgo));
 
+/* this is in securityconf.h */
+char *generic_get_security_conf P((char *, void *));
 #endif /* ! CONFFILE_H */
index 21b2c1066228b6dd4fcac347e594d091a9920267..8d465bb8e5c8201663fede3bbb002a16334b2c5b 100644 (file)
@@ -23,7 +23,7 @@
  * Authors: the Amanda Development Team.  Its members are listed in a
  * file named AUTHORS, in the root directory of this distribution.
  */
-/* $Id: disk_history.c,v 1.8.10.1 2002/03/24 19:23:23 jrjackson Exp $
+/* $Id: disk_history.c,v 1.12 2006/01/16 00:07:01 martinea Exp $
  *
  * functions for obtaining backup history
  */
@@ -42,19 +42,28 @@ void clear_list P((void))
     {
        this = item;
        item = item->next;
+       while(this->tapes != NULL) {
+           tapelist_t *tapes = this->tapes;
+           this->tapes = tapes->next;
+           amfree(tapes->label);
+           amfree(tapes->files);
+           amfree(tapes);
+       }
        amfree(this);
     }
     disk_hist = NULL;
 }
 
 /* add item, maintain list ordered by oldest date last */
-void add_dump(date, level, tape, file)
+void add_dump(date, level, tape, file, partnum)
 char *date;
 int level;
 char *tape;
 int file;
+int partnum;
 {
     DUMP_ITEM *new, *item, *before;
+    int isafile = 0;
 
     new = (DUMP_ITEM *)alloc(sizeof(DUMP_ITEM));
     strncpy(new->date, date, sizeof(new->date)-1);
@@ -63,14 +72,37 @@ int file;
     strncpy(new->tape, tape, sizeof(new->tape)-1);
     new->tape[sizeof(new->tape)-1] = '\0';
     new->file = file;
+    if(partnum == -1) new->is_split = 0;
+    else new->is_split = 1;
+    new->tapes = NULL;
+
+   if(new->tape[0] == '/') isafile = 1; /* XXX kludgey, like this whole thing */
 
     if (disk_hist == NULL)
     {
        disk_hist = new;
+       new->tapes = append_to_tapelist(new->tapes, tape, file, isafile);
        new->next = NULL;
        return;
     }
 
+    /* see if we already have part of this dump somewhere */
+    if(new->is_split){
+       for(item = disk_hist; item; item = item->next){
+           if (!strcmp(item->date, new->date) &&
+                   item->level == new->level && item->is_split){
+               item->tapes = append_to_tapelist(item->tapes, tape, file, isafile);
+               amfree(new);
+               return;
+           }
+       }
+    }
+
+    new->tapes = append_to_tapelist(new->tapes, tape, file, isafile);
+
+    /* prepend this item to the history list, if it's newer */
+    /* XXX this should probably handle them being on the same date with
+       datestamp_uax or something */
     if (strcmp(disk_hist->date, new->date) <= 0)
     {
        new->next = disk_hist;
@@ -78,6 +110,7 @@ int file;
        return;
     }
 
+    /* append this item to the history list, if it's older */
     before = disk_hist;
     item = disk_hist->next;
     while ((item != NULL) && (strcmp(item->date, new->date) > 0))
index 644688127b3872b6de27d34cec58d02d333a368c..b10f0358c364bad6016b867c9d56f81b4d047f12 100644 (file)
  * Authors: the Amanda Development Team.  Its members are listed in a
  * file named AUTHORS, in the root directory of this distribution.
  */
-/* $Id: disk_history.h,v 1.3 1998/07/04 00:19:45 oliva Exp $
+/* $Id: disk_history.h,v 1.4 2005/10/11 01:17:01 vectro Exp $
  *
  * interface for obtaining disk backup history
  */
 
+#include "tapelist.h"
+
 typedef struct DUMP_ITEM
 {
     char date[11];
     int  level;
+    int  is_split;
     char tape[256];
+    tapelist_t *tapes;
     int  file;
 
     struct DUMP_ITEM *next;
@@ -40,6 +44,6 @@ typedef struct DUMP_ITEM
 DUMP_ITEM;
 
 extern void clear_list P((void));
-extern void add_dump P((char *date, int level, char *tape, int file));
+extern void add_dump P((char *date, int level, char *tape, int file, int partnum));
 extern DUMP_ITEM *first_dump P((void));
 extern DUMP_ITEM *next_dump P((DUMP_ITEM *item));
index 1adb6eedebd32da364e7493487578e0d22c55e68..a224eeeeba99b6d82d7e0fa4bad2e378db54fb80 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: diskfile.c,v 1.27.4.6.4.3.2.15.2.8 2005/09/30 19:13:36 martinea Exp $
+ * $Id: diskfile.c,v 1.73 2006/03/10 13:51:06 martinea Exp $
  *
  * read disklist file
  */
 #include "arglist.h"
 #include "conffile.h"
 #include "diskfile.h"
+#include "util.h"
 
-
-static disklist_t lst;
-static FILE *diskf;
-static char *diskfname = NULL;
 static am_host_t *hostlist;
-static int line_num, got_parserror;
 
 /* local functions */
 static char *upcase P((char *st));
-static int read_diskline P((void));
-static void parserror P((char *format, ...))
-    __attribute__ ((format (printf, 1, 2)));
+static int parse_diskline P((disklist_t *, const char *, FILE *, int *, char **));
+static void parserror P((const char *, int, const char *, ...))
+    __attribute__ ((format (printf, 3, 4)));
 
 
-disklist_t *read_diskfile(filename)
-char *filename;
+int
+read_diskfile(filename, lst)
+    const char *filename;
+    disklist_t *lst;
 {
-    extern int errno;
+    FILE *diskf;
+    int line_num;
+    char *line;
 
     /* initialize */
 
     hostlist = NULL;
-    lst.head = lst.tail = NULL;
-    diskfname = newstralloc(diskfname, filename);
-    malloc_mark(diskfname);
-    line_num = got_parserror = 0;
+    lst->head = lst->tail = NULL;
+    line_num = 0;
 
-    if((diskf = fopen(filename, "r")) == NULL)
+    if ((diskf = fopen(filename, "r")) == NULL) {
        error("could not open disklist file \"%s\": %s",
              filename, strerror(errno));
+    }
 
-    while(read_diskline());
-    afclose(diskf);
+    while ((line = agets(diskf)) != NULL) {
+       line_num++;
+       if (parse_diskline(lst, filename, diskf, &line_num, &line) < 0) {
+           amfree(line);
+           afclose(diskf);
+           return (-1);
+       }
+       amfree(line);
+    }
 
-    if(got_parserror) return NULL;
-    else return &lst;
+    afclose(diskf);
+    return (0);
 }
 
-am_host_t *lookup_host(hostname)
-char *hostname;
+am_host_t *
+lookup_host(hostname)
+    const char *hostname;
 {
     am_host_t *p;
 
-    for(p = hostlist; p != NULL; p = p->next) {
+    for (p = hostlist; p != NULL; p = p->next) {
        if(strcasecmp(p->hostname, hostname) == 0) return p;
     }
-    return NULL;
+    return (NULL);
 }
 
-disk_t *lookup_disk(hostname, diskname)
-char *hostname, *diskname;
+disk_t *
+lookup_disk(hostname, diskname)
+    const char *hostname, *diskname;
 {
     am_host_t *host;
     disk_t *disk;
 
     host = lookup_host(hostname);
-    if(host == NULL) return NULL;
+    if (host == NULL)
+       return (NULL);
 
-    for(disk = host->disks; disk != NULL; disk = disk->hostnext) {
-       if(strcmp(disk->name, diskname) == 0) return disk;
+    for (disk = host->disks; disk != NULL; disk = disk->hostnext) {
+       if (strcmp(disk->name, diskname) == 0)
+           return (disk);
     }
-    return NULL;
+    return (NULL);
 }
 
 void enqueue_disk(list, disk)  /* put disk on end of queue */
@@ -146,7 +156,8 @@ int (*cmp) P((disk_t *a, disk_t *b));
     else ptr->prev = disk;
 }
 
-disk_t *add_disk(hostname, diskname)
+disk_t *add_disk(list, hostname, diskname)
+disklist_t *list;
 char *hostname;
 char *diskname;
 {
@@ -155,11 +166,15 @@ char *diskname;
 
     disk = alloc(sizeof(disk_t));
     disk->line = 0;
+    disk->tape_splitsize = 0;
+    disk->split_diskbuffer = NULL;
+    disk->fallback_splitsize = 0;
     disk->name = stralloc(diskname);
     disk->device = stralloc(diskname);
     disk->spindle = -1;
     disk->up = NULL;
     disk->compress = COMP_NONE;
+    disk->encrypt  = ENCRYPT_NONE;
     disk->start_t = 0;
     disk->todo = 1;
 
@@ -178,7 +193,7 @@ char *diskname;
        host->up = NULL;
        host->features = NULL;
     }
-    enqueue_disk(&lst, disk);
+    enqueue_disk(list, disk);
 
     disk->host = host;
     disk->hostnext = host->disks;
@@ -246,20 +261,32 @@ disk_t *disk;
     disk->prev = disk->next = NULL;
 }
 
+void free_disklist(disklist_t* dl) {
+  while (dl->head != NULL) {
+    free(dequeue_disk(dl));
+  }
+}
+
 static char *upcase(st)
 char *st;
 {
     char *s = st;
 
     while(*s) {
-       if(islower((int)*s)) *s = toupper(*s);
+       if(islower((int)*s)) *s = toupper((int)*s);
        s++;
     }
     return st;
 }
 
 
-static int read_diskline()
+static int
+parse_diskline(lst, filename, diskf, line_num_p, line_p)
+    disklist_t *lst;
+    const char *filename;
+    FILE *diskf;
+    int *line_num_p;
+    char **line_p;
 {
     am_host_t *host;
     disk_t *disk;
@@ -267,21 +294,20 @@ static int read_diskline()
     interface_t *netif = 0;
     char *hostname = NULL;
     char *diskname, *diskdevice;
-    static char *line = NULL;
-    char *s = NULL, *fp;
-    int ch = '\0', dup = 0;
-    char *dn;
-
-    amfree(line);
-    for(; (line = agets(diskf)) != NULL; free(line)) {
-       line_num += 1;
-       s = line;
-       ch = *s++;
+    char *s, *fp;
+    int ch, dup = 0;
+    char *line = *line_p;
+    int line_num = *line_num_p;
 
-       skip_whitespace(s, ch);
-       if(ch != '\0' && ch != '#') break;
-    }
-    if(line == NULL) return 0;
+    assert(filename != NULL);
+    assert(line_num > 0);
+    assert(line != NULL);
+
+    s = line;
+    ch = *s++;
+    skip_whitespace(s, ch);
+    if(ch == '\0' || ch == '#')
+       return (0);
 
     fp = s - 1;
     skip_non_whitespace(s, ch);
@@ -296,8 +322,9 @@ static int read_diskline()
 
     skip_whitespace(s, ch);
     if(ch == '\0' || ch == '#') {
-       parserror("disk device name expected");
-       return 1;
+       parserror(filename, line_num, "disk device name expected");
+       if (host == NULL) amfree(hostname);
+       return (-1);
     }
     fp = s - 1;
     skip_non_whitespace(s, ch);
@@ -306,7 +333,7 @@ static int read_diskline()
 
     skip_whitespace(s, ch);
     if(ch == '\0' || ch == '#') {
-       parserror("disk dumptype expected");
+       parserror(filename, line_num, "disk dumptype expected");
        if(host == NULL) amfree(hostname);
        amfree(diskname);
        return 1;
@@ -316,15 +343,14 @@ static int read_diskline()
     s[-1] = '\0';
 
     /* diskdevice */
-    dn = stralloc(fp);
+    diskdevice = stralloc(fp);
     if(fp[0] != '{' && (dtype = lookup_dumptype(upcase(fp))) == NULL) {
-       diskdevice = dn;
        skip_whitespace(s, ch);
        if(ch == '\0' || ch == '#') {
-           parserror("disk dumptype expected");
+           parserror(filename, line_num, "disk dumptype expected");
            if(host == NULL) amfree(hostname);
-           amfree(diskname);
            amfree(diskdevice);
+           amfree(diskname);
            return 1;
        }
        fp = s - 1;
@@ -332,13 +358,13 @@ static int read_diskline()
        s[-1] = '\0';
     }
     else {
-       diskdevice = NULL;
-       amfree(dn);
+       amfree(diskdevice);
     }
 
     /* check for duplicate disk */
     if(host && (disk = lookup_disk(hostname, diskname)) != NULL) {
-       parserror("duplicate disk record, previous on line %d", disk->line);
+       parserror(filename, line_num,
+           "duplicate disk record, previous on line %d", disk->line);
        dup = 1;
     } else {
        disk = alloc(sizeof(disk_t));
@@ -357,7 +383,8 @@ static int read_diskline()
        s = fp+2;
        skip_whitespace(s, ch);
        if (ch != '\0' && ch != '#') {
-           parserror("expected line break after `{\', ignoring rest of line");
+           parserror(filename, line_num,
+                     "expected line break after `{\', ignoring rest of line");
        }
 
        if (strchr(s-1, '}') &&
@@ -365,46 +392,60 @@ static int read_diskline()
             strchr(s-1, '}') < strchr(s-1, '#'))) {
            if(host == NULL) amfree(hostname);
            if(!dup) {
+               amfree(disk->device);
                amfree(disk->name);
                amfree(disk);
+           } else {
+               amfree(diskdevice);
+               amfree(diskname);
            }
-           return 1;
+           return (-1);
        }
        amfree(line);
 
        dtype = read_dumptype(vstralloc("custom(", hostname,
                                        ":", disk->name, ")", 0),
-                             diskf, diskfname, &line_num);
+                             diskf, (char*)filename, line_num_p);
 
-       line = agets(diskf);
-       /* line_num += 1; */ /* read_dumptype did it already */
+       *line_p = line = agets(diskf);
+       line_num = *line_num_p; /* no incr, read_dumptype did it already */
 
        if (dtype == NULL || dup) {
            if(host == NULL) amfree(hostname);
            if(!dup) {
-             amfree(disk->name);
-             amfree(disk);
+               amfree(disk->device);
+               amfree(disk->name);
+               amfree(disk);
+           } else {
+               amfree(diskdevice);
+               amfree(diskname);
            }
-           return line != NULL;
+           return (-1);
        }
 
        if (line == NULL)
-           line = stralloc("");
+           *line_p = line = stralloc("");
        s = line;
        ch = *s++;
     } else if((dtype = lookup_dumptype(upcase(fp))) == NULL) {
-       parserror("undefined dumptype `%s'", fp);
+       parserror(filename, line_num, "undefined dumptype `%s'", fp);
        if(host == NULL) amfree(hostname);
-       if(!dup) {
-         amfree(disk->name);
-         amfree(disk);
+       if (!dup) {
+           amfree(disk->device);
+           amfree(disk->name);
+           amfree(disk);
+       } else {
+           amfree(diskdevice);
+           amfree(diskname);
        }
-       return 1;
+       return (-1);
     }
 
     if (dup) {
-       if(host == NULL) amfree(hostname);
-       return 1;
+       if (host == NULL) amfree(hostname);
+       amfree(diskdevice);
+       amfree(diskname);
+       return (-1);
     }
 
     disk->dtype_name   = dtype->name;
@@ -418,8 +459,11 @@ static int read_diskline()
     disk->priority     = dtype->priority;
     disk->dumpcycle    = dtype->dumpcycle;
     disk->frequency    = dtype->frequency;
-    disk->auth         = dtype->auth;
+    disk->security_driver = dtype->security_driver;
     disk->maxdumps     = dtype->maxdumps;
+    disk->tape_splitsize       = dtype->tape_splitsize;
+    disk->split_diskbuffer     = dtype->split_diskbuffer;
+    disk->fallback_splitsize   = dtype->fallback_splitsize;
     disk->maxpromoteday        = dtype->maxpromoteday;
     disk->bumppercent  = dtype->bumppercent;
     disk->bumpsize     = dtype->bumpsize;
@@ -429,6 +473,13 @@ static int read_diskline()
     disk->strategy     = dtype->strategy;
     disk->estimate     = dtype->estimate;
     disk->compress     = dtype->compress;
+    disk->srvcompprog  = dtype->srvcompprog;
+    disk->clntcompprog = dtype->clntcompprog;
+    disk->encrypt       = dtype->encrypt;
+    disk->srv_decrypt_opt   = dtype->srv_decrypt_opt;
+    disk->clnt_decrypt_opt  = dtype->clnt_decrypt_opt;
+    disk->srv_encrypt   = dtype->srv_encrypt;
+    disk->clnt_encrypt  = dtype->clnt_encrypt;
     disk->comprate[0]  = dtype->comprate[0];
     disk->comprate[1]  = dtype->comprate[1];
     disk->record       = dtype->record;
@@ -454,7 +505,7 @@ static int read_diskline()
            }
        }
        if(is_digit == 0) {
-           parserror("non-integer spindle `%s'", fp);
+           parserror(filename, line_num, "non-integer spindle `%s'", fp);
            if(host == NULL) amfree(hostname);
            amfree(disk->name);
            amfree(disk);
@@ -470,11 +521,12 @@ static int read_diskline()
        skip_non_whitespace(s, ch);
        s[-1] = '\0';
        if((netif = lookup_interface(upcase(fp))) == NULL) {
-           parserror("undefined network interface `%s'", fp);
+           parserror(filename, line_num,
+               "undefined network interface `%s'", fp);
            if(host == NULL) amfree(hostname);
            amfree(disk->name);
            amfree(disk);
-           return 1;
+           return (-1);
        }
     } else {
        netif = lookup_interface("");
@@ -482,17 +534,14 @@ static int read_diskline()
 
     skip_whitespace(s, ch);
     if(ch && ch != '#') {              /* now we have garbage, ignore it */
-       parserror("end of line expected");
+       parserror(filename, line_num, "end of line expected");
     }
 
     if(dtype->ignore || dtype->strategy == DS_SKIP) {
-       amfree(diskname);
-       free_sl(disk->exclude_file);
-       free_sl(disk->exclude_list);
-       free_sl(disk->include_file);
-       free_sl(disk->include_list);
+       if(host == NULL) amfree(hostname);
+       amfree(disk->name);
        amfree(disk);
-       return 1;
+       return (1);
     }
 
     /* success, add disk to lists */
@@ -516,30 +565,29 @@ static int read_diskline()
 
     host->netif = netif;
 
-    enqueue_disk(&lst, disk);
+    enqueue_disk(lst, disk);
 
     disk->host = host;
     disk->hostnext = host->disks;
     host->disks = disk;
     host->maxdumps = disk->maxdumps;
 
-    return 1;
+    return (0);
 }
 
 
-printf_arglist_function(static void parserror, char *, format)
+printf_arglist_function2(static void parserror, const char *, filename,
+    int, line_num, const char *, format)
 {
     va_list argp;
 
     /* print error message */
 
-    fprintf(stderr, "\"%s\", line %d: ", diskfname, line_num);
+    fprintf(stderr, "\"%s\", line %d: ", filename, line_num);
     arglist_start(argp, format);
     vfprintf(stderr, format, argp);
     arglist_end(argp);
     fputc('\n', stderr);
-
-    got_parserror = 1;
 }
 
 
@@ -580,6 +628,8 @@ FILE *fdout;
     char *auth_opt = NULL;
     char *kencrypt_opt = "";
     char *compress_opt = "";
+    char *encrypt_opt = "";
+    char *decrypt_opt ="";
     char *record_opt = "";
     char *index_opt = "";
     char *exclude_file = NULL;
@@ -594,49 +644,23 @@ FILE *fdout;
     int nb_exclude_file;
     int nb_include_file;
 
-    /* modification by BIS@BBN 4/25/2003:
-     * The first "if" statement has a number of problems, so I removed the
-     * am_has_feature(dp->host->features, fe_options_auth)
-     * condition and caused the first case to always fail.
-     * 1) If dp->host is a NULL pointer, subsequent tests which look
-     *    at dp->host->features or dp->host->hostname will cause a dump.
-     *    It appears that there should be an assertion that dp->host
-     *    is NOT NULL.
-     * 2) The code which checks for the kencrypt feature is only executed
-     *    in the case where dp->auth == AUTH_KRB4.  If we enable Kerberos IV
-     *    in the first case, then the code checking for kencrypt will never
-     *    be executed.
-     * 3) The option processing code in server-src/dumper.c and
-     *    client-src/sendbackup.c do not yet handle the "auth=krb4"
-     *    option style of specifying Kerberos IV.
-     * Getting rid of the whole first case seems to take care of problems
-     * 2 and 3, but not problem 1.
-     */
-    if(dp->host && 0)
-       /* && am_has_feature(dp->host->features, fe_options_auth)) */ {
-       auth_opt = stralloc("auth=");
-       if(dp->auth == AUTH_BSD) {
-           strappend(auth_opt, "bsd");
-       } else if(dp->auth == AUTH_KRB4) {
-           strappend(auth_opt, "krb4");
-       } else {
-           strappend(auth_opt, "unknown");
-       }
-       strappend(auth_opt, ";");
-    } else if(dp->auth == AUTH_BSD) {
-       if(am_has_feature(dp->host->features, fe_options_bsd_auth)) {
+    if(dp->host
+       && am_has_feature(dp->host->features, fe_options_auth)) {
+       auth_opt = vstralloc("auth=", dp->security_driver, ";", NULL);
+    } else if(strcasecmp(dp->security_driver, "bsd") == 0) {
+       if(am_has_feature(dp->host->features, fe_options_bsd_auth))
            auth_opt = stralloc("bsd-auth;");
-       }
        else if(fdout) {
-           fprintf(fdout, "WARNING: %s:%s does not support bsd-auth\n",
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support auth or bsd-auth\n",
                    dp->host->hostname, dp->name);
        }
-    } else if(dp->auth == AUTH_KRB4) {
-       if(am_has_feature(dp->host->features, fe_options_krb4_auth)) {
+    } else if(strcasecmp(dp->security_driver, "krb4") == 0) {
+       if(am_has_feature(dp->host->features, fe_options_krb4_auth))
            auth_opt = stralloc("krb4-auth;");
-       }
        else if(fdout) {
-           fprintf(fdout, "WARNING: %s:%s does not support krb4-auth\n",
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support auth or krb4-auth\n",
                    dp->host->hostname, dp->name);
        }
        if(dp->kencrypt) {
@@ -644,9 +668,9 @@ FILE *fdout;
                kencrypt_opt = "kencrypt;";
            }
            else if(fdout) {
-               fprintf(fdout,
-                       "WARNING: %s:%s does not support kencrypt\n",
-                       dp->host->hostname, dp->name);
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support kencrypt\n",
+                   dp->host->hostname, dp->name);
            }
        }
     }
@@ -672,6 +696,23 @@ FILE *fdout;
                    dp->host->hostname, dp->name);
        }
        break;
+    case COMP_CUST:
+        if(am_has_feature(their_features, fe_options_compress_cust)) {
+         compress_opt = vstralloc("comp-cust=", dp->clntcompprog, ";", NULL);
+         if (BSTRNCMP(compress_opt, "comp-cust=;") == 0){
+           if(fdout) {
+             fprintf(fdout,
+                     "WARNING: %s:%s client custom compression with no compression program specified\n",
+                     dp->host->hostname, dp->name);
+           }
+         }
+       }
+       else if(fdout) {
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support client custom compression\n",
+                   dp->host->hostname, dp->name);
+       }
+       break;
     case COMP_SERV_FAST:
        if(am_has_feature(their_features, fe_options_srvcomp_fast)) {
            compress_opt = "srvcomp-fast;";
@@ -682,8 +723,82 @@ FILE *fdout;
             compress_opt = "srvcomp-best;";
        }
        break;
+    case COMP_SERV_CUST:
+        if(am_has_feature(their_features, fe_options_srvcomp_cust)) {
+         compress_opt = vstralloc("srvcomp-cust=", dp->srvcompprog, ";", NULL);
+         if (BSTRNCMP(compress_opt, "srvcomp-cust=;") == 0){
+           if(fdout) {
+             fprintf(fdout,
+                     "WARNING: %s:%s server custom compression with no compression program specified\n",
+                     dp->host->hostname, dp->name);
+           }
+         }
+       }
+       else if(fdout) {
+         fprintf(fdout,
+                 "WARNING: %s:%s does not support server custom compression\n",
+                 dp->host->hostname, dp->name);
+       }
+       break;
     }
 
+    switch(dp->encrypt) {
+    case ENCRYPT_CUST:
+      if(am_has_feature(their_features, fe_options_encrypt_cust)) {
+        encrypt_opt = vstralloc("encrypt-cust=", dp->clnt_encrypt, ";", NULL);
+        if (BSTRNCMP(encrypt_opt, "encrypt-cust=;") == 0) {
+           if(fdout) {
+             fprintf(fdout,
+                     "WARNING: %s:%s encrypt client with no encryption program specified\n",
+                     dp->host->hostname, dp->name);
+           }
+         }
+        if(dp->clnt_decrypt_opt) {
+          if(am_has_feature(their_features, fe_options_client_decrypt_option)) {
+            decrypt_opt = vstralloc("client-decrypt-option=", dp->clnt_decrypt_opt, ";", NULL);
+          }
+          else if(fdout) {
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support client decrypt option\n",
+                   dp->host->hostname, dp->name);
+          }
+        }
+      }
+      else if(fdout) {
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support client data encryption\n",
+                   dp->host->hostname, dp->name);
+     }
+        break;
+    case ENCRYPT_SERV_CUST:
+      if(am_has_feature(their_features, fe_options_encrypt_serv_cust)) {
+        encrypt_opt = vstralloc("encrypt-serv-cust=", dp->srv_encrypt, ";", NULL);
+        if (BSTRNCMP(encrypt_opt, "encrypt-serv-cust=;") == 0){
+           if(fdout) {
+             fprintf(fdout,
+                     "WARNING: %s:%s encrypt server with no encryption program specified\n",
+                     dp->host->hostname, dp->name);
+           }
+         }
+        if(dp->srv_decrypt_opt) {
+          if(am_has_feature(their_features, fe_options_server_decrypt_option)) {
+            decrypt_opt = vstralloc("server-decrypt-option=", dp->srv_decrypt_opt, ";", NULL);
+          }
+          else if(fdout) {
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support server decrypt option\n",
+                   dp->host->hostname, dp->name);
+          }
+        }
+      }
+      else if(fdout) {
+           fprintf(fdout,
+                   "WARNING: %s:%s does not support server data encryption\n",
+                   dp->host->hostname, dp->name);
+      }
+        break;
+    }
+    
     if(!dp->record) {
        if(am_has_feature(their_features, fe_options_no_record)) {
            record_opt = "no-record;";
@@ -704,6 +819,9 @@ FILE *fdout;
        }
     }
 
+    if(dp->kencrypt) kencrypt_opt = "kencrypt;";
+
+
     exclude_file = stralloc("");
     nb_exclude_file = 0;
     if(dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
@@ -839,6 +957,8 @@ FILE *fdout;
                       auth_opt,
                       kencrypt_opt,
                       compress_opt,
+                      encrypt_opt,
+                      decrypt_opt,
                       record_opt,
                       index_opt,
                       exclude_file,
@@ -849,8 +969,8 @@ FILE *fdout;
                       incl_opt,
                       NULL);
     amfree(auth_opt);
-    amfree(exclude_file);
     amfree(exclude_list);
+    amfree(exclude_file);
     amfree(include_file);
     amfree(include_list);
     amfree(exc);
@@ -937,9 +1057,13 @@ void match_disklist(disklist_t *origqp, int sargc, char **sargv)
  
 #ifdef TEST
 
-void
+static void dump_disk P((const disk_t *));
+static void dump_disklist P((const disklist_t *));
+int main P((int, char *[]));
+
+static void
 dump_disk(dp)
-disk_t *dp;
+    const disk_t *dp;
 {
     printf("  DISK %s (HOST %s, LINE %d) TYPE %s NAME %s SPINDLE %d\n",
           dp->name, dp->host->hostname, dp->line, dp->dtype_name,
@@ -947,11 +1071,12 @@ disk_t *dp;
           dp->spindle);
 }
 
-void
-dump_disklist()
+static void
+dump_disklist(lst)
+    const disklist_t *lst;
 {
-    disk_t *dp, *prev;
-    am_host_t *hp;
+    const disk_t *dp, *prev;
+    const am_host_t *hp;
 
     if(hostlist == NULL) {
        printf("DISKLIST not read in\n");
@@ -974,21 +1099,22 @@ dump_disklist()
     printf("DISKLIST IN FILE ORDER:\n");
 
     prev = NULL;
-    for(dp = lst.head; dp != NULL; prev = dp, dp = dp->next) {
+    for(dp = lst->head; dp != NULL; prev = dp, dp = dp->next) {
        dump_disk(dp);
        /* check pointers */
        if(dp->prev != prev) printf("*** prev pointer mismatch!\n");
-       if(dp->next == NULL && lst.tail != dp) printf("tail mismatch!\n");
+       if(dp->next == NULL && lst->tail != dp) printf("tail mismatch!\n");
     }
 }
 
 int
 main(argc, argv)
-int argc;
-char *argv[];
+     int argc;
+     char *argv[];
 {
   char *conffile;
   char *conf_diskfile;
+  disklist_t lst;
   int result;
   unsigned long malloc_hist_1, malloc_size_1;
   unsigned long malloc_hist_2, malloc_size_2;
@@ -997,6 +1123,9 @@ char *argv[];
 
   set_pname("diskfile");
 
+  /* Don't die when child closes pipe */
+  signal(SIGPIPE, SIG_IGN);
+
   malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
   if (argc>1) {
@@ -1018,8 +1147,9 @@ char *argv[];
     } else {
       conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((result = (read_diskfile(conf_diskfile) == NULL)) == 0) {
-      dump_disklist();
+    result = read_diskfile(conf_diskfile, &lst);
+    if(result == 0) {
+      dump_disklist(&lst);
     }
     amfree(conf_diskfile);
   }
@@ -1034,5 +1164,4 @@ char *argv[];
 
   return result;
 }
-
 #endif /* TEST */
index ae17fc8c9fb3d995ac079afa26844e1f730c830e..f53441c9eb77f3feb335a18782bf3d602a7d8cf6 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: diskfile.h,v 1.11.4.3.4.1.2.9.2.3 2004/08/03 11:27:17 martinea Exp $
+ * $Id: diskfile.h,v 1.32 2005/12/09 03:22:52 paddy_s Exp $
  *
  * interface for disklist file reading code
  */
@@ -59,6 +59,10 @@ typedef struct disk_s {
     char *device;                      /* device name for disk, eg "sd0g" */
     char *dtype_name;                  /* name of dump type   XXX shouldn't need this */
     char *program;                     /* dump program, eg DUMP, GNUTAR */
+    char *srvcompprog;                  /* custom compression server filter */
+    char *clntcompprog;                 /* custom compression client filter */
+    char *srv_encrypt;                  /* custom encryption server filter */
+    char *clnt_encrypt;                 /* custom encryption client filter */
     sl_t *exclude_file;                        /* file exclude spec */
     sl_t *exclude_list;                        /* exclude list */
     sl_t *include_file;                        /* file include spec */
@@ -66,9 +70,12 @@ typedef struct disk_s {
     int exclude_optional;              /* exclude list are optional */
     int include_optional;              /* include list are optional */
     long priority;                     /* priority of disk */
+    long tape_splitsize;               /* size of dumpfile chunks on tape */
+    char *split_diskbuffer;            /* place where we can buffer PORT-WRITE dumps other than RAM */
+    long fallback_splitsize;           /* size for in-RAM PORT-WRITE buffers */
     long dumpcycle;                    /* days between fulls */
     long frequency;                    /* XXX - not used */
-    auth_t auth;                       /* type of authentication (per system?) */
+    char *security_driver;             /* type of authentication (per disk) */
     int maxdumps;                      /* max number of parallel dumps (per system) */
     int maxpromoteday;                 /* maximum of promote day */
     int bumppercent;
@@ -79,6 +86,9 @@ typedef struct disk_s {
     int strategy;                      /* what dump strategy to use */
     int estimate;                      /* what estimate strategy to use */
     int compress;                      /* type of compression to use */
+    int encrypt;                       /* type of encryption to use */
+    char *srv_decrypt_opt;             /* server-side decryption option parameter to use */
+    char *clnt_decrypt_opt;             /* client-side decryption option parameter to use */
     float comprate[2];                 /* default compression rates */
     /* flag options */
     unsigned int record:1;             /* record dump in /etc/dumpdates ? */
@@ -100,11 +110,12 @@ typedef struct disklist_s {
 #define empty(dlist)   ((dlist).head == NULL)
 
 
-disklist_t *read_diskfile P((char *filename));
+int read_diskfile P((const char *, disklist_t *));
 
-disk_t *add_disk P((char *hostname, char *diskname));
-am_host_t *lookup_host P((char *hostname));
-disk_t *lookup_disk P((char *hostname, char *diskname));
+am_host_t *lookup_host P((const char *hostname));
+disk_t *lookup_disk P((const char *hostname, const char *diskname));
+
+disk_t *add_disk P((disklist_t *list, char *hostname, char *diskname));
 
 void enqueue_disk P((disklist_t *list, disk_t *disk));
 void headqueue_disk P((disklist_t *list, disk_t *disk));
@@ -119,5 +130,6 @@ void dump_queue P((char *str, disklist_t q, int npr, FILE *f));
 char *optionstr P((disk_t *dp, am_feature_t *their_features, FILE *fdout));
 
 void match_disklist P((disklist_t *origqp, int sargc, char **sargv));
+void free_disklist P((disklist_t *dl));
 
 #endif /* ! DISKFILE_H */
index 345f3f931d2ba14d5e07e58b205c13d4fca2d26e..c9f53e45fc1a86f87ac46b9c2423f57f76d2670a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-2000 University of Maryland at College Park
+ * Copyright (c) 1991-1998 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: driver.c,v 1.58.2.31.2.8.2.20.2.16 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: driver.c,v 1.164 2006/03/22 15:07:08 martinea Exp $
  *
  * controlling process for the Amanda backup system
  */
  *     tape.  Probably not effective though, should do this in planner.
  */
 
+/*#define HOLD_DEBUG*/
+
 #include "amanda.h"
 #include "clock.h"
 #include "conffile.h"
 #include "diskfile.h"
+#include "event.h"
 #include "holding.h"
 #include "infofile.h"
 #include "logfile.h"
 #include "driverio.h"
 #include "server_util.h"
 
-disklist_t waitq, runq, tapeq, roomq;
-int pending_aborts, inside_dump_to_tape;
-disk_t *taper_disk;
-int degraded_mode;
-unsigned long reserved_space;
-unsigned long total_disksize;
-char *dumper_program;
-int  inparallel;
-int nodump = 0;
-unsigned long tape_length, tape_left = 0;
-int conf_taperalgo;
-am_host_t *flushhost = NULL;
-
-int client_constrained P((disk_t *dp));
-int sort_by_priority_reversed P((disk_t *a, disk_t *b));
-int sort_by_time P((disk_t *a, disk_t *b));
-int start_some_dumps P((disklist_t *rq));
-void dump_schedule P((disklist_t *qp, char *str));
-void start_degraded_mode P((disklist_t *queuep));
-void handle_taper_result P((void));
-dumper_t *idle_dumper P((void));
-int some_dumps_in_progress P((void));
-int num_busy_dumpers P((void));
-dumper_t *lookup_dumper P((int fd));
-void handle_dumper_result P((int fd));
-void read_flush P((disklist_t *tapeqp));
-void read_schedule P((disklist_t *waitqp, disklist_t *runqp));
-int free_kps P((interface_t *ip));
-void interface_state P((char *time_str));
-void allocate_bandwidth P((interface_t *ip, int kps));
-void deallocate_bandwidth P((interface_t *ip, int kps));
-unsigned long free_space P((void));
-assignedhd_t **find_diskspace P((unsigned long size, int *cur_idle, assignedhd_t *preferred));
-char *diskname2filename P((char *dname));
-int assign_holdingdisk P((assignedhd_t **holdp, disk_t *diskp));
+static disklist_t waitq, runq, tapeq, roomq;
+static int pending_aborts;
+static disk_t *taper_disk;
+static int degraded_mode;
+static unsigned long reserved_space;
+static unsigned long total_disksize;
+static char *dumper_program;
+static char *chunker_program;
+static int  inparallel;
+static int nodump = 0;
+static unsigned long tape_length, tape_left = 0;
+static int current_tape = 1;
+static int conf_taperalgo;
+static int conf_runtapes;
+static time_t sleep_time;
+static int idle_reason;
+static char *datestamp;
+static char *timestamp;
+static am_host_t *flushhost = NULL;
+static int need_degraded=0;
+
+static event_handle_t *dumpers_ev_time = NULL;
+static event_handle_t *schedule_ev_read = NULL;
+
+static void allocate_bandwidth P((interface_t *ip, int kps));
+static int assign_holdingdisk P((assignedhd_t **holdp, disk_t *diskp));
 static void adjust_diskspace P((disk_t *diskp, cmd_t cmd));
 static void delete_diskspace P((disk_t *diskp));
-assignedhd_t **build_diskspace P((char *destname));
-void holdingdisk_state P((char *time_str));
-int dump_to_tape P((disk_t *dp));
-int queue_length P((disklist_t q));
-void short_dump_state P((void));
-void dump_state P((char *str));
-void startaflush P((void));
+static assignedhd_t **build_diskspace P((char *destname));
+static int client_constrained P((disk_t *dp));
+static void deallocate_bandwidth P((interface_t *ip, int kps));
+static void dump_schedule P((disklist_t *qp, char *str));
+static int dump_to_tape P((disk_t *dp));
+static assignedhd_t **find_diskspace P((unsigned long size, int *cur_idle,
+                                       assignedhd_t *preferred));
+static int free_kps P((interface_t *ip));
+static unsigned long free_space P((void));
+static void dumper_result P((disk_t *dp));
+static void handle_dumper_result P((void *));
+static void handle_chunker_result P((void *));
+static void handle_dumpers_time P((void *));
+static void handle_taper_result P((void *));
+static void holdingdisk_state P((char *time_str));
+static dumper_t *idle_dumper P((void));
+static void interface_state P((char *time_str));
+static int num_busy_dumpers P((void));
+static int queue_length P((disklist_t q));
+static disklist_t read_flush P((void));
+static void read_schedule P((void *cookie));
+static void short_dump_state P((void));
+static void startaflush P((void));
+static void start_degraded_mode P((disklist_t *queuep));
+static void start_some_dumps P((disklist_t *rq));
+static void continue_port_dumps();
+static void update_failed_dump_to_tape P((disk_t *));
+#if 0
+static void dump_state P((const char *str));
+#endif
 int main P((int main_argc, char **main_argv));
 
-static int idle_reason;
-char *datestamp;
-char *timestamp;
-
-char *idle_strings[] = {
+static const char *idle_strings[] = {
 #define NOT_IDLE               0
     "not-idle",
-#define IDLE_START_WAIT                1
-    "start-wait",
-#define IDLE_NO_DUMPERS                2
+#define IDLE_NO_DUMPERS                1
     "no-dumpers",
+#define IDLE_START_WAIT                2
+    "start-wait",
 #define IDLE_NO_HOLD           3
     "no-hold",
 #define IDLE_CLIENT_CONSTRAINED        4
@@ -117,19 +130,14 @@ char *idle_strings[] = {
     "taper-wait",
 };
 
-#define SLEEP_MAX              (24*3600)
-struct timeval sleep_time = { SLEEP_MAX, 0 };
-/* enabled if any disks are in start-wait: */
-int any_delayed_disk = 0;
-
-int main(main_argc, main_argv)
+int
+main(main_argc, main_argv)
      int main_argc;
      char **main_argv;
 {
-    disklist_t *origqp;
+    disklist_t origq;
     disk_t *diskp;
-    fd_set selectset;
-    int fd, dsk;
+    int dsk;
     dumper_t *dumper;
     char *newdir = NULL;
     generic_fs_stats_t fs;
@@ -154,6 +162,7 @@ int main(main_argc, main_argv)
 
     set_pname("driver");
 
+    /* Don't die when child closes pipe */
     signal(SIGPIPE, SIG_IGN);
 
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
@@ -162,7 +171,6 @@ int main(main_argc, main_argv)
     set_logerror(logerror);
 
     startclock();
-    FD_ZERO(&readset);
 
     printf("%s: pid %ld executable %s version %s\n",
           get_pname(), (long) getpid(), main_argv[0], version());
@@ -204,9 +212,12 @@ int main(main_argc, main_argv)
     taper_program = vstralloc(libexecdir, "/", "taper", versionsuffix(), NULL);
     dumper_program = vstralloc(libexecdir, "/", "dumper", versionsuffix(),
                               NULL);
+    chunker_program = vstralloc(libexecdir, "/", "chunker", versionsuffix(),
+                              NULL);
 
     conf_taperalgo = getconf_int(CNF_TAPERALGO);
     conf_tapetype = getconf_str(CNF_TAPETYPE);
+    conf_runtapes = getconf_int(CNF_RUNTAPES);
     tape = lookup_tapetype(conf_tapetype);
     tape_length = tape->length;
     printf("driver: tape size %ld\n", tape_length);
@@ -214,8 +225,10 @@ int main(main_argc, main_argv)
     /* taper takes a while to get going, so start it up right away */
 
     init_driverio();
-    startup_tape_process(taper_program);
-    taper_cmd(START_TAPER, datestamp, NULL, 0, NULL);
+    if(conf_runtapes > 0) {
+       startup_tape_process(taper_program);
+       taper_cmd(START_TAPER, datestamp, NULL, 0, NULL);
+    }
 
     /* start initializing: read in databases */
 
@@ -225,9 +238,8 @@ int main(main_argc, main_argv)
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((origqp = read_diskfile(conf_diskfile)) == NULL) {
+    if (read_diskfile(conf_diskfile, &origq) < 0)
        error("could not load disklist \"%s\"", conf_diskfile);
-    }
     amfree(conf_diskfile);
 
     /* set up any configuration-dependent variables */
@@ -276,7 +288,7 @@ int main(main_argc, main_argv)
        newdir = newvstralloc(newdir,
                              hdp->diskdir, "/", timestamp,
                              NULL);
-        if(!mkholdingdir(newdir)) {
+       if(!mkholdingdir(newdir)) {
            hdp->disksize = 0L;
        }
        total_disksize += hdp->disksize;
@@ -292,7 +304,6 @@ int main(main_argc, main_argv)
     if(inparallel > MAX_DUMPERS) inparallel = MAX_DUMPERS;
 
     /* fire up the dumpers now while we are waiting */
-
     if(!nodump) startup_dump_processes(dumper_program, inparallel);
 
     /*
@@ -303,12 +314,12 @@ int main(main_argc, main_argv)
      * in parallel with the planner.
      */
 
-    waitq = *origqp;
-    tapeq.head = tapeq.tail = NULL;
-    roomq.head = roomq.tail = NULL;
-    runq.head = runq.tail = NULL;
+    runq.head = NULL;
+    runq.tail = NULL;
+    waitq = origq;
+    tapeq = read_flush();
 
-    read_flush(&tapeq);
+    roomq.head = roomq.tail = NULL;
 
     log_add(L_STATS, "startup time %s", walltime_str(curclock()));
 
@@ -320,87 +331,35 @@ int main(main_argc, main_argv)
           getconf_str(CNF_DUMPORDER));
     fflush(stdout);
 
-    /* Let's see if the tape is ready */
+    /* ok, planner is done, now lets see if the tape is ready */
 
-    cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1);
+    if(conf_runtapes > 0) {
+       cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1);
 
-    if(cmd != TAPER_OK) {
-       /* no tape, go into degraded mode: dump to holding disk */
-       start_degraded_mode(&runq);
-       FD_CLR(taper,&readset);
+       if(cmd != TAPER_OK) {
+           /* no tape, go into degraded mode: dump to holding disk */
+           need_degraded=1;
+       }
+    }
+    else {
+       need_degraded=1;
     }
-
-    short_dump_state();                                        /* for amstatus */
 
     tape_left = tape_length;
     taper_busy = 0;
     taper_disk = NULL;
+    taper_ev_read = NULL;
+    if(!need_degraded) startaflush();
 
-    /* Start autoflush while waiting for dump schedule */
-    if(!nodump) {
-       /* Start any autoflush tape writes */
-       if (!empty(tapeq)) {
-           startaflush();
-           short_dump_state();                         /* for amstatus */
-
-           /* Process taper results until the schedule arrives */
-           while (1) {
-               FD_ZERO(&selectset);
-               FD_SET(0, &selectset);
-               FD_SET(taper, &selectset);
-
-               if(select(taper+1, (SELECT_ARG_TYPE *)(&selectset), NULL, NULL,
-                         &sleep_time) == -1)
-                   error("select: %s", strerror(errno));
-               if (FD_ISSET(0, &selectset)) break;     /* schedule arrived */
-               if (FD_ISSET(taper, &selectset)) handle_taper_result();
-               short_dump_state();                     /* for amstatus */
-           }
-           
-       }
-
-       /* Read the dump schedule */
-       read_schedule(&waitq, &runq);
-    }
-
-    /* Start any needed flushes */
-    startaflush();
-
-    while(start_some_dumps(&runq) || some_dumps_in_progress() ||
-         any_delayed_disk) {
-       short_dump_state();
-
-       /* wait for results */
-
-       memcpy(&selectset, &readset, sizeof(fd_set));
-       if(select(maxfd+1, (SELECT_ARG_TYPE *)(&selectset),
-                 NULL, NULL, &sleep_time) == -1)
-           error("select: %s", strerror(errno));
-
-       /* handle any results that have come in */
-
-       for(fd = 0; fd <= maxfd; fd++) {
-           /*
-            * The first pass through the following loop, we have
-            * data ready for areads (called by getresult, called by
-            * handle_.*_result).  But that may read more than one record,
-            * so we need to keep processing as long as areads has data.
-            * We will get control back after each record and the buffer
-            * will go empty (indicated by areads_dataready(fd) == 0)
-            * after the last one available has been processed.
-            */
-           while(FD_ISSET(fd, &selectset) || areads_dataready(fd) > 0) {
-               if(fd == taper) handle_taper_result();
-               else handle_dumper_result(fd);
-               FD_CLR(fd, &selectset);
-           }
-       }
+    if(!nodump)
+       schedule_ev_read = event_register(0, EV_READFD, read_schedule, NULL);
 
-    }
+    short_dump_state();
+    event_loop(0);
 
     /* handle any remaining dumps by dumping directly to tape, if possible */
 
-    while(!empty(runq)) {
+    while(!empty(runq) && taper > 0) {
        diskp = dequeue_disk(&runq);
        if(!degraded_mode) {
            int rc = dump_to_tape(diskp);
@@ -419,8 +378,8 @@ int main(main_argc, main_argv)
        }
        else
            log_add(L_FAIL, "%s %s %s %d [%s]",
-                   diskp->host->hostname, diskp->name,
-                   sched(diskp)->datestamp, sched(diskp)->level,
+               diskp->host->hostname, diskp->name, sched(diskp)->datestamp,
+               sched(diskp)->level,
                diskp->no_hold ?
                    "can't dump no-hold disk in degraded mode" :
                    "no more holding disk space");
@@ -474,7 +433,7 @@ int main(main_argc, main_argv)
            who = stralloc("taper");
        }
        if(what != NULL && who == NULL) {
-           ap_snprintf(number, sizeof(number), "%ld", (long)pid);
+           snprintf(number, sizeof(number), "%ld", (long)pid);
            who = stralloc2("unknown pid ", number);
        }
        if(who && what) {
@@ -494,6 +453,7 @@ int main(main_argc, main_argv)
     }
     amfree(newdir);
 
+    check_unfree_serial();
     printf("driver: FINISHED time %s\n", walltime_str(curclock()));
     fflush(stdout);
     log_add(L_FINISH,"date %s time %s", datestamp, walltime_str(curclock()));
@@ -514,21 +474,26 @@ int main(main_argc, main_argv)
     return 0;
 }
 
-void startaflush() {
+static void
+startaflush()
+{
     disk_t *dp = NULL;
     disk_t *fit = NULL;
     char *datestamp;
-
+    unsigned int extra_tapes = 0;
     if(!degraded_mode && !taper_busy && !empty(tapeq)) {
+       
        datestamp = sched(tapeq.head)->datestamp;
        switch(conf_taperalgo) {
        case ALGO_FIRST:
                dp = dequeue_disk(&tapeq);
                break;
-       case ALGO_FIRSTFIT: 
+       case ALGO_FIRSTFIT:
                fit = tapeq.head;
                while (fit != NULL) {
-                   if(sched(fit)->act_size <= tape_left &&
+                   extra_tapes = (fit->tape_splitsize > 0) ? 
+                                               conf_runtapes - current_tape : 0;
+                   if(sched(fit)->act_size <= (tape_left + tape_length*extra_tapes) &&
                       strcmp(sched(fit)->datestamp, datestamp) <= 0) {
                        dp = fit;
                        fit = NULL;
@@ -539,7 +504,7 @@ void startaflush() {
                }
                if(dp) remove_disk(&tapeq, dp);
                break;
-       case ALGO_LARGEST: 
+       case ALGO_LARGEST:
                fit = dp = tapeq.head;
                while (fit != NULL) {
                    if(sched(fit)->act_size > sched(dp)->act_size &&
@@ -550,10 +515,12 @@ void startaflush() {
                }
                if(dp) remove_disk(&tapeq, dp);
                break;
-       case ALGO_LARGESTFIT: 
+       case ALGO_LARGESTFIT:
                fit = tapeq.head;
                while (fit != NULL) {
-                   if(sched(fit)->act_size <= tape_left &&
+                   extra_tapes = (fit->tape_splitsize > 0) ? 
+                                               conf_runtapes - current_tape : 0;
+                   if(sched(fit)->act_size <= (tape_left + tape_length*extra_tapes) &&
                       (!dp || sched(fit)->act_size > sched(dp)->act_size) &&
                       strcmp(sched(fit)->datestamp, datestamp) <= 0) {
                        dp = fit;
@@ -562,7 +529,7 @@ void startaflush() {
                }
                if(dp) remove_disk(&tapeq, dp);
                break;
-       case ALGO_SMALLEST: 
+       case ALGO_SMALLEST:
                break;
        case ALGO_LAST:
                dp = tapeq.tail;
@@ -580,27 +547,40 @@ void startaflush() {
                   strcmp(sched(fit)->datestamp, datestamp) <= 0) {
                    dp = fit;
                }
-               fit = fit->next;
+               fit = fit->next;
            }
            if(dp) remove_disk(&tapeq, dp);
        }
-       taper_disk = dp;
-       taper_busy = 1;
-       taper_cmd(FILE_WRITE, dp, sched(dp)->destname, sched(dp)->level, 
+       if(taper_ev_read == NULL) {
+           taper_ev_read = event_register(taper, EV_READFD,
+                                          handle_taper_result, NULL);
+       }
+       if (dp != NULL) {
+           taper_disk = dp;
+           taper_busy = 1;
+           taper_cmd(FILE_WRITE, dp, sched(dp)->destname, sched(dp)->level,
                  sched(dp)->datestamp);
-       fprintf(stderr,"driver: startaflush: %s %s %s %ld %ld\n",
-               taperalgo2str(conf_taperalgo), dp->host->hostname,
-               dp->name, sched(taper_disk)->act_size, tape_left);
-       if(sched(dp)->act_size <= tape_left)
-           tape_left -= sched(dp)->act_size;
-       else
-           tape_left = 0;
+           fprintf(stderr,"driver: startaflush: %s %s %s %ld %ld\n",
+                   taperalgo2str(conf_taperalgo), dp->host->hostname,
+                   dp->name, sched(taper_disk)->act_size, tape_left);
+           if(sched(dp)->act_size <= tape_left)
+               tape_left -= sched(dp)->act_size;
+           else
+               tape_left = 0;
+       } else {
+           error("FATAL: Taper marked busy and no work found.");
+           /*NOTREACHED*/
+       }
+    } else if(!taper_busy && taper_ev_read != NULL) {
+       event_release(taper_ev_read);
+       taper_ev_read = NULL;
     }
 }
 
 
-int client_constrained(dp)
-disk_t *dp;
+static int
+client_constrained(dp)
+    disk_t *dp;
 {
     disk_t *dp2;
 
@@ -624,86 +604,109 @@ disk_t *dp;
     return 0;
 }
 
-int start_some_dumps(rq)
-disklist_t *rq;
+static void
+start_some_dumps(rq)
+    disklist_t *rq;
 {
-    int total, cur_idle;
-    disk_t *diskp, *diskp_accept;
-    dumper_t *dumper;
+    int cur_idle;
+    disk_t *diskp, *delayed_diskp, *diskp_accept;
     assignedhd_t **holdp=NULL, **holdp_accept;
-    time_t now = time(NULL);
+    const time_t now = time(NULL);
+    cmd_t cmd;
+    int result_argc;
+    char *result_argv[MAX_ARGS+1];
+    chunker_t *chunker;
+    dumper_t *dumper;
+    char dumptype;
+    char *dumporder;
 
-    total = 0;
     idle_reason = IDLE_NO_DUMPERS;
-    sleep_time.tv_sec = SLEEP_MAX;
-    sleep_time.tv_usec = 0;
-    any_delayed_disk = 0;
+    sleep_time = 0;
 
-    if(rq->head == NULL) {
-       idle_reason = 0;
-       return 0;
+    if(dumpers_ev_time != NULL) {
+       event_release(dumpers_ev_time);
+       dumpers_ev_time = NULL;
     }
 
-    /*
-     * A potential problem with starting from the bottom of the dump time
-     * distribution is that a slave host will have both one of the shortest
-     * and one of the longest disks, so starting its shortest disk first will
-     * tie up the host and eliminate its longest disk from consideration the
-     * first pass through.  This could cause a big delay in starting that long
-     * disk, which could drag out the whole night's dumps.
-     *
-     * While starting from the top of the dump time distribution solves the
-     * above problem, this turns out to be a bad idea, because the big dumps
-     * will almost certainly pack the holding disk completely, leaving no
-     * room for even one small dump to start.  This ends up shutting out the
-     * small-end dumpers completely (they stay idle).
-     *
-     * The introduction of multiple simultaneous dumps to one host alleviates
-     * the biggest&smallest dumps problem: both can be started at the
-     * beginning.
-     */
-    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++) {
-       if(dumper->busy || dumper->down) continue;
-       /* found an idle dumper, now find a disk for it */
-       diskp = rq->head;
+    for (dumper = dmptable; dumper < dmptable+inparallel; dumper++) {
+
+       if( dumper->busy ) {
+           continue;
+       }
+
+       if (dumper->ev_read != NULL) {
+/*         assert(dumper->ev_read == NULL);*/
+           event_release(dumper->ev_read);
+           dumper->ev_read = NULL;
+       }
+
+       /*
+        * A potential problem with starting from the bottom of the dump time
+        * distribution is that a slave host will have both one of the shortest
+        * and one of the longest disks, so starting its shortest disk first will
+        * tie up the host and eliminate its longest disk from consideration the
+        * first pass through.  This could cause a big delay in starting that long
+        * disk, which could drag out the whole night's dumps.
+        *
+        * While starting from the top of the dump time distribution solves the
+        * above problem, this turns out to be a bad idea, because the big dumps
+        * will almost certainly pack the holding disk completely, leaving no
+        * room for even one small dump to start.  This ends up shutting out the
+        * small-end dumpers completely (they stay idle).
+        *
+        * The introduction of multiple simultaneous dumps to one host alleviates
+        * the biggest&smallest dumps problem: both can be started at the
+        * beginning.
+        */
+
        diskp_accept = NULL;
        holdp_accept = NULL;
-
-       if(idle_reason == IDLE_NO_DUMPERS)
-           idle_reason = NOT_IDLE;
+       delayed_diskp = NULL;
 
        cur_idle = NOT_IDLE;
 
-       while(diskp) {
+       dumporder = getconf_str(CNF_DUMPORDER);
+       if(strlen(dumporder) > (dumper-dmptable)) {
+           dumptype = dumporder[dumper-dmptable];
+       }
+       else {
+           if(dumper-dmptable < 3)
+               dumptype = 't';
+           else
+               dumptype = 'T';
+       }
+
+       for(diskp = rq->head; diskp != NULL; diskp = diskp->next) {
            assert(diskp->host != NULL && sched(diskp) != NULL);
 
            /* round estimate to next multiple of DISK_BLOCK_KB */
            sched(diskp)->est_size = am_round(sched(diskp)->est_size,
                                              DISK_BLOCK_KB);
 
-           if(diskp->host->start_t > now) {
+           if (diskp->host->start_t > now) {
                cur_idle = max(cur_idle, IDLE_START_WAIT);
-               sleep_time.tv_sec = min(diskp->host->start_t - now, 
-                                       sleep_time.tv_sec);
-               any_delayed_disk = 1;
-           }
-           else if(diskp->start_t > now) {
+               if (delayed_diskp == NULL || sleep_time > diskp->host->start_t) {
+                   delayed_diskp = diskp;
+                   sleep_time = diskp->host->start_t;
+               }
+           else if(diskp->start_t > now) {
                cur_idle = max(cur_idle, IDLE_START_WAIT);
-               sleep_time.tv_sec = min(diskp->start_t - now, 
-                                       sleep_time.tv_sec);
-               any_delayed_disk = 1;
-           }
-           else if(diskp->host->netif->curusage > 0 &&
-                   sched(diskp)->est_kps > free_kps(diskp->host->netif))
+               if (delayed_diskp == NULL || sleep_time > diskp->start_t) {
+                   delayed_diskp = diskp;
+                   sleep_time = diskp->start_t;
+               }
+           } else if (diskp->host->netif->curusage > 0 &&
+                      sched(diskp)->est_kps > free_kps(diskp->host->netif)) {
                cur_idle = max(cur_idle, IDLE_NO_BANDWIDTH);
-           else if(sched(diskp)->no_space)
+           } else if(sched(diskp)->no_space) {
                cur_idle = max(cur_idle, IDLE_NO_DISKSPACE);
-           else if((holdp = find_diskspace(sched(diskp)->est_size,&cur_idle,NULL)) == NULL)
+           } else if ((holdp =
+               find_diskspace(sched(diskp)->est_size,&cur_idle,NULL)) == NULL) {
                cur_idle = max(cur_idle, IDLE_NO_DISKSPACE);
-           else if(diskp->no_hold) {
+           } else if (diskp->no_hold) {
                free_assignedhd(holdp);
                cur_idle = max(cur_idle, IDLE_NO_HOLD);
-           } else if(client_constrained(diskp)) {
+           } else if (client_constrained(diskp)) {
                free_assignedhd(holdp);
                cur_idle = max(cur_idle, IDLE_CLIENT_CONSTRAINED);
            } else {
@@ -711,17 +714,6 @@ disklist_t *rq;
                /* disk fits, dump it */
                int accept = !diskp_accept;
                if(!accept) {
-                   char dumptype;
-                   char *dumporder = getconf_str(CNF_DUMPORDER);
-                   if(strlen(dumporder) <= (dumper-dmptable)) {
-                       if(dumper-dmptable < 3)
-                           dumptype = 't';
-                       else
-                           dumptype = 'T';
-                   }
-                   else {
-                       dumptype = dumporder[dumper-dmptable];
-                   }
                    switch(dumptype) {
                      case 's': accept = (sched(diskp)->est_size < sched(diskp_accept)->est_size);
                                break;
@@ -735,7 +727,7 @@ disklist_t *rq;
                                break;
                      case 'B': accept = (sched(diskp)->est_kps > sched(diskp_accept)->est_kps);
                                break;
-                     default:  log_add(L_WARNING, "Unknown dumporder character \'%c\', using 's'.\n",
+                     default:  log_add(L_WARNING, "Unknown dumporder character \'%c\', using 's'.\n",
                                        dumptype);
                                accept = (sched(diskp)->est_size < sched(diskp_accept)->est_size);
                                break;
@@ -755,60 +747,94 @@ disklist_t *rq;
                    free_assignedhd(holdp);
                }
            }
-           diskp = diskp->next;
        }
 
        diskp = diskp_accept;
        holdp = holdp_accept;
-       if(diskp) {
-           cur_idle = NOT_IDLE;
+
+       idle_reason = max(idle_reason, cur_idle);
+
+       /*
+        * If we have no disk at this point, and there are disks that
+        * are delayed, then schedule a time event to call this dumper
+        * with the disk with the shortest delay.
+        */
+       if (diskp == NULL && delayed_diskp != NULL) {
+           assert(sleep_time > now);
+           sleep_time -= now;
+           dumpers_ev_time = event_register(sleep_time, EV_TIME,
+               handle_dumpers_time, &runq);
+           return;
+       } else if (diskp != NULL) {
            sched(diskp)->act_size = 0;
            allocate_bandwidth(diskp->host->netif, sched(diskp)->est_kps);
            sched(diskp)->activehd = assign_holdingdisk(holdp, diskp);
            amfree(holdp);
-           diskp->host->inprogress += 1;       /* host is now busy */
+           sched(diskp)->destname = newstralloc(sched(diskp)->destname,
+                                                sched(diskp)->holdp[0]->destname);
+           diskp->host->inprogress++;  /* host is now busy */
            diskp->inprogress = 1;
            sched(diskp)->dumper = dumper;
-           sched(diskp)->timestamp = time((time_t *)0);
+           sched(diskp)->timestamp = now;
 
+           dumper->ev_read = event_register(dumper->fd, EV_READFD,
+               handle_dumper_result, dumper);
            dumper->busy = 1;           /* dumper is now busy */
            dumper->dp = diskp;         /* link disk to dumper */
-           total++;
            remove_disk(rq, diskp);             /* take it off the run queue */
-           dumper_cmd(dumper, FILE_DUMP, diskp);
-           diskp->host->start_t = time(NULL) + 15;
+
+           sched(diskp)->origsize = -1;
+           sched(diskp)->dumpsize = -1;
+           sched(diskp)->dumptime = -1;
+           sched(diskp)->tapetime = -1;
+           chunker = dumper->chunker;
+           chunker->result = LAST_TOK;
+           dumper->result = LAST_TOK;
+           startup_chunk_process(chunker,chunker_program);
+           chunker->dumper = dumper;
+           chunker_cmd(chunker, PORT_WRITE, diskp);
+           cmd = getresult(chunker->fd, 1, &result_argc, result_argv, MAX_ARGS+1);
+           if(cmd != PORT) {
+               printf("driver: did not get PORT from %s for %s:%s\n",
+                      chunker->name, diskp->host->hostname, diskp->name);
+               fflush(stdout);
+               return ;        /* fatal problem */
+           }
+           chunker->ev_read = event_register(chunker->fd, EV_READFD,
+                   handle_chunker_result, chunker);
+           dumper->output_port = atoi(result_argv[2]);
+
+           dumper_cmd(dumper, PORT_DUMP, diskp);
+
+           diskp->host->start_t = now + 15;
+       } else if (/* cur_idle != NOT_IDLE && */
+           (num_busy_dumpers() > 0 || taper_busy)) {
+           /*
+            * We are constrained.
+            */
        }
-       idle_reason = max(idle_reason, cur_idle);
     }
-    return total;
-}
-
-int sort_by_priority_reversed(a, b)
-disk_t *a, *b;
-{
-    if(sched(b)->priority - sched(a)->priority != 0)
-       return sched(b)->priority - sched(a)->priority;
-    else
-       return sort_by_time(a, b);
 }
 
-int sort_by_time(a, b)
-disk_t *a, *b;
+/*
+ * This gets called when a dumper is delayed for some reason.  It may
+ * be because a disk has a delayed start, or amanda is constrained
+ * by network or disk limits.
+ */
+static void
+handle_dumpers_time(cookie)
+    void *cookie;
 {
-    long diff;
-
-    if ((diff = sched(a)->est_time - sched(b)->est_time) < 0) {
-       return -1;
-    } else if (diff > 0) {
-       return 1;
-    } else {
-       return 0;
-    }
+    disklist_t *runq = cookie;
+    event_release(dumpers_ev_time);
+    dumpers_ev_time = NULL; 
+    start_some_dumps(runq);
 }
 
-void dump_schedule(qp, str)
-disklist_t *qp;
-char *str;
+static void
+dump_schedule(qp, str)
+    disklist_t *qp;
+    char *str;
 {
     disk_t *dp;
 
@@ -822,14 +848,19 @@ char *str;
     printf("--------\n");
 }
 
-
-void start_degraded_mode(queuep)
-disklist_t *queuep;
+static void
+start_degraded_mode(queuep)
+    disklist_t *queuep;
 {
     disk_t *dp;
     disklist_t newq;
     unsigned long est_full_size;
 
+    if (taper_ev_read != NULL) {
+       event_release(taper_ev_read);
+       taper_ev_read = NULL;
+    }
+
     newq.head = newq.tail = 0;
 
     dump_schedule(queuep, "before start degraded mode");
@@ -840,11 +871,11 @@ disklist_t *queuep;
 
        if(sched(dp)->level != 0)
            /* go ahead and do the disk as-is */
-           insert_disk(&newq, dp, sort_by_priority_reversed);
+           enqueue_disk(&newq, dp);
        else {
            if (reserved_space + est_full_size + sched(dp)->est_size
                <= total_disksize) {
-               insert_disk(&newq, dp, sort_by_priority_reversed);
+               enqueue_disk(&newq, dp);
                est_full_size += sched(dp)->est_size;
            }
            else if(sched(dp)->degr_level != -1) {
@@ -853,12 +884,12 @@ disklist_t *queuep;
                sched(dp)->est_size = sched(dp)->degr_size;
                sched(dp)->est_time = sched(dp)->degr_time;
                sched(dp)->est_kps  = sched(dp)->degr_kps;
-               insert_disk(&newq, dp, sort_by_priority_reversed);
+               enqueue_disk(&newq, dp);
            }
            else {
-               log_add(L_FAIL, "%s %s %s %d [can't switch to incremental dump]",
-                       dp->host->hostname, dp->name,
-                       sched(dp)->datestamp, sched(dp)->level);
+               log_add(L_FAIL,"%s %s %s %d [can't switch to incremental dump]",
+                       dp->host->hostname, dp->name, sched(dp)->datestamp,
+                       sched(dp)->level);
            }
        }
     }
@@ -869,12 +900,13 @@ disklist_t *queuep;
     dump_schedule(queuep, "after start degraded mode");
 }
 
-void continue_dumps()
+
+static void continue_port_dumps()
 {
-disk_t *dp, *ndp;
-assignedhd_t **h;
-int active_dumpers=0, busy_dumpers=0, i;
-dumper_t *dumper;
+    disk_t *dp, *ndp;
+    assignedhd_t **h;
+    int active_dumpers=0, busy_dumpers=0, i;
+    dumper_t *dumper;
 
     /* First we try to grant diskspace to some dumps waiting for it. */
     for( dp = roomq.head; dp; dp = ndp ) {
@@ -882,13 +914,14 @@ dumper_t *dumper;
        /* find last holdingdisk used by this dump */
        for( i = 0, h = sched(dp)->holdp; h[i+1]; i++ );
        /* find more space */
-       h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size, &active_dumpers, h[i] );
+       h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size,
+                           &active_dumpers, h[i] );
        if( h ) {
            for(dumper = dmptable; dumper < dmptable + inparallel &&
                                   dumper->dp != dp; dumper++);
            assert( dumper < dmptable + inparallel );
            sched(dp)->activehd = assign_holdingdisk( h, dp );
-           dumper_cmd( dumper, CONTINUE, dp );
+           chunker_cmd( dumper->chunker, CONTINUE, dp );
            amfree(h);
            remove_disk( &roomq, dp );
        }
@@ -909,17 +942,18 @@ dumper_t *dumper;
      * it will be dumped directly to tape. Actually, case c is a special
      * manifestation of case b) where only one dumper is busy.
      */
-    for( dp=NULL, dumper = dmptable; dumper < dmptable + inparallel; dumper++) {
+    for(dp=NULL, dumper = dmptable; dumper < (dmptable+inparallel); dumper++) {
        if( dumper->busy ) {
            busy_dumpers++;
            if( !find_disk(&roomq, dumper->dp) ) {
                active_dumpers++;
-           } else if( !dp || sched(dp)->est_size > sched(dumper->dp)->est_size ) {
+           } else if( !dp || 
+                      sched(dp)->est_size > sched(dumper->dp)->est_size ) {
                dp = dumper->dp;
            }
        }
     }
-    if( !active_dumpers && busy_dumpers > 0 && 
+    if((dp != NULL) && (active_dumpers == 0) && (busy_dumpers > 0) && 
         ((!taper_busy && empty(tapeq)) || degraded_mode) &&
        pending_aborts == 0 ) { /* not case a */
        if( busy_dumpers == 1 ) { /* case c */
@@ -930,411 +964,584 @@ dumper_t *dumper;
         * We abort that dump, hopefully not wasting too much time retrying it.
         */
        remove_disk( &roomq, dp );
+       chunker_cmd( sched(dp)->dumper->chunker, ABORT, NULL );
        dumper_cmd( sched(dp)->dumper, ABORT, NULL );
        pending_aborts++;
     }
 }
 
-void handle_taper_result()
+
+static void
+handle_taper_result(void *cookie)
 {
     disk_t *dp;
     int filenum;
     cmd_t cmd;
     int result_argc;
     char *result_argv[MAX_ARGS+1];
+    int avail_tapes = 0;
+    
+    assert(cookie == NULL);
+    
+    do {
+        
+       short_dump_state();
+        
+       cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1);
+        
+       switch(cmd) {
+            
+       case PARTIAL:
+       case DONE:      /* DONE <handle> <label> <tape file> <err mess> */
+           if(result_argc != 5) {
+               error("error: [taper DONE result_argc != 5: %d", result_argc);
+           }
+            
+           dp = serial2disk(result_argv[2]);
+           free_serial(result_argv[2]);
+            
+           filenum = atoi(result_argv[4]);
+           if(cmd == DONE) {
+               update_info_taper(dp, result_argv[3], filenum,
+                                  sched(dp)->level);
+           }
+            
+           delete_diskspace(dp);
+            
+           printf("driver: finished-cmd time %s taper wrote %s:%s\n",
+                  walltime_str(curclock()), dp->host->hostname, dp->name);
+           fflush(stdout);
+            
+           amfree(sched(dp)->destname);
+           amfree(sched(dp)->dumpdate);
+           amfree(sched(dp)->degr_dumpdate);
+           amfree(sched(dp)->datestamp);
+           amfree(dp->up);
+            
+           taper_busy = 0;
+           taper_disk = NULL;
+           startaflush();
+            
+           /* continue with those dumps waiting for diskspace */
+           continue_port_dumps();
+           break;
+            
+       case TRYAGAIN:  /* TRY-AGAIN <handle> <err mess> */
+           if (result_argc < 2) {
+               error("error [taper TRYAGAIN result_argc < 2: %d]",
+                     result_argc);
+           }
+           dp = serial2disk(result_argv[2]);
+           free_serial(result_argv[2]);
+           printf("driver: taper-tryagain time %s disk %s:%s\n",
+                  walltime_str(curclock()), dp->host->hostname, dp->name);
+           fflush(stdout);
+            
+           /* See how many tapes we have left, but we alwyays
+              retry once (why?) */
+           current_tape++;
+           if(dp->tape_splitsize > 0)
+               avail_tapes = conf_runtapes - current_tape;
+           else
+               avail_tapes = 0;
+            
+           if(sched(dp)->attempted > avail_tapes) {
+               log_add(L_FAIL, "%s %s %s %d [too many taper retries]",
+                        dp->host->hostname, dp->name, sched(dp)->datestamp,
+                        sched(dp)->level);
+               printf("driver: taper failed %s %s %s, too many taper retry\n",
+                       result_argv[2], dp->host->hostname, dp->name);
+           }
+           else {
+               /* Re-insert into taper queue. */
+               sched(dp)->attempted++;
+               headqueue_disk(&tapeq, dp);
+           }
+            
+           tape_left = tape_length;
+            
+           /* run next thing from queue */
+            
+           taper_busy = 0;
+           taper_disk = NULL;
+           startaflush();
+           continue_port_dumps();
+           break;
+            
+        case SPLIT_CONTINUE:  /* SPLIT_CONTINUE <handle> <new_label> */
+            if (result_argc != 3) {
+                error("error [taper SPLIT_CONTINUE result_argc != 3: %d]",
+                      result_argc);
+            }
+            
+            break;
+        case SPLIT_NEEDNEXT:  /* SPLIT-NEEDNEXT <handle> <kb written> */
+            if (result_argc != 3) {
+                error("error [taper SPLIT_NEEDNEXT result_argc != 3: %d]",
+                      result_argc);
+            }
+            
+            /* Update our tape counter and reset tape_left */
+            current_tape++;
+            tape_left = tape_length;
+            
+            /* Reduce the size of the dump by amount written and reduce
+               tape_left by the amount left over */
+            dp = serial2disk(result_argv[2]);
+            sched(dp)->act_size -= atoi(result_argv[3]);
+            if (sched(dp)->act_size < tape_left)
+                tape_left -= sched(dp)->act_size;
+            else
+                tape_length = 0;
+            
+            break;
+            
+        case TAPE_ERROR: /* TAPE-ERROR <handle> <err mess> */
+            dp = serial2disk(result_argv[2]);
+            free_serial(result_argv[2]);
+            printf("driver: finished-cmd time %s taper wrote %s:%s\n",
+                   walltime_str(curclock()), dp->host->hostname, dp->name);
+            fflush(stdout);
+            log_add(L_WARNING, "Taper  error: %s", result_argv[3]);
+            /* FALLSTHROUGH */
+
+        case BOGUS:
+            if (cmd == BOGUS) {
+               log_add(L_WARNING, "Taper protocol error");
+            }
+            /*
+             * Since we've gotten a taper error, we can't send anything more
+             * to the taper.  Go into degraded mode to try to get everthing
+             * onto disk.  Later, these dumps can be flushed to a new tape.
+             * The tape queue is zapped so that it appears empty in future
+             * checks. If there are dumps waiting for diskspace to be freed,
+             * cancel one.
+             */
+            if(!nodump) {
+                log_add(L_WARNING,
+                        "going into degraded mode because of taper component error.");
+                start_degraded_mode(&runq);
+            }
+            tapeq.head = tapeq.tail = NULL;
+            taper_busy = 0;
+            taper_disk = NULL;
+            if(taper_ev_read != NULL) {
+                event_release(taper_ev_read);
+                taper_ev_read = NULL;
+            }
+            if(cmd != TAPE_ERROR) aclose(taper);
+            continue_port_dumps();
+            break;
+
+       default:
+            error("driver received unexpected token (%s) from taper",
+                  cmdstr[cmd]);
+       }
+       /*
+        * Wakeup any dumpers that are sleeping because of network
+        * or disk constraints.
+        */
+       start_some_dumps(&runq);
+        
+    } while(areads_dataready(taper));
+}
 
-    cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1);
+static dumper_t *
+idle_dumper()
+{
+    dumper_t *dumper;
 
-    switch(cmd) {
+    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++)
+       if(!dumper->busy && !dumper->down) return dumper;
 
-    case DONE: /* DONE <handle> <label> <tape file> <err mess> */
-       if(result_argc != 5) {
-           error("error: [taper DONE result_argc != 5: %d", result_argc);
-       }
+    return NULL;
+}
 
-       dp = serial2disk(result_argv[2]);
-       free_serial(result_argv[2]);
+static int
+num_busy_dumpers()
+{
+    dumper_t *dumper;
+    int n;
 
-       filenum = atoi(result_argv[4]);
-       update_info_taper(dp, result_argv[3], filenum, sched(dp)->level);
+    n = 0;
+    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++)
+       if(dumper->busy) n += 1;
 
-       delete_diskspace(dp);
+    return n;
+}
 
-       printf("driver: finished-cmd time %s taper wrote %s:%s\n",
-              walltime_str(curclock()), dp->host->hostname, dp->name);
-       fflush(stdout);
 
-       amfree(sched(dp)->dumpdate);
-       amfree(sched(dp)->degr_dumpdate);
-       amfree(sched(dp)->datestamp);
-       amfree(dp->up);
+static void
+dumper_result(dp)
+    disk_t *dp;
+{
+    dumper_t *dumper;
+    chunker_t *chunker;
+    assignedhd_t **h=NULL;
+    int activehd, i, dummy;
+    long size;
+    int is_partial;
 
-       taper_busy = 0;
-       taper_disk = NULL;
-       startaflush();
-       continue_dumps(); /* continue with those dumps waiting for diskspace */
-       break;
+    dumper = sched(dp)->dumper;
+    chunker = dumper->chunker;
 
-    case TRYAGAIN:  /* TRY-AGAIN <handle> <err mess> */
-       if (result_argc < 2) {
-           error("error [taper TRYAGAIN result_argc < 2: %d]", result_argc);
-       }
-       dp = serial2disk(result_argv[2]);
-       free_serial(result_argv[2]);
-       printf("driver: taper-tryagain time %s disk %s:%s\n",
-              walltime_str(curclock()), dp->host->hostname, dp->name);
-       fflush(stdout);
+    free_serial_dp(dp);
 
-       /* re-insert into taper queue */
+    h = sched(dp)->holdp;
+    activehd = sched(dp)->activehd;
 
-       if(sched(dp)->attempted) {
-           log_add(L_FAIL, "%s %s %d %s [too many taper retries]",
-                   dp->host->hostname, dp->name, sched(dp)->level,
-                   sched(dp)->datestamp);
-           printf("driver: taper failed %s %s %s, too many taper retry\n", result_argv[2], dp->host->hostname, dp->name);
-       }
-       else {
-           sched(dp)->attempted++;
-           headqueue_disk(&tapeq, dp);
-       }
+    if(dumper->result == DONE && chunker->result == DONE) {
+       update_info_dumper(dp, sched(dp)->origsize,
+                          sched(dp)->dumpsize, sched(dp)->dumptime);
+    }
 
-       tape_left = tape_length;
+    deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
 
-       /* run next thing from queue */
-       taper_busy = 0;
-       taper_disk = NULL;
-       startaflush();
-       continue_dumps(); /* continue with those dumps waiting for diskspace */
+    is_partial = dumper->result != DONE || chunker->result != DONE;
+    rename_tmp_holding(sched(dp)->destname, !is_partial);
 
-       break;
+    dummy = 0;
+    for( i = 0, h = sched(dp)->holdp; i < activehd; i++ ) {
+       dummy += h[i]->used;
+    }
 
-    case TAPE_ERROR: /* TAPE-ERROR <handle> <err mess> */
-       dp = serial2disk(result_argv[2]);
-       free_serial(result_argv[2]);
-       printf("driver: finished-cmd time %s taper wrote %s:%s\n",
-              walltime_str(curclock()), dp->host->hostname, dp->name);
-       fflush(stdout);
-       /* Note: fall through code... */
+    size = size_holding_files(sched(dp)->destname, 0);
+    h[activehd]->used = size - dummy;
+    holdalloc(h[activehd]->disk)->allocated_dumpers--;
+    adjust_diskspace(dp, DONE);
 
-    case BOGUS:
-       /*
-        * Since we've gotten a tape error, we can't send anything more
-        * to the taper.  Go into degraded mode to try to get everthing
-        * onto disk.  Later, these dumps can be flushed to a new tape.
-        * The tape queue is zapped so that it appears empty in future
-        * checks. If there are dumps waiting for diskspace to be freed,
-        * cancel one.
-        */
-       if(!nodump) {
-           log_add(L_WARNING,
-                   "going into degraded mode because of tape error.");
-       }
-       start_degraded_mode(&runq);
-       taper_busy = 0;
-       taper_disk = NULL;
-       tapeq.head = tapeq.tail = NULL;
-       FD_CLR(taper,&readset);
-       if(cmd != TAPE_ERROR) aclose(taper);
-       continue_dumps();
-       break;
-    default:
-       error("driver received unexpected token (%d) from taper", cmd);
+    sched(dp)->attempted += 1;
+
+    if((dumper->result != DONE || chunker->result != DONE) &&
+       sched(dp)->attempted <= 1) {
+       delete_diskspace(dp);
+       enqueue_disk(&runq, dp);
+    }
+    else if(size > DISK_BLOCK_KB) {
+       sched(dp)->attempted = 0;
+       enqueue_disk(&tapeq, dp);
+       startaflush();
+    }
+    else {
+       delete_diskspace(dp);
     }
+
+    dumper->busy = 0;
+    dp->host->inprogress -= 1;
+    dp->inprogress = 0;
+
+    waitpid(chunker->pid, NULL, 0 );
+    aclose(chunker->fd);
+    chunker->fd = -1;
+    chunker->down = 1;
+    
+    dp = NULL;
+    continue_port_dumps();
+    /*
+     * Wakeup any dumpers that are sleeping because of network
+     * or disk constraints.
+     */
+    start_some_dumps(&runq);
 }
 
 
-dumper_t *idle_dumper()
+static void
+handle_dumper_result(cookie)
+    void *cookie;
 {
-    dumper_t *dumper;
+    /*static int pending_aborts = 0;*/
+    dumper_t *dumper = cookie;
+    disk_t *dp, *sdp;
+    cmd_t cmd;
+    int result_argc;
+    char *result_argv[MAX_ARGS+1];
 
-    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++)
-       if(!dumper->busy && !dumper->down) return dumper;
+    assert(dumper != NULL);
+    dp = dumper->dp;
+    assert(dp != NULL && sched(dp) != NULL);
 
-    return NULL;
-}
+    do {
 
-int some_dumps_in_progress()
-{
-    dumper_t *dumper;
+       short_dump_state();
 
-    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++)
-       if(dumper->busy) return 1;
+       cmd = getresult(dumper->fd, 1, &result_argc, result_argv, MAX_ARGS+1);
 
-    return taper_busy;
-}
+       if(cmd != BOGUS) {
+           /* result_argv[2] always contains the serial number */
+           sdp = serial2disk(result_argv[2]);
+           assert(sdp == dp);
+       }
 
-int num_busy_dumpers()
-{
-    dumper_t *dumper;
-    int n;
+       switch(cmd) {
 
-    n = 0;
-    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++)
-       if(dumper->busy) n += 1;
+       case DONE: /* DONE <handle> <origsize> <dumpsize> <dumptime> <errstr> */
+           if(result_argc != 6) {
+               error("error [dumper DONE result_argc != 6: %d]", result_argc);
+           }
 
-    return n;
-}
+           /*free_serial(result_argv[2]);*/
 
-dumper_t *lookup_dumper(fd)
-int fd;
-{
-    dumper_t *dumper;
+           sched(dp)->origsize = (long)atof(result_argv[3]);
+           sched(dp)->dumptime = (long)atof(result_argv[5]);
 
-    for(dumper = dmptable; dumper < dmptable+inparallel; dumper++)
-       if(dumper->outfd == fd) return dumper;
+           printf("driver: finished-cmd time %s %s dumped %s:%s\n",
+                  walltime_str(curclock()), dumper->name,
+                  dp->host->hostname, dp->name);
+           fflush(stdout);
 
-    return NULL;
+           dumper->result = cmd;
+
+           break;
+
+       case TRYAGAIN: /* TRY-AGAIN <handle> <errstr> */
+           /*
+            * Requeue this disk, and fall through to the FAILED
+            * case for cleanup.
+            */
+           if(sched(dp)->attempted) {
+               log_add(L_FAIL, "%s %s %s %d [too many dumper retry: %s]",
+                   dp->host->hostname, dp->name, sched(dp)->datestamp,
+                   sched(dp)->level, result_argv[3]);
+               printf("driver: dump failed %s %s %s, too many dumper retry: %s\n",
+                       result_argv[2], dp->host->hostname, dp->name,
+                       result_argv[3]);
+           }
+           /* FALLTHROUGH */
+       case FAILED: /* FAILED <handle> <errstr> */
+           /*free_serial(result_argv[2]);*/
+           dumper->result = cmd;
+           break;
+
+       case ABORT_FINISHED: /* ABORT-FINISHED <handle> */
+           /*
+            * We sent an ABORT from the NO-ROOM case because this dump
+            * wasn't going to fit onto the holding disk.  We now need to
+            * clean up the remains of this image, and try to finish
+            * other dumps that are waiting on disk space.
+            */
+           assert(pending_aborts);
+           /*free_serial(result_argv[2]);*/
+           dumper->result = cmd;
+           break;
+
+       case BOGUS:
+           /* either EOF or garbage from dumper.  Turn it off */
+           log_add(L_WARNING, "%s pid %ld is messed up, ignoring it.\n",
+                   dumper->name, (long)dumper->pid);
+           event_release(dumper->ev_read);
+           dumper->ev_read = NULL;
+           aclose(dumper->fd);
+           dumper->busy = 0;
+           dumper->down = 1;   /* mark it down so it isn't used again */
+           if(dp) {
+               /* if it was dumping something, zap it and try again */
+               if(sched(dp)->attempted) {
+               log_add(L_FAIL, "%s %s %s %d [%s died]",
+                       dp->host->hostname, dp->name, sched(dp)->datestamp,
+                       sched(dp)->level, dumper->name);
+               }
+               else {
+               log_add(L_WARNING, "%s died while dumping %s:%s lev %d.",
+                       dumper->name, dp->host->hostname, dp->name,
+                       sched(dp)->level);
+               }
+           }
+           dumper->result = cmd;
+           break;
+
+       default:
+           assert(0);
+       }
+       /* send the dumper result to the chunker */
+       if(dumper->chunker->down == 0 && dumper->chunker->fd != -1) {
+           if(cmd == DONE) {
+               chunker_cmd(dumper->chunker, DONE, dp);
+           }
+           else {
+               chunker_cmd(dumper->chunker, FAILED, dp);
+           }
+       }
+
+       if(dumper->result != LAST_TOK && dumper->chunker->result != LAST_TOK)
+           dumper_result(dp);
+
+    } while(areads_dataready(dumper->fd));
 }
 
 
-void handle_dumper_result(fd)
-     int fd;
+static void
+handle_chunker_result(cookie)
+    void *cookie;
 {
+    /*static int pending_aborts = 0;*/
+    chunker_t *chunker = cookie;
     assignedhd_t **h=NULL;
     dumper_t *dumper;
     disk_t *dp, *sdp;
-    long origsize;
-    long dumpsize;
-    long dumptime;
     cmd_t cmd;
     int result_argc;
     char *result_argv[MAX_ARGS+1];
-    int i, dummy;
+    int dummy;
     int activehd = -1;
 
-    dumper = lookup_dumper(fd);
+
+    assert(chunker != NULL);
+    dumper = chunker->dumper;
+    assert(dumper != NULL);
     dp = dumper->dp;
-    assert(dp && sched(dp) && sched(dp)->destname);
+    assert(dp != NULL);
+    assert(sched(dp) != NULL);
+    assert(sched(dp)->destname != NULL);
+    assert(dp != NULL && sched(dp) != NULL && sched(dp)->destname);
 
     if(dp && sched(dp) && sched(dp)->holdp) {
        h = sched(dp)->holdp;
        activehd = sched(dp)->activehd;
     }
 
-    cmd = getresult(fd, 1, &result_argc, result_argv, MAX_ARGS+1);
+    do {
 
-    if(cmd != BOGUS) {
-       sdp = serial2disk(result_argv[2]); /* result_argv[2] always contains the serial number */
-       assert(sdp == dp);
-    }
+       short_dump_state();
 
-    switch(cmd) {
+       cmd = getresult(chunker->fd, 1, &result_argc, result_argv, MAX_ARGS+1);
 
-    case DONE: /* DONE <handle> <origsize> <dumpsize> <dumptime> <err str> */
-       if(result_argc != 6) {
-           error("error [dumper DONE result_argc != 6: %d]", result_argc);
+       if(cmd != BOGUS) {
+           /* result_argv[2] always contains the serial number */
+           sdp = serial2disk(result_argv[2]);
+           assert(sdp == dp);
        }
 
-       free_serial(result_argv[2]);
-
-       origsize = (long)atof(result_argv[3]);
-       dumpsize = (long)atof(result_argv[4]);
-       dumptime = (long)atof(result_argv[5]);
-       update_info_dumper(dp, origsize, dumpsize, dumptime);
+       switch(cmd) {
 
-       /* adjust holdp[active]->used using the real dumpsize and all other
-        * holdp[i]->used as an estimate.
-        */
+       case PARTIAL: /* PARTIAL <handle> <dumpsize> <errstr> */
+       case DONE: /* DONE <handle> <dumpsize> <errstr> */
+           if(result_argc != 4) {
+               error("error [chunker %s result_argc != 4: %d]", cmdstr[cmd],
+                     result_argc);
+           }
+           /*free_serial(result_argv[2]);*/
 
-       dummy = 0;
-       for( i = 0, h = sched(dp)->holdp; i < activehd; i++ ) {
-           dummy += h[i]->used;
-       }
+           sched(dp)->dumpsize = (long)atof(result_argv[3]);
 
-       rename_tmp_holding(sched(dp)->destname, 1);
-       assert( h && activehd >= 0 );
-       h[activehd]->used = size_holding_files(sched(dp)->destname) - dummy;
-       deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
-       holdalloc(h[activehd]->disk)->allocated_dumpers--;
-       adjust_diskspace(dp, DONE);
-       dumper->busy = 0;
-       dp->host->inprogress -= 1;
-       dp->inprogress = 0;
-       sched(dp)->attempted = 0;
-       printf("driver: finished-cmd time %s %s dumped %s:%s\n",
-              walltime_str(curclock()), dumper->name,
-              dp->host->hostname, dp->name);
-       fflush(stdout);
+           printf("driver: finished-cmd time %s %s chunked %s:%s\n",
+                  walltime_str(curclock()), chunker->name,
+                  dp->host->hostname, dp->name);
+           fflush(stdout);
 
-       enqueue_disk(&tapeq, dp);
-       dp = NULL;
+           event_release(chunker->ev_read);
 
-       startaflush();
-       continue_dumps();
+           chunker->result = cmd;
 
-       break;
+           break;
 
-    case TRYAGAIN: /* TRY-AGAIN <handle> <err str> */
-    case FATAL_TRYAGAIN:
-       free_serial(result_argv[2]);
+       case TRYAGAIN: /* TRY-AGAIN <handle> <errstr> */
+           assert(0);
+           event_release(chunker->ev_read);
 
-       rename_tmp_holding(sched(dp)->destname, 0);
-       deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
-       assert( h && activehd >= 0 );
-       holdalloc(h[activehd]->disk)->allocated_dumpers--;
-       /* Because we don't know how much was written to disk the
-        * following functions *must* be called together!
-        */
-       adjust_diskspace(dp, DONE);
-       delete_diskspace(dp);
-       dumper->busy = 0;
-       dp->host->inprogress -= 1;
-       dp->inprogress = 0;
-
-       if(sched(dp)->attempted) {
-           log_add(L_FAIL, "%s %s %d %s [too many dumper retry]",
-                   dp->host->hostname, dp->name,
-                   sched(dp)->level, sched(dp)->datestamp);
-           printf("driver: dump failed %s %s %s, too many dumper retry\n", result_argv[2], dp->host->hostname, dp->name);
-       } else {
-           sched(dp)->attempted++;
-           enqueue_disk(&runq, dp);
-       }
-       continue_dumps();
+           break;
+       case FAILED: /* FAILED <handle> <errstr> */
+           /*free_serial(result_argv[2]);*/
 
-       if(cmd == FATAL_TRYAGAIN) {
-           /* dumper is confused, start another */
-           log_add(L_WARNING, "%s (pid %ld) confused, restarting it.",
-                   dumper->name, (long)dumper->pid);
-           FD_CLR(fd,&readset);
-           aclose(fd);
-           startup_dump_process(dumper, dumper_program);
-       }
-       /* sleep in case the dumper failed because of a temporary network
-          problem, as NIS or NFS... */
-       sleep(15);
-       break;
+           event_release(chunker->ev_read);
 
-    case FAILED: /* FAILED <handle> <errstr> */
-       free_serial(result_argv[2]);
+           chunker->result = cmd;
 
-       rename_tmp_holding(sched(dp)->destname, 0);
-       deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
-       assert( h && activehd >= 0 );
-       holdalloc(h[activehd]->disk)->allocated_dumpers--;
-       /* Because we don't know how much was written to disk the
-        * following functions *must* be called together!
-        */
-       adjust_diskspace(dp, DONE);
-       delete_diskspace(dp);
-       dumper->busy = 0;
-       dp->host->inprogress -= 1;
-       dp->inprogress = 0;
-       continue_dumps();
-
-       /* no need to log this, dumper will do it */
-       /* sleep in case the dumper failed because of a temporary network
-          problem, as NIS or NFS... */
-       sleep(15);
-       break;
+           break;
 
-    case NO_ROOM: /* NO-ROOM <handle> <missing_size> */
-       assert( h && activehd >= 0 );
-       h[activehd]->used -= atoi(result_argv[3]);
-       h[activehd]->reserved -= atoi(result_argv[3]);
-       holdalloc(h[activehd]->disk)->allocated_space -= atoi(result_argv[3]);
-       h[activehd]->disk->disksize -= atoi(result_argv[3]);
-       break;
+       case NO_ROOM: /* NO-ROOM <handle> <missing_size> */
+           assert( h && activehd >= 0 );
+           h[activehd]->used -= atoi(result_argv[3]);
+           h[activehd]->reserved -= atoi(result_argv[3]);
+           holdalloc(h[activehd]->disk)->allocated_space -= atoi(result_argv[3]);
+           h[activehd]->disk->disksize -= atoi(result_argv[3]);
+           break;
 
-    case RQ_MORE_DISK: /* RQ-MORE-DISK <handle> */
-       assert( h && activehd >= 0 );
-       holdalloc(h[activehd]->disk)->allocated_dumpers--;
-       h[activehd]->used = h[activehd]->reserved;
-       if( h[++activehd] ) { /* There's still some allocated space left. Tell
-                              * the dumper about it. */
-           sched(dp)->activehd++;
-           dumper_cmd( dumper, CONTINUE, dp );
-       } else { /* !h[++activehd] - must allocate more space */
-           sched(dp)->act_size = sched(dp)->est_size; /* not quite true */
-           sched(dp)->est_size = sched(dp)->act_size * 21 / 20; /* +5% */
-           sched(dp)->est_size = am_round(sched(dp)->est_size, DISK_BLOCK_KB);
-           h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size,
-                               &dummy,
-                               h[activehd-1] );
-           if( !h ) {
-    /*     cur_idle = max(cur_idle, IDLE_NO_DISKSPACE); */
-               /* No diskspace available. The reason for this will be
-                * determined in continue_dumps(). */
-               enqueue_disk( &roomq, dp );
-               continue_dumps();
-           } else {
-               /* OK, allocate space for disk and have dumper continue */
-               sched(dp)->activehd = assign_holdingdisk( h, dp );
-               dumper_cmd( dumper, CONTINUE, dp );
-               amfree(h);
+       case RQ_MORE_DISK: /* RQ-MORE-DISK <handle> */
+           assert( h && activehd >= 0 );
+           holdalloc(h[activehd]->disk)->allocated_dumpers--;
+           h[activehd]->used = h[activehd]->reserved;
+           if( h[++activehd] ) { /* There's still some allocated space left.
+                                  * Tell the dumper about it. */
+               sched(dp)->activehd++;
+               chunker_cmd( chunker, CONTINUE, dp );
+           } else { /* !h[++activehd] - must allocate more space */
+               sched(dp)->act_size = sched(dp)->est_size; /* not quite true */
+               sched(dp)->est_size = sched(dp)->act_size * 21 / 20; /* +5% */
+               sched(dp)->est_size = am_round(sched(dp)->est_size, DISK_BLOCK_KB);
+               h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size,
+                                   &dummy,
+                                   h[activehd-1] );
+               if( !h ) {
+                   /* No diskspace available. The reason for this will be
+                    * determined in continue_port_dumps(). */
+                   enqueue_disk( &roomq, dp );
+                   continue_port_dumps();
+               } else {
+                   /* OK, allocate space for disk and have chunker continue */
+                   sched(dp)->activehd = assign_holdingdisk( h, dp );
+                   chunker_cmd( chunker, CONTINUE, dp );
+                   amfree(h);
+               }
            }
-       }
-       break;
+           break;
 
-    case ABORT_FINISHED: /* ABORT-FINISHED <handle> */
-       assert(pending_aborts);
-       free_serial(result_argv[2]);
+       case ABORT_FINISHED: /* ABORT-FINISHED <handle> */
+           /*
+            * We sent an ABORT from the NO-ROOM case because this dump
+            * wasn't going to fit onto the holding disk.  We now need to
+            * clean up the remains of this image, and try to finish
+            * other dumps that are waiting on disk space.
+            */
+           /*assert(pending_aborts);*/
 
-       rename_tmp_holding(sched(dp)->destname, 0);
-       deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
-       /* Because we don't know how much was written to disk the
-        * following functions *must* be called together!
-        */
-       adjust_diskspace(dp, DONE);
-       delete_diskspace(dp);
-       sched(dp)->attempted++;
-       enqueue_disk(&runq, dp);        /* we'll try again later */
-       dumper->busy = 0;
-       dp->host->inprogress -= 1;
-       dp->inprogress = 0;
-       dp = NULL;
-       pending_aborts--;
-       continue_dumps();
-       break;
+           /*free_serial(result_argv[2]);*/
 
-    case BOGUS:
-       /* either EOF or garbage from dumper.  Turn it off */
-       log_add(L_WARNING, "%s pid %ld is messed up, ignoring it.\n",
-               dumper->name, (long)dumper->pid);
-       FD_CLR(fd,&readset);
-       aclose(fd);
-       dumper->busy = 0;
-       dumper->down = 1;       /* mark it down so it isn't used again */
-       if(dp) {
-           /* if it was dumping something, zap it and try again */
-           rename_tmp_holding(sched(dp)->destname, 0);
-           deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
-           assert( h && activehd >= 0 );
-           holdalloc(h[activehd]->disk)->allocated_dumpers--;
-           /* Because we don't know how much was written to disk the
-            * following functions *must* be called together!
-            */
-           adjust_diskspace(dp, DONE);
-           delete_diskspace(dp);
-           dp->host->inprogress -= 1;
-           dp->inprogress = 0;
-           if(sched(dp)->attempted) {
-               log_add(L_FAIL, "%s %s %d %s [%s died]",
-                       dp->host->hostname, dp->name,
-                       sched(dp)->level, sched(dp)->datestamp, dumper->name);
-           }
-           else {
-               log_add(L_WARNING, "%s died while dumping %s:%s lev %d.",
-                       dumper->name, dp->host->hostname, dp->name,
-                       sched(dp)->level);
-               sched(dp)->attempted++;
-               enqueue_disk(&runq, dp);
+           event_release(chunker->ev_read);
+
+           chunker->result = cmd;
+
+           break;
+
+       case BOGUS:
+           /* either EOF or garbage from chunker.  Turn it off */
+           log_add(L_WARNING, "%s pid %ld is messed up, ignoring it.\n",
+                   chunker->name, (long)chunker->pid);
+
+           if(dp) {
+               /* if it was dumping something, zap it and try again */
+               assert( h && activehd >= 0 );
+               if(sched(dp)->attempted) {
+                   log_add(L_FAIL, "%s %s %s %d [%s died]",
+                           dp->host->hostname, dp->name, sched(dp)->datestamp,
+                           sched(dp)->level, chunker->name);
+               }
+               else {
+                   log_add(L_WARNING, "%s died while dumping %s:%s lev %d.",
+                           chunker->name, dp->host->hostname, dp->name,
+                           sched(dp)->level);
+               }
+               dp = NULL;
            }
-           dp = NULL;
-           continue_dumps();
+
+           event_release(chunker->ev_read);
+
+           chunker->result = cmd;
+
+           break;
+
+       default:
+           assert(0);
        }
-       break;
 
-    default:
-       assert(0);
-    }
+       if(chunker->result != LAST_TOK && chunker->dumper->result != LAST_TOK)
+           dumper_result(dp);
 
-    return;
+    } while(areads_dataready(chunker->fd));
 }
 
 
-void read_flush(tapeqp)
-disklist_t *tapeqp;
+static disklist_t
+read_flush()
 {
     sched_t *sp;
     disk_t *dp;
@@ -1348,9 +1555,9 @@ disklist_t *tapeqp;
     char *command;
     char *s;
     int ch;
-    long flush_size = 0;
+    disklist_t tq;
 
-    /* read schedule from stdin */
+    tq.head = tq.tail = NULL;
 
     for(line = 0; (inpline = agets(stdin)) != NULL; free(inpline)) {
        line++;
@@ -1358,9 +1565,9 @@ disklist_t *tapeqp;
        s = inpline;
        ch = *s++;
 
-       skip_whitespace(s, ch);                 /* find the command */
+       skip_whitespace(s, ch);                 /* find the command */
        if(ch == '\0') {
-           error("Aflush line %d: syntax error", line);
+           error("flush line %d: syntax error (no command)", line);
            continue;
        }
        command = s - 1;
@@ -1372,13 +1579,13 @@ disklist_t *tapeqp;
        }
 
        if(strcmp(command,"FLUSH") != 0) {
-           error("Bflush line %d: syntax error", line);
+           error("flush line %d: syntax error (%s != FLUSH)", line, command);
            continue;
        }
 
        skip_whitespace(s, ch);                 /* find the hostname */
        if(ch == '\0') {
-           error("Cflush line %d: syntax error", line);
+           error("flush line %d: syntax error (no hostname)", line);
            continue;
        }
        hostname = s - 1;
@@ -1387,7 +1594,7 @@ disklist_t *tapeqp;
 
        skip_whitespace(s, ch);                 /* find the diskname */
        if(ch == '\0') {
-           error("Cflush line %d: syntax error", line);
+           error("flush line %d: syntax error (no diskname)", line);
            continue;
        }
        diskname = s - 1;
@@ -1396,7 +1603,7 @@ disklist_t *tapeqp;
 
        skip_whitespace(s, ch);                 /* find the datestamp */
        if(ch == '\0') {
-           error("Cflush line %d: syntax error", line);
+           error("flush line %d: syntax error (no datestamp)", line);
            continue;
        }
        datestamp = s - 1;
@@ -1405,14 +1612,14 @@ disklist_t *tapeqp;
 
        skip_whitespace(s, ch);                 /* find the level number */
        if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
-           error("Cflush line %d: syntax error", line);
+           error("flush line %d: syntax error (bad level)", line);
            continue;
        }
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);                 /* find the filename */
        if(ch == '\0') {
-           error("Cflush line %d: syntax error", line);
+           error("flush line %d: syntax error (no filename)", line);
            continue;
        }
        destname = s - 1;
@@ -1475,28 +1682,28 @@ disklist_t *tapeqp;
        sp->degr_level = -1;
        sp->est_kps = 10;
        sp->attempted = 0;
-       sp->act_size = size_holding_files(destname);
-       /*sp->holdp = NULL; JLM: must be build*/
+       sp->act_size = size_holding_files(destname, 0);
        sp->holdp = build_diskspace(destname);
-        if(sp->holdp == NULL) continue;
+       if(sp->holdp == NULL) continue;
        sp->dumper = NULL;
        sp->timestamp = (time_t)0;
 
        dp1->up = (char *)sp;
 
-       enqueue_disk(tapeqp, dp1);
-       flush_size += sp->act_size;
+       enqueue_disk(&tq, dp1);
     }
-    printf("driver: flush size %ld\n", flush_size);
     amfree(inpline);
-}
 
+    return tq;
+}
 
-void read_schedule(waitqp, runqp)
-disklist_t *waitqp, *runqp;
+static void
+read_schedule(cookie)
+    void *cookie;
 {
     sched_t *sp;
     disk_t *dp;
+    disklist_t rq;
     int level, line, priority;
     char *dumpdate, *degr_dumpdate;
     int degr_level;
@@ -1506,6 +1713,11 @@ disklist_t *waitqp, *runqp;
     char *command;
     char *s;
     int ch;
+    long flush_size = 0;
+
+    rq.head = rq.tail = NULL;
+
+    event_release(schedule_ev_read);
 
     /* read schedule from stdin */
 
@@ -1686,16 +1898,21 @@ disklist_t *waitqp, *runqp;
        if(dp->host->features == NULL) {
            dp->host->features = am_string_to_feature(features);
        }
-       remove_disk(waitqp, dp);
-       insert_disk(&runq, dp, sort_by_time);
+       remove_disk(&waitq, dp);
+       enqueue_disk(&runq, dp);
+       flush_size += sp->act_size;
     }
+    printf("driver: flush size %ld\n", flush_size);
     amfree(inpline);
     if(line == 0)
        log_add(L_WARNING, "WARNING: got empty schedule from planner");
+    if(need_degraded==1) start_degraded_mode(&runq);
+    start_some_dumps(&runq);
 }
 
-int free_kps(ip)
-interface_t *ip;
+static int
+free_kps(ip)
+    interface_t *ip;
 {
     int res;
 
@@ -1716,8 +1933,9 @@ interface_t *ip;
     return res;
 }
 
-void interface_state(time_str)
-char *time_str;
+static void
+interface_state(time_str)
+    char *time_str;
 {
     interface_t *ip;
 
@@ -1729,23 +1947,26 @@ char *time_str;
     printf("\n");
 }
 
-void allocate_bandwidth(ip, kps)
-interface_t *ip;
-int kps;
+static void
+allocate_bandwidth(ip, kps)
+    interface_t *ip;
+    int kps;
 {
     ip->curusage += kps;
 }
 
-void deallocate_bandwidth(ip, kps)
-interface_t *ip;
-int kps;
+static void
+deallocate_bandwidth(ip, kps)
+    interface_t *ip;
+    int kps;
 {
     assert(kps <= ip->curusage);
     ip->curusage -= kps;
 }
 
 /* ------------ */
-unsigned long free_space()
+static unsigned long
+free_space()
 {
     holdingdisk_t *hdp;
     unsigned long total_free;
@@ -1760,22 +1981,21 @@ unsigned long free_space()
     return total_free;
 }
 
-assignedhd_t **find_diskspace(size, cur_idle, pref)
-unsigned long size;
-int *cur_idle;
-assignedhd_t *pref;
-/* Rewrite by Peter Conrad <conrad@opus5.de>, June '99:
- *  - enable splitting a dump across several holding disks
- *  - allocate only as much as size tells us, dumpers may request more later
- * We return an array of pointers to assignedhd_t. The array contains at
+static assignedhd_t **
+find_diskspace(size, cur_idle, pref)
+    unsigned long size;
+    int *cur_idle;
+    assignedhd_t *pref;
+/* We return an array of pointers to assignedhd_t. The array contains at
  * most one entry per holding disk. The list of pointers is terminated by
  * a NULL pointer. Each entry contains a pointer to a holdingdisk and
  * how much diskspace to use on that disk. Later on, assign_holdingdisk
  * will allocate the given amount of space.
  * If there is not enough room on the holdingdisks, NULL is returned.
  */
+
 {
-assignedhd_t **result = NULL;
+    assignedhd_t **result = NULL;
     holdingdisk_t *minp, *hdp;
     int i=0, num_holdingdisks=0; /* are we allowed to use the global thing? */
     int j, minj;
@@ -1785,7 +2005,7 @@ assignedhd_t **result = NULL;
     size = am_round(size, DISK_BLOCK_KB);
 
 #ifdef HOLD_DEBUG
-    printf("find diskspace: want %lu K\n", size );
+    printf("%s: want %lu K\n", debug_prefix_time(": find_diskspace"), size);
     fflush(stdout);
 #endif
 
@@ -1811,7 +2031,7 @@ assignedhd_t **result = NULL;
                break;
            }
            else if( holdalloc(hdp)->allocated_space <= hdp->disksize - 2*DISK_BLOCK_KB &&
-               !used[j] && 
+               !used[j] &&
                (!minp ||
                 holdalloc(hdp)->allocated_dumpers < holdalloc(minp)->allocated_dumpers ||
                 (holdalloc(hdp)->allocated_dumpers == holdalloc(minp)->allocated_dumpers &&
@@ -1820,6 +2040,7 @@ assignedhd_t **result = NULL;
                minj = j;
            }
        }
+
        pref = NULL;
        if( !minp ) { break; } /* all holding disks are full */
        used[minj] = 1;
@@ -1837,7 +2058,9 @@ assignedhd_t **result = NULL;
        halloc = dalloc + (((dalloc-1)/minp->chunksize)+1) * DISK_BLOCK_KB;
 
 #ifdef HOLD_DEBUG
-       fprintf(stdout,"find diskspace: size %ld hf %ld df %ld da %ld ha %ld\n",                size, hfree, dfree, dalloc, halloc);
+       printf("%s: find diskspace: size %ld hf %ld df %ld da %ld ha %ld\n",
+              debug_prefix_time(": find_diskspace"),
+              size, hfree, dfree, dalloc, halloc);
        fflush(stdout);
 #endif
        size -= dalloc;
@@ -1852,21 +2075,20 @@ assignedhd_t **result = NULL;
     amfree(used);
 
     if( size ) { /* not enough space available */
-#ifdef HOLD_DEBUG
        printf("find diskspace: not enough diskspace. Left with %lu K\n", size);
        fflush(stdout);
-#endif
        free_assignedhd(result);
        result = NULL;
     }
 
 #ifdef HOLD_DEBUG
     for( i = 0; result && result[i]; i++ ) {
-    printf("find diskspace: selected %s free %ld reserved %ld dumpers %d\n",
-           result[i]->disk->diskdir,
-           result[i]->disk->disksize - holdalloc(result[i]->disk)->allocated_space,
-          result[i]->reserved,
-           holdalloc(result[i]->disk)->allocated_dumpers);
+       printf("%s: find diskspace: selected %s free %ld reserved %ld dumpers %d\n",
+               debug_prefix_time(": find_diskspace"),
+               result[i]->disk->diskdir,
+               result[i]->disk->disksize - holdalloc(result[i]->disk)->allocated_space,
+               result[i]->reserved,
+               holdalloc(result[i]->disk)->allocated_dumpers);
     }
     fflush(stdout);
 #endif
@@ -1874,21 +2096,18 @@ assignedhd_t **result = NULL;
     return result;
 }
 
-int assign_holdingdisk(holdp, diskp)
-assignedhd_t **holdp;
-disk_t *diskp;
+static int
+assign_holdingdisk(holdp, diskp)
+    assignedhd_t **holdp;
+    disk_t *diskp;
 {
-/* Modified by Peter Conrad <conrad@opus5.de>, June '99
- * Modifications for splitting dumps across holding disks:
- * sched(diskp)->holdp now contains an array of pointers to assignedhd_t.
- */
     int i, j, c, l=0;
     unsigned long size;
     char *sfn = sanitise_filename(diskp->name);
     char lvl[64];
     assignedhd_t **new_holdp;
 
-    ap_snprintf( lvl, sizeof(lvl), "%d", sched(diskp)->level );
+    snprintf( lvl, sizeof(lvl), "%d", sched(diskp)->level );
 
     size = am_round(sched(diskp)->est_size - sched(diskp)->act_size,
                    DISK_BLOCK_KB);
@@ -1914,7 +2133,8 @@ disk_t *diskp;
            holdalloc(holdp[0]->disk)->allocated_space += holdp[0]->reserved;
            size = (holdp[0]->reserved>size) ? 0 : size-holdp[0]->reserved;
 #ifdef HOLD_DEBUG
-           printf("merging holding disk %s to disk %s:%s, add %lu for reserved %lu, left %lu\n",
+           printf("%s: merging holding disk %s to disk %s:%s, add %lu for reserved %lu, left %lu\n",
+                  debug_prefix_time(": assign_holdingdisk"),
                   sched(diskp)->holdp[j-1]->disk->diskdir,
                   diskp->host->hostname, diskp->name,
                   holdp[0]->reserved, sched(diskp)->holdp[j-1]->reserved,
@@ -1939,41 +2159,34 @@ disk_t *diskp;
        holdalloc(holdp[i]->disk)->allocated_space += holdp[i]->reserved;
        size = (holdp[i]->reserved>size) ? 0 : size-holdp[i]->reserved;
 #ifdef HOLD_DEBUG
-        printf("assigning holding disk %s to disk %s:%s, reserved %lu, left %lu\n",
-                holdp[i]->disk->diskdir, diskp->host->hostname, diskp->name,
-                holdp[i]->reserved, size );
-        fflush(stdout);
+       printf("%s: %d assigning holding disk %s to disk %s:%s, reserved %lu, left %lu\n",
+               debug_prefix_time(": assign_holdingdisk"),
+               i, holdp[i]->disk->diskdir, diskp->host->hostname, diskp->name,
+               holdp[i]->reserved, size );
+       fflush(stdout);
 #endif
        holdp[i] = NULL; /* so it doesn't get free()d... */
     }
     sched(diskp)->holdp[j] = NULL;
-    sched(diskp)->destname = newstralloc(sched(diskp)->destname,sched(diskp)->holdp[0]->destname);
     amfree(sfn);
 
     return l;
 }
 
-static void adjust_diskspace(diskp, cmd)
-disk_t *diskp;
-cmd_t cmd;
+static void
+adjust_diskspace(diskp, cmd)
+    disk_t *diskp;
+    cmd_t cmd;
 {
-/* Re-write by Peter Conrad <conrad@opus5.de>, March '99
- * Modifications for splitting dumps across holding disks:
- * Dumpers no longer write more than they've allocated, therefore an
- * adjustment may only free some allocated space.
- * 08/99: Jean-Louis suggested that dumpers tell us how much they've written.
- * We just believe them and don't stat all the files but rely on the used
- * field.
- */
-
     assignedhd_t **holdp;
     unsigned long total=0;
     long diff;
     int i;
 
 #ifdef HOLD_DEBUG
-    printf("adjust: %s:%s %s\n", diskp->host->hostname, diskp->name,
-           sched(diskp)->destname );
+    printf("%s: %s:%s %s\n",
+          debug_prefix_time(": adjust_diskspace"),
+          diskp->host->hostname, diskp->name, sched(diskp)->destname);
     fflush(stdout);
 #endif
 
@@ -1985,32 +2198,33 @@ cmd_t cmd;
        diff = holdp[i]->used - holdp[i]->reserved;
        total += holdp[i]->used;
        holdalloc(holdp[i]->disk)->allocated_space += diff;
+
 #ifdef HOLD_DEBUG
-       printf("adjust: hdisk %s done, reserved %ld used %ld diff %ld alloc %ld dumpers %d\n",
+       printf("%s: hdisk %s done, reserved %ld used %ld diff %ld alloc %ld dumpers %d\n",
+               debug_prefix_time(": adjust_diskspace"),
                holdp[i]->disk->name, holdp[i]->reserved, holdp[i]->used, diff,
                holdalloc(holdp[i]->disk)->allocated_space,
                holdalloc(holdp[i]->disk)->allocated_dumpers );
-               fflush(stdout);
+       fflush(stdout);
 #endif
        holdp[i]->reserved += diff;
     }
 
     sched(diskp)->act_size = total;
+
 #ifdef HOLD_DEBUG
-    printf("adjust: after: disk %s:%s used %ld\n", diskp->host->hostname,
-          diskp->name, sched(diskp)->act_size );
+    printf("%s: after: disk %s:%s used %ld\n",
+          debug_prefix_time(": adjust_diskspace"),
+          diskp->host->hostname, diskp->name, sched(diskp)->act_size );
     fflush(stdout);
 #endif
+
 }
 
-static void delete_diskspace(diskp)
-disk_t *diskp;
+static void
+delete_diskspace(diskp)
+    disk_t *diskp;
 {
-/* Re-write by Peter Conrad <conrad@opus5.de>, March '99
- * Modifications for splitting dumps across holding disks:
- * After implementing Jean-Louis' suggestion (see above) this looks much
- * simpler... again, we rely on assignedhd_s containing correct info
- */
     assignedhd_t **holdp;
     int i;
 
@@ -2019,24 +2233,22 @@ disk_t *diskp;
     assert(holdp);
 
     for( i = 0; holdp[i]; i++ ) { /* for each disk */
-        /* find all files of this dump on that disk, and subtract their
-         * reserved sizes from the disk's allocated space
-         */
+       /* find all files of this dump on that disk, and subtract their
+        * reserved sizes from the disk's allocated space
+        */
        holdalloc(holdp[i]->disk)->allocated_space -= holdp[i]->used;
     }
 
-    unlink_holding_files(holdp[0]->destname); /* no need for the entire list, 
-                                                        because unlink_holding_files
-                                                will walk through all files
-                                                        using cont_filename */
-
+    unlink_holding_files(holdp[0]->destname);  /* no need for the entire list,
+                                                * because unlink_holding_files
+                                                * will walk through all files
+                                                * using cont_filename */
     free_assignedhd(sched(diskp)->holdp);
     sched(diskp)->holdp = NULL;
     sched(diskp)->act_size = 0;
-    amfree(sched(diskp)->destname);
 }
 
-assignedhd_t **build_diskspace(destname)
+static assignedhd_t **build_diskspace(destname)
 char *destname;
 {
     int i, j;
@@ -2085,8 +2297,9 @@ char *destname;
                    filename, strerror(errno));
            return NULL;
        }
-       buflen = fullread(fd, buffer, sizeof(buffer));
-       parse_file_header(buffer, &file, buflen);
+       if ((buflen = fullread(fd, buffer, sizeof(buffer))) > 0) {;
+               parse_file_header(buffer, &file, buflen);
+       }
        close(fd);
        filename = file.cont_filename;
     }
@@ -2108,9 +2321,9 @@ char *destname;
     return result;
 }
 
-
-void holdingdisk_state(time_str)
-char *time_str;
+static void
+holdingdisk_state(time_str)
+    char *time_str;
 {
     holdingdisk_t *hdp;
     int dsk;
@@ -2126,9 +2339,14 @@ char *time_str;
     printf("\n");
 }
 
-static void update_failed_dump_to_tape(dp)
-disk_t *dp;
+static void
+update_failed_dump_to_tape(dp)
+    disk_t *dp;
 {
+/* JLM
+ * should simply set no_bump
+ */
+
     time_t save_timestamp = sched(dp)->timestamp;
     /* setting timestamp to 0 removes the current level from the
      * database, so that we ensure that it will not be bumped to the
@@ -2141,8 +2359,9 @@ disk_t *dp;
 }
 
 /* ------------------- */
-int dump_to_tape(dp)
-     disk_t *dp;
+static int
+dump_to_tape(dp)
+    disk_t *dp;
 {
     dumper_t *dumper;
     int failed = 0;
@@ -2150,13 +2369,12 @@ int dump_to_tape(dp)
     long origsize = 0;
     long dumpsize = 0;
     long dumptime = 0;
+    float tapetime = 0;
     cmd_t cmd;
     int result_argc;
     char *result_argv[MAX_ARGS+1];
     int dumper_tryagain = 0;
 
-    inside_dump_to_tape = 1;   /* for simulator */
-
     printf("driver: dumping %s:%s directly to tape\n",
           dp->host->hostname, dp->name);
     fflush(stdout);
@@ -2170,7 +2388,6 @@ int dump_to_tape(dp)
        fflush(stdout);
        log_add(L_WARNING, "no idle dumpers for %s:%s.\n",
                dp->host->hostname, dp->name);
-       inside_dump_to_tape = 0;
        return 2;       /* fatal problem */
     }
 
@@ -2182,11 +2399,10 @@ int dump_to_tape(dp)
        printf("driver: did not get PORT from taper for %s:%s\n",
                dp->host->hostname, dp->name);
        fflush(stdout);
-       inside_dump_to_tape = 0;
        return 2;       /* fatal problem */
     }
     /* copy port number */
-    sched(dp)->destname = newvstralloc(sched(dp)->destname, result_argv[2], NULL );
+    dumper->output_port = atoi(result_argv[2]);
 
     /* tell the dumper to dump to a port */
 
@@ -2200,13 +2416,13 @@ int dump_to_tape(dp)
     dp->inprogress = 1;
     sched(dp)->timestamp = time((time_t *)0);
     allocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
-    idle_reason = 0;
+    idle_reason = NOT_IDLE;
 
     short_dump_state();
 
     /* wait for result from dumper */
 
-    cmd = getresult(dumper->outfd, 1, &result_argc, result_argv, MAX_ARGS+1);
+    cmd = getresult(dumper->fd, 1, &result_argc, result_argv, MAX_ARGS+1);
 
     if(cmd != BOGUS)
        free_serial(result_argv[2]);
@@ -2220,21 +2436,21 @@ int dump_to_tape(dp)
        failed = 1;     /* dump failed, must still finish up with taper */
        break;
 
-    case DONE: /* DONE <handle> <origsize> <dumpsize> <dumptime> <err str> */
+    case DONE: /* DONE <handle> <origsize> <dumpsize> <dumptime> <errstr> */
        /* everything went fine */
        origsize = (long)atof(result_argv[3]);
-       dumpsize = (long)atof(result_argv[4]);
+       /*dumpsize = (long)atof(result_argv[4]);*/
        dumptime = (long)atof(result_argv[5]);
        break;
 
     case NO_ROOM: /* NO-ROOM <handle> */
        dumper_cmd(dumper, ABORT, dp);
-       cmd = getresult(dumper->outfd, 1, &result_argc, result_argv, MAX_ARGS+1);
+       cmd = getresult(dumper->fd, 1, &result_argc, result_argv, MAX_ARGS+1);
        if(cmd != BOGUS)
            free_serial(result_argv[2]);
        assert(cmd == ABORT_FINISHED);
 
-    case TRYAGAIN: /* TRY-AGAIN <handle> <err str> */
+    case TRYAGAIN: /* TRY-AGAIN <handle> <errstr> */
     default:
        /* dump failed, but we must still finish up with taper */
        /* problem with dump, possibly nonfatal, retry one time */
@@ -2257,9 +2473,12 @@ int dump_to_tape(dp)
      * "no space on device", etc., since taper closed the port first.
      */
 
+    continue_port_dump:
+
     cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1);
 
     switch(cmd) {
+    case PARTIAL:
     case DONE: /* DONE <handle> <label> <tape file> <err mess> */
        if(result_argc != 5) {
            error("error [dump to tape DONE result_argc != 5: %d]", result_argc);
@@ -2270,17 +2489,23 @@ int dump_to_tape(dp)
 
        free_serial(result_argv[2]);
 
-       /* every thing went fine */
-       update_info_dumper(dp, origsize, dumpsize, dumptime);
-       filenum = atoi(result_argv[4]);
-       update_info_taper(dp, result_argv[3], filenum, sched(dp)->level);
-       /* note that update_info_dumper() must be run before
-          update_info_taper(), since update_info_dumper overwrites
-          tape information.  */
+       sscanf(result_argv[5],"[sec %f kb %ld ", &tapetime, &dumpsize);
+
+       if(cmd == DONE) {
+           /* every thing went fine */
+           update_info_dumper(dp, origsize, dumpsize, dumptime);
+           filenum = atoi(result_argv[4]);
+           update_info_taper(dp, result_argv[3], filenum, sched(dp)->level);
+           /* note that update_info_dumper() must be run before
+              update_info_taper(), since update_info_dumper overwrites
+              tape information.  */
+       }
 
        break;
 
     case TRYAGAIN: /* TRY-AGAIN <handle> <err mess> */
+       tape_left = tape_length;
+       current_tape++;
        if(dumper_tryagain == 0) {
            sched(dp)->attempted++;
            if(sched(dp)->attempted > failed)
@@ -2292,10 +2517,21 @@ int dump_to_tape(dp)
     failed_dumper:
        update_failed_dump_to_tape(dp);
        free_serial(result_argv[2]);
-       tape_left = tape_length;
        break;
 
-
+    case SPLIT_CONTINUE:  /* SPLIT_CONTINUE <handle> <new_label> */
+        if (result_argc != 3) {
+            error("error [taper SPLIT_CONTINUE result_argc != 3: %d]", result_argc);
+        }
+        fprintf(stderr, "driver: Got SPLIT_CONTINUE %s %s\n", result_argv[2], result_argv[3]);
+        goto continue_port_dump;
+        break;
+    case SPLIT_NEEDNEXT:
+        fprintf(stderr, "driver: Got SPLIT_NEEDNEXT %s %s\n", result_argv[2], result_argv[3]);
+
+        goto continue_port_dump;
+        break;
     case TAPE_ERROR: /* TAPE-ERROR <handle> <err mess> */
     case BOGUS:
     default:
@@ -2312,12 +2548,12 @@ int dump_to_tape(dp)
     dp->inprogress = 0;
     deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
 
-    inside_dump_to_tape = 0;
     return failed;
 }
 
-int queue_length(q)
-disklist_t q;
+static int
+queue_length(q)
+    disklist_t q;
 {
     disk_t *p;
     int len;
@@ -2326,8 +2562,8 @@ disklist_t q;
     return len;
 }
 
-
-void short_dump_state()
+static void
+short_dump_state()
 {
     int i, nidle;
     char *wall_time;
@@ -2346,15 +2582,17 @@ void short_dump_state()
     printf(" qlen tapeq: %d", queue_length(tapeq));
     printf(" runq: %d", queue_length(runq));
     printf(" roomq: %d", queue_length(roomq));
-    printf(" wakeup: %d", (int)sleep_time.tv_sec);
+    printf(" wakeup: %d", (int)sleep_time);
     printf(" driver-idle: %s\n", idle_strings[idle_reason]);
     interface_state(wall_time);
     holdingdisk_state(wall_time);
     fflush(stdout);
 }
 
-void dump_state(str)
-char *str;
+#if 0
+static void
+dump_state(str)
+    const char *str;
 {
     int i;
     disk_t *dp;
@@ -2383,3 +2621,4 @@ char *str;
     printf("================\n");
     fflush(stdout);
 }
+#endif
index 9973d12123c0d42d590bd638034cd893632c9c03..0000a3c3b2e815731e5e273d6292b897adaa6b99 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: driverio.c,v 1.35.2.14.4.2.2.5.2.5 2005/09/12 13:39:55 martinea Exp $
+ * $Id: driverio.c,v 1.81 2006/03/11 21:57:18 martinea Exp $
  *
  * I/O-related functions for driver program
  */
 #include "amanda.h"
+#include "util.h"
 #include "clock.h"
 #include "conffile.h"
 #include "diskfile.h"
 #define GLOBAL         /* the global variables defined here */
 #include "driverio.h"
 
+int nb_chunker = 0;
+
+static const char *childstr P((int));
+
 void init_driverio()
 {
     dumper_t *dumper;
@@ -48,41 +53,29 @@ void init_driverio()
     taper = -1;
 
     for(dumper = dmptable; dumper < dmptable + MAX_DUMPERS; dumper++) {
-       dumper->outfd = -1;
+       dumper->fd = -1;
     }
 }
 
 
-void addfd(fd, readset, maxfd)
-int    fd;
-fd_set *readset;
-int    *maxfd;
-{
-    if(fd < 0 || fd >= FD_SETSIZE) {
-       error("addfd: descriptor %d out of range (0 .. %d)\n",
-             fd, FD_SETSIZE-1);
-    }
-    if(readset != NULL)
-       FD_SET(fd, readset);
-    if(maxfd != NULL)
-       if(fd > *maxfd) *maxfd = fd;
-}
-
-char *childstr(fd)
-int fd;
+static const char *
+childstr(fd)
+    int fd;
 {
-    static char *str = NULL;
-    char fd_str[NUM_STR_SIZE];
+    static char buf[NUM_STR_SIZE + 32];
     dumper_t *dumper;
 
-    if(fd == taper) return "taper";
-
-    for(dumper = dmptable; dumper < dmptable + MAX_DUMPERS; dumper++)
-       if(dumper->outfd == fd) return dumper->name;
+    if (fd == taper)
+       return ("taper");
 
-    ap_snprintf(fd_str, sizeof(fd_str), "%d", fd);
-    str = newvstralloc(str, "unknown child (fd ", fd_str, ")", NULL);
-    return str;
+    for (dumper = dmptable; dumper < dmptable + MAX_DUMPERS; dumper++) {
+       if (dumper->fd == fd)
+           return (dumper->name);
+       if (dumper->chunker->fd == fd)
+           return (dumper->chunker->name);
+    }
+    snprintf(buf, sizeof(buf), "unknown child (fd %d)", fd);
+    return (buf);
 }
 
 
@@ -114,7 +107,7 @@ char *taper_program;
     default:   /* parent process */
        aclose(fd[1]);
        taper = fd[0];
-       addfd(taper, &readset, &maxfd);
+       taper_ev_read = NULL;
     }
 }
 
@@ -143,8 +136,8 @@ char *dumper_program;
              dumper->name, strerror(errno));
     default:   /* parent process */
        aclose(fd[1]);
-       dumper->infd = dumper->outfd = fd[0];
-       addfd(dumper->outfd, &readset, &maxfd);
+       dumper->fd = fd[0];
+       dumper->ev_read = NULL;
        dumper->busy = dumper->down = 0;
        dumper->dp = NULL;
        fprintf(stderr,"driver: started %s pid %d\n",
@@ -162,13 +155,51 @@ int inparallel;
     char number[NUM_STR_SIZE];
 
     for(dumper = dmptable, i = 0; i < inparallel; dumper++, i++) {
-       ap_snprintf(number, sizeof(number), "%d", i);
+       snprintf(number, sizeof(number), "%d", i);
        dumper->name = stralloc2("dumper", number);
+       dumper->chunker = &chktable[i];
+       chktable[i].name = stralloc2("chunker", number);
+       chktable[i].dumper = dumper;
+       chktable[i].fd = -1;
 
        startup_dump_process(dumper, dumper_program);
     }
 }
 
+void startup_chunk_process(chunker, chunker_program)
+chunker_t *chunker;
+char *chunker_program;
+{
+    int fd[2];
+
+    if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1)
+       error("%s pipe: %s", chunker->name, strerror(errno));
+
+    switch(chunker->pid = fork()) {
+    case -1:
+       error("fork %s: %s", chunker->name, strerror(errno));
+    case 0:            /* child process */
+       aclose(fd[0]);
+       if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1)
+           error("%s dup2: %s", chunker->name, strerror(errno));
+       execle(chunker_program,
+              chunker->name ? chunker->name : "chunker",
+              config_name,
+              (char *)0,
+              safe_env());
+       error("exec %s (%s): %s", chunker_program,
+             chunker->name, strerror(errno));
+    default:   /* parent process */
+       aclose(fd[1]);
+       chunker->down = 0;
+       chunker->fd = fd[0];
+       chunker->ev_read = NULL;
+       fprintf(stderr,"driver: started %s pid %d\n",
+               chunker->name, chunker->pid);
+       fflush(stderr);
+    }
+}
+
 cmd_t getresult(fd, show, result_argc, result_argv, max_arg)
 int fd;
 int show;
@@ -188,17 +219,22 @@ int max_arg;
     } else {
        *result_argc = split(line, result_argv, max_arg, " ");
     }
-    amfree(line);
 
     if(show) {
        printf("driver: result time %s from %s:",
               walltime_str(curclock()),
               childstr(fd));
-       for(arg = 1; arg <= *result_argc; arg++)
-           printf(" %s", result_argv[arg]);
-       printf("\n");
+       if(line) {
+           for(arg = 1; arg <= *result_argc; arg++) {
+               printf(" %s", result_argv[arg]);
+           }
+           putchar('\n');
+       } else {
+           printf(" (eof)\n");
+       }
        fflush(stdout);
     }
+    amfree(line);
 
 #ifdef DEBUG
     printf("argc = %d\n", *result_argc);
@@ -224,8 +260,10 @@ char *datestamp;
 {
     char *cmdline = NULL;
     char number[NUM_STR_SIZE];
+    char splitsize[NUM_STR_SIZE];
+    char fallback_splitsize[NUM_STR_SIZE];
+    char *diskbuffer = NULL;
     disk_t *dp;
-    int l, n, s;
     char *features;
 
     switch(cmd) {
@@ -234,7 +272,8 @@ char *datestamp;
        break;
     case FILE_WRITE:
        dp = (disk_t *) ptr;
-       ap_snprintf(number, sizeof(number), "%d", level);
+       snprintf(number, sizeof(number), "%d", level);
+       snprintf(splitsize, sizeof(splitsize), "%ld", dp->tape_splitsize);
        features = am_feature_to_string(dp->host->features);
        cmdline = vstralloc(cmdstr[cmd],
                            " ", disk2serial(dp),
@@ -244,12 +283,27 @@ char *datestamp;
                            " ", dp->name,
                            " ", number,
                            " ", datestamp,
+                           " ", splitsize,
                            "\n", NULL);
        amfree(features);
        break;
     case PORT_WRITE:
        dp = (disk_t *) ptr;
-       ap_snprintf(number, sizeof(number), "%d", level);
+       snprintf(number, sizeof(number), "%d", level);
+
+       /*
+          If we haven't been given a place to buffer split dumps to disk,
+          make the argument something besides and empty string so's taper
+          won't get confused
+       */
+       if(!dp->split_diskbuffer || dp->split_diskbuffer[0] == '\0'){
+           diskbuffer = "NULL";
+       } else {
+           diskbuffer = dp->split_diskbuffer;
+       }
+       snprintf(splitsize, sizeof(splitsize), "%ld", dp->tape_splitsize);
+       snprintf(fallback_splitsize, sizeof(fallback_splitsize),
+                   "%ld", dp->fallback_splitsize);
        features = am_feature_to_string(dp->host->features);
        cmdline = vstralloc(cmdstr[cmd],
                            " ", disk2serial(dp),
@@ -258,6 +312,9 @@ char *datestamp;
                            " ", dp->name,
                            " ", number,
                            " ", datestamp,
+                           " ", splitsize,
+                           " ", diskbuffer,
+                           " ", fallback_splitsize,
                            "\n", NULL);
        amfree(features);
        break;
@@ -273,13 +330,11 @@ char *datestamp;
     printf("driver: send-cmd time %s to taper: %s",
           walltime_str(curclock()), cmdline);
     fflush(stdout);
-    for(l = 0, n = strlen(cmdline); l < n; l += s) {
-       if((s = write(taper, cmdline + l, n - l)) < 0) {
-           printf("writing taper command: %s\n", strerror(errno));
-           fflush(stdout);
-           amfree(cmdline);
-           return 0;
-       }
+    if (fullwrite(taper, cmdline, strlen(cmdline)) < 0) {
+       printf("writing taper command: %s\n", strerror(errno));
+       fflush(stdout);
+       amfree(cmdline);
+       return 0;
     }
     amfree(cmdline);
     return 1;
@@ -292,9 +347,7 @@ disk_t *dp;
 {
     char *cmdline = NULL;
     char number[NUM_STR_SIZE];
-    char chunksize[NUM_STR_SIZE];
-    char use[NUM_STR_SIZE];
-    int l, n, s;
+    char numberport[NUM_STR_SIZE];
     char *o;
     int activehd=0;
     assignedhd_t **h=NULL;
@@ -314,68 +367,123 @@ disk_t *dp;
     }
 
     switch(cmd) {
-    case FILE_DUMP:
-       holdalloc(h[activehd]->disk)->allocated_dumpers++;
-       ap_snprintf(number, sizeof(number), "%d", sched(dp)->level);
-       ap_snprintf(chunksize, sizeof(chunksize), "%ld", h[0]->disk->chunksize);
-       ap_snprintf(use, sizeof(use), "%ld", h[0]->reserved );
-       features = am_feature_to_string(dp->host->features);
-       o = optionstr(dp, dp->host->features, NULL);
-       cmdline = vstralloc(cmdstr[cmd],
+    case PORT_DUMP:
+       if (dp != NULL) {
+           snprintf(number, sizeof(number), "%d", sched(dp)->level);
+           snprintf(numberport, sizeof(numberport), "%d", dumper->output_port);
+           features = am_feature_to_string(dp->host->features);
+           o = optionstr(dp, dp->host->features, NULL);
+           cmdline = vstralloc(cmdstr[cmd],
                            " ", disk2serial(dp),
-                           " ", sched(dp)->destname,
+                           " ", numberport,
                            " ", dp->host->hostname,
                            " ", features,
                            " ", dp->name,
                            " ", device,
                            " ", number,
                            " ", sched(dp)->dumpdate,
-                           " ", chunksize,
                            " ", dp->program,
-                           " ", use,
                            " |", o,
                            "\n", NULL);
-       amfree(features);
-       amfree(o);
+           amfree(features);
+           amfree(o);
+       } else {
+               error("PORT-DUMP without disk pointer\n");
+               /*NOTREACHED*/
+       }
        break;
-    case PORT_DUMP:
-       ap_snprintf(number, sizeof(number), "%d", sched(dp)->level);
-       features = am_feature_to_string(dp->host->features);
-       o = optionstr(dp, dp->host->features, NULL);
-       cmdline = vstralloc(cmdstr[cmd],
+    case QUIT:
+    case ABORT:
+       if( dp ) {
+           cmdline = vstralloc(cmdstr[cmd],
+                               " ", sched(dp)->destname,
+                               "\n", NULL );
+       } else {
+           cmdline = stralloc2(cmdstr[cmd], "\n");
+       }
+       break;
+    default:
+       error("Don't know how to send %s command to dumper", cmdstr[cmd]);
+    }
+    /*
+     * Note: cmdline already has a '\n'.
+     */
+    if(dumper->down) {
+       printf("driver: send-cmd time %s ignored to down dumper %s: %s",
+              walltime_str(curclock()), dumper->name, cmdline);
+    } else {
+       printf("driver: send-cmd time %s to %s: %s",
+              walltime_str(curclock()), dumper->name, cmdline);
+       fflush(stdout);
+       if (fullwrite(dumper->fd, cmdline, strlen(cmdline)) < 0) {
+           printf("writing %s command: %s\n", dumper->name, strerror(errno));
+           fflush(stdout);
+           amfree(cmdline);
+           return 0;
+       }
+    }
+    amfree(cmdline);
+    return 1;
+}
+
+int chunker_cmd(chunker, cmd, dp)
+chunker_t *chunker;
+cmd_t cmd;
+disk_t *dp;
+{
+    char *cmdline = NULL;
+    char number[NUM_STR_SIZE];
+    char chunksize[NUM_STR_SIZE];
+    char use[NUM_STR_SIZE];
+    char *o;
+    int activehd=0;
+    assignedhd_t **h=NULL;
+    char *features;
+
+    if(dp && sched(dp) && sched(dp)->holdp) {
+       h = sched(dp)->holdp;
+       activehd = sched(dp)->activehd;
+    }
+
+    switch(cmd) {
+    case PORT_WRITE:
+       if (dp && h) {
+           holdalloc(h[activehd]->disk)->allocated_dumpers++;
+           snprintf(number, sizeof(number), "%d", sched(dp)->level);
+           snprintf(chunksize, sizeof(chunksize), "%ld", h[0]->disk->chunksize);
+           snprintf(use, sizeof(use), "%ld", h[0]->reserved );
+           features = am_feature_to_string(dp->host->features);
+           o = optionstr(dp, dp->host->features, NULL);
+           cmdline = vstralloc(cmdstr[cmd],
                            " ", disk2serial(dp),
                            " ", sched(dp)->destname,
                            " ", dp->host->hostname,
                            " ", features,
                            " ", dp->name,
-                           " ", device,
                            " ", number,
                            " ", sched(dp)->dumpdate,
+                           " ", chunksize,
                            " ", dp->program,
+                           " ", use,
                            " |", o,
                            "\n", NULL);
-       amfree(features);
-       amfree(o);
-       break;
-    case QUIT:
-    case ABORT:
-       if( dp ) {
-           cmdline = vstralloc(cmdstr[cmd],
-                               " ", sched(dp)->destname,
-                               "\n", NULL );
+           amfree(features);
+           amfree(o);
        } else {
-           cmdline = stralloc2(cmdstr[cmd], "\n");
+               error("Write command without disk and holding disk.\n",
+                     cmdstr[cmd]);
+               /*NOTREACHED*/
        }
        break;
     case CONTINUE:
-       if( dp ) {
+       if( dp && h) {
            holdalloc(h[activehd]->disk)->allocated_dumpers++;
-           ap_snprintf(chunksize, sizeof(chunksize), "%ld", 
-                       h[activehd]->disk->chunksize );
-           ap_snprintf(use, sizeof(use), "%ld", 
-                       h[activehd]->reserved - h[activehd]->used );
+           snprintf(chunksize, sizeof(chunksize), "%ld", 
+                    h[activehd]->disk->chunksize );
+           snprintf(use, sizeof(use), "%ld", 
+                    h[activehd]->reserved - h[activehd]->used );
            cmdline = vstralloc(cmdstr[cmd],
-                               " ", disk2serial(dp),
+                               " ", disk2serial(dp),
                                " ", h[activehd]->destname,
                                " ", chunksize,
                                " ", use,
@@ -384,28 +492,33 @@ disk_t *dp;
            cmdline = stralloc2(cmdstr[cmd], "\n");
        }
        break;
+    case QUIT:
+       cmdline = stralloc2(cmdstr[cmd], "\n");
+       break;
+    case DONE:
+    case FAILED:
+       if( dp) {
+           cmdline = vstralloc(cmdstr[cmd],
+                               " ", disk2serial(dp),
+                               "\n",  NULL);
+       } else {
+           cmdline = vstralloc(cmdstr[cmd], "\n");
+       }
+       break;
     default:
-       error("Don't know how to send %s command to dumper", cmdstr[cmd]);
+       error("Don't know how to send %s command to chunker", cmdstr[cmd]);
     }
     /*
      * Note: cmdline already has a '\n'.
      */
-    if(dumper->down) {
-       printf("driver: send-cmd time %s ignored to down dumper %s: %s",
-              walltime_str(curclock()), dumper->name, cmdline);
-    } else {
-       printf("driver: send-cmd time %s to %s: %s",
-              walltime_str(curclock()), dumper->name, cmdline);
+    printf("driver: send-cmd time %s to %s: %s",
+          walltime_str(curclock()), chunker->name, cmdline);
+    fflush(stdout);
+    if (fullwrite(chunker->fd, cmdline, strlen(cmdline)) < 0) {
+       printf("writing %s command: %s\n", chunker->name, strerror(errno));
        fflush(stdout);
-       for(l = 0, n = strlen(cmdline); l < n; l += s) {
-           if((s = write(dumper->infd, cmdline + l, n - l)) < 0) {
-               printf("writing %s command: %s\n", dumper->name, 
-                      strerror(errno));
-               fflush(stdout);
-               amfree(cmdline);
-               return 0;
-           }
-       }
+       amfree(cmdline);
+       return 0;
     }
     amfree(cmdline);
     return 1;
@@ -433,8 +546,8 @@ char *str;
        error("error [serial out of range 0..%d: %d]", MAX_SERIAL, s);
     }
     if(gen != stable[s].gen)
-       printf("driver: error time %s serial gen mismatch\n",
-              walltime_str(curclock()));
+       printf("driver: error time %s serial gen mismatch %s\n",
+              walltime_str(curclock()), str);
     return stable[s].dp;
 }
 
@@ -461,6 +574,37 @@ char *str;
 }
 
 
+void free_serial_dp(dp)
+disk_t *dp;
+{
+    int s;
+
+    for(s = 0; s < MAX_SERIAL; s++) {
+       if(stable[s].dp == dp) {
+           stable[s].gen = 0;
+           stable[s].dp = NULL;
+           return;
+       }
+    }
+
+    printf("driver: error time %s serial not found\n",
+          walltime_str(curclock()));
+}
+
+
+void check_unfree_serial()
+{
+    int s;
+
+    /* find used serial number */
+    for(s = 0; s < MAX_SERIAL; s++) {
+       if(stable[s].gen != 0 || stable[s].dp != NULL) {
+           printf("driver: error time %s bug: serial in use: %02d-%05ld\n",
+                  walltime_str(curclock()), s, stable[s].gen);
+       }
+    }
+}
+
 char *disk2serial(dp)
 disk_t *dp;
 {
@@ -469,7 +613,7 @@ disk_t *dp;
 
     for(s = 0; s < MAX_SERIAL; s++) {
        if(stable[s].dp == dp) {
-           ap_snprintf(str, sizeof(str), "%02d-%05ld", s, stable[s].gen);
+           snprintf(str, sizeof(str), "%02d-%05ld", s, stable[s].gen);
            return str;
        }
     }
@@ -487,7 +631,7 @@ disk_t *dp;
     stable[s].gen = generation++;
     stable[s].dp = dp;
 
-    ap_snprintf(str, sizeof(str), "%02d-%05ld", s, stable[s].gen);
+    snprintf(str, sizeof(str), "%02d-%05ld", s, stable[s].gen);
     return str;
 }
 
index bb5db74a82f8ef0d9cce6c6eb41a9cc245a0e024..0d53c94c4cbd3052ef078a8bc06b6d9a19d9ae41 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: driverio.h,v 1.13.2.7.4.3 2001/11/08 18:44:56 martinea Exp $
+ * $Id: driverio.h,v 1.32 2005/12/03 13:27:43 martinea Exp $
  *
  * driver-related helper functions
  */
 
+#include "event.h"
+
 #include "holding.h"
 #include "server_util.h"
 
 #define GLOBAL extern
 #endif
 
+/* chunker process structure */
+
+typedef struct chunker_s {
+    char *name;                        /* name of this chunker */
+    int pid;                   /* its pid */
+    int down;                  /* state */
+    int fd;                    /* read/write */
+    int result;
+    event_handle_t *ev_read;   /* read event handle */
+    struct dumper_s *dumper;
+} chunker_t;
+
 /* dumper process structure */
 
 typedef struct dumper_s {
-    char *name;                /* name of this dumper */
-    int pid;           /* its pid */
-    int busy, down;
-    int infd, outfd;
-    disk_t *dp;
+    char *name;                        /* name of this dumper */
+    int pid;                   /* its pid */
+    int busy, down;            /* state */
+    int fd;                    /* read/write */
+    int result;
+    int output_port;           /* output port */
+    event_handle_t *ev_read;   /* read event handle */
+    disk_t *dp;                        /* disk currently being dumped */
+    chunker_t *chunker;
 } dumper_t;
 
 typedef struct assignedhd_s {
@@ -63,6 +81,8 @@ typedef struct sched_s {
     int level, degr_level;
     long est_time, degr_time;
     unsigned long est_size, degr_size, act_size;
+    unsigned long origsize, dumpsize;
+    unsigned long dumptime, tapetime;
     char *dumpdate, *degr_dumpdate;
     int est_kps, degr_kps;
     char *destname;                            /* file/port name */
@@ -87,20 +107,27 @@ typedef struct holdalloc_s {
 #define holdalloc(hp)  ((holdalloc_t *) (hp)->up)
 
 GLOBAL dumper_t dmptable[MAX_DUMPERS];
+GLOBAL chunker_t chktable[MAX_DUMPERS];
+
+/* command/result tokens */
 
-GLOBAL int maxfd;
-GLOBAL fd_set readset;
 GLOBAL int taper, taper_busy, taper_pid;
+GLOBAL event_handle_t *taper_ev_read;
 
-void init_driverio();
+void init_driverio P((void));
 void startup_tape_process P((char *taper_program));
 void startup_dump_process P((dumper_t *dumper, char *dumper_program));
 void startup_dump_processes P((char *dumper_program, int inparallel));
+void startup_chunk_process P((chunker_t *chunker, char *chunker_program));
+
 cmd_t getresult P((int fd, int show, int *result_argc, char **result_argv, int max_arg));
 int taper_cmd P((cmd_t cmd, void *ptr, char *destname, int level, char *datestamp));
 int dumper_cmd P((dumper_t *dumper, cmd_t cmd, disk_t *dp));
+int chunker_cmd P((chunker_t *chunker, cmd_t cmd, disk_t *dp));
 disk_t *serial2disk P((char *str));
 void free_serial P((char *str));
+void free_serial_dp P((disk_t *dp));
+void check_unfree_serial P(());
 char *disk2serial P((disk_t *dp));
 void update_info_dumper P((disk_t *dp, long origsize, long dumpsize, long dumptime));
 void update_info_taper P((disk_t *dp, char *label, int filenum, int level));
diff --git a/server-src/dumper-krb4.c b/server-src/dumper-krb4.c
deleted file mode 100644 (file)
index 6dcca07..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991,1994 University of Maryland
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
- */
-/*
- * dumper-krb4.c - those bits of dumper code that deal with encrypting
- *                data streams over the network.  Even though these just
- *                call the underlying DES routines, the U.S. government
- *                considers this a munition.  Go figure.
- */
-#include "krb4-security.h"
-
-/*
- * NOTE:  This symbol must be the same as DATABUF_SIZE in
- * client-src/sendbackup-krb4.c
- * so that the encrypt/decrypt routines are working on the same sized buffers.
- * Really, this should be moved out of dumper.c so that both programs can use
- * the same symbol.  Hopefully that can be done later.  This is good enough
- * to get encryption working for now...
- *
- *                  - Chris Ross (cross@uu.net)  4-Jun-1998
- */
-#define        DATABUF_SIZE    DISK_BLOCK_BYTES
-
-int kamanda_port;
-CREDENTIALS cred;
-
-des_key_schedule sched;
-
-void decrypt_initialize()
-{
-    des_key_sched(cred.session, sched);
-}
-
-decrypt_buffer(buffer, size)
-char *buffer;
-int size;
-{
-    des_pcbc_encrypt((des_cblock *)buffer, 
-                    (des_cblock *)buffer, 
-                     size, sched, (des_cblock *)cred.session, DES_DECRYPT);
-}
-
-#define NAUGHTY_BITS_INITIALIZE                \
-    if(kencrypt) decrypt_initialize()
-
-#define NAUGHTY_BITS                   \
-    if(kencrypt) decrypt_buffer(databuf, DATABUF_SIZE)
index 6afc7c052b0f6b10025c166aefce79b5e193572f..1e008601cf65cfa5fc137bc1baa6741087f29ccf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -23,7 +23,7 @@
  * Authors: the Amanda Development Team.  Its members are listed in a
  * file named AUTHORS, in the root directory of this distribution.
  */
-/* $Id: dumper.c,v 1.75.2.14.2.7.2.17.2.4 2005/09/20 21:31:52 jrjackson Exp $
+/* $Id: dumper.c,v 1.170 2006/03/22 15:10:52 martinea Exp $
  *
  * requests remote amandad processes to dump filesystems
  */
 #include "arglist.h"
 #include "clock.h"
 #include "conffile.h"
+#include "event.h"
 #include "logfile.h"
+#include "packet.h"
 #include "protocol.h"
+#include "security.h"
 #include "stream.h"
 #include "token.h"
 #include "version.h"
 #include "fileheader.h"
 #include "amfeatures.h"
 #include "server_util.h"
-#include "holding.h"
-
-#ifdef KRB4_SECURITY
-#include "dumper-krb4.c"
-#else
-#define NAUGHTY_BITS_INITIALIZE                /* I'd tell you what these do */
-#define NAUGHTY_BITS                   /* but then I'd have to kill you */
-#endif
-
+#include "util.h"
 
 #ifndef SEEK_SET
 #define SEEK_SET 0
 #endif
 
 #define CONNECT_TIMEOUT        5*60
-#define MESGBUF_SIZE   4*1024
 
 #define STARTUP_TIMEOUT 60
 
-int interactive;
-char *handle = NULL;
-
-char databuf[DISK_BLOCK_BYTES];
-char mesgbuf[MESGBUF_SIZE+1];
-char *errstr = NULL;
-char *datain;                          /* where to read in data */
-char *dataout;                         /* where to write out data */
-char *datalimit;                       /* end of the data area */
-int abort_pending;
-long dumpsize;                         /* total size of dump */
-long dumpbytes;
-long origsize;
-long filesize;                         /* size of current holding disk file */
-int nb_header_block;
-static enum { srvcomp_none, srvcomp_fast, srvcomp_best } srvcompress;
+struct databuf {
+    int fd;                    /* file to flush to */
+    char *buf;
+    char *datain;              /* data buffer markers */
+    char *dataout;
+    char *datalimit;
+    pid_t compresspid;         /* valid if fd is pipe to compress */
+    pid_t encryptpid;          /* valid if fd is pipe to encrypt */
+};
+
+static char *handle = NULL;
+
+static char *errstr = NULL;
+static long dumpbytes;
+static long dumpsize, headersize, origsize;
+
+static comp_t srvcompress = COMP_NONE;
+char *srvcompprog = NULL;
+char *clntcompprog = NULL;
+
+static encrypt_t srvencrypt = ENCRYPT_NONE;
+char *srv_encrypt = NULL;
+char *clnt_encrypt = NULL;
+char *srv_decrypt_opt = NULL;
+char *clnt_decrypt_opt = NULL;
 
 static FILE *errf = NULL;
-char *filename = NULL;                 /* holding disk base file name */
-string_t cont_filename;
-char *hostname = NULL;
+static char *hostname = NULL;
 am_feature_t *their_features = NULL;
-char *diskname = NULL;
-char *device = NULL;
-char *options = NULL;
-char *progname = NULL;
-int level;
-char *dumpdate = NULL;
-long chunksize;
-long use;                              /* space remaining in this hold disk */
-char *datestamp;
-char *backup_name = NULL;
-char *recover_cmd = NULL;
-char *compress_suffix = NULL;
-int conf_dtimeout;
-
-dumpfile_t file;
-int filename_seq;
-long split_size;                       /* next dumpsize we will split at */
-
-int datafd = -1;
-int mesgfd = -1;
-int indexfd = -1;
-int amanda_port;
+static char *diskname = NULL;
+static char *device = NULL;
+static char *options = NULL;
+static char *progname = NULL;
+static int level;
+static char *dumpdate = NULL;
+static char *datestamp;
+static int conf_dtimeout;
+static int indexfderror;
+
+static dumpfile_t file;
+
+static struct {
+    const char *name;
+    security_stream_t *fd;
+} streams[] = {
+#define        DATAFD  0
+    { "DATA", NULL },
+#define        MESGFD  1
+    { "MESG", NULL },
+#define        INDEXFD 2
+    { "INDEX", NULL },
+};
+#define        NSTREAMS        (sizeof(streams) / sizeof(streams[0]))
 
 static am_feature_t *our_features = NULL;
 static char *our_feature_string = NULL;
 
 /* local functions */
-int main P((int main_argc, char **main_argv));
-int do_dump P((int mesgfd, int datafd, int indexfd, int outfd));
-void check_options P((char *options));
-void service_ports_init P((void));
-int write_tapeheader P((int outfd, dumpfile_t *type));
-int write_dataptr P((int outf));
-int update_dataptr P((int *outf, int size));
+int main P((int, char **));
+static int do_dump P((struct databuf *));
+static void check_options P((char *));
+static void finish_tapeheader P((dumpfile_t *));
+static int write_tapeheader P((int, dumpfile_t *));
+static void databuf_init P((struct databuf *, int));
+static int databuf_write P((struct databuf *, const void *, int));
+static int databuf_flush P((struct databuf *));
 static void process_dumpeof P((void));
-static void process_dumpline P((char *str));
-static void add_msg_data P((char *str, int len));
-static void log_msgout P((logtype_t typ));
-void sendbackup_response P((proto_t *p, pkt_t *pkt));
-int startup_dump P((char *hostname, char *disk, char *device, int level,
-                   char *dumpdate, char *progname, char *options));
-
-
-void check_options(options)
-char *options;
-{
-#ifdef KRB4_SECURITY
-    krb4_auth = strstr(options, "krb4-auth;") != NULL;
-    kencrypt = strstr(options, "kencrypt;") != NULL;
-#endif
-    if (strstr(options, "srvcomp-best;") != NULL)
-      srvcompress = srvcomp_best;
+static void process_dumpline P((const char *));
+static void add_msg_data P((const char *, size_t));
+static void parse_info_line P((char *));
+static void log_msgout P((logtype_t));
+
+static int runcompress P((int, pid_t *, comp_t));
+static int runencrypt P((int, pid_t *,  encrypt_t));
+
+static void sendbackup_response P((void *, pkt_t *, security_handle_t *));
+static int startup_dump P((const char *, const char *, const char *, int,
+                          const char *, const char *, const char *));
+static void stop_dump P((void));
+
+static void read_indexfd P((void *, void *, ssize_t));
+static void read_datafd P((void *, void *, ssize_t));
+static void read_mesgfd P((void *, void *, ssize_t));
+static void timeout P((int));
+static void timeout_callback P((void *));
+
+static void
+check_options(options)
+    char *options;
+{      
+  char *compmode = NULL;
+  char *compend  = NULL;
+  char *encryptmode = NULL;
+  char *encryptend = NULL;
+  char *decryptmode = NULL;
+  char *decryptend = NULL;
+
+    /* parse the compression option */
+  if (strstr(options, "srvcomp-best;") != NULL) 
+      srvcompress = COMP_BEST;
     else if (strstr(options, "srvcomp-fast;") != NULL)
-      srvcompress = srvcomp_fast;
-    else
-      srvcompress = srvcomp_none;
-}
-
-void service_ports_init()
-{
-    struct servent *amandad;
-
-    if((amandad = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL) {
-       amanda_port = AMANDA_SERVICE_DEFAULT;
-       log_add(L_WARNING, "no %s/udp service, using default port %d",
-               AMANDA_SERVICE_NAME, AMANDA_SERVICE_DEFAULT);
+      srvcompress = COMP_FAST;
+    else if ((compmode = strstr(options, "srvcomp-cust=")) != NULL) {
+       compend = strchr(compmode, ';');
+       if (compend ) {
+           srvcompress = COMP_SERV_CUST;
+           *compend = '\0';
+           srvcompprog = stralloc(compmode + strlen("srvcomp-cust="));
+           *compend = ';';
+       }
+    } else if ((compmode = strstr(options, "comp-cust=")) != NULL) {
+       compend = strchr(compmode, ';');
+       if (compend) {
+           srvcompress = COMP_CUST;
+           *compend = '\0';
+           clntcompprog = stralloc(compmode + strlen("comp-cust="));
+           *compend = ';';
+       }
     }
-    else
-       amanda_port = ntohs(amandad->s_port);
-
-#ifdef KRB4_SECURITY
-    if((amandad = getservbyname(KAMANDA_SERVICE_NAME, "udp")) == NULL) {
-       kamanda_port = KAMANDA_SERVICE_DEFAULT;
-       log_add(L_WARNING, "no %s/udp service, using default port %d",
-               KAMANDA_SERVICE_NAME, KAMANDA_SERVICE_DEFAULT);
+    else {
+      srvcompress = COMP_NONE;
+    }
+    
+
+    /* now parse the encryption option */
+    if ((encryptmode = strstr(options, "encrypt-serv-cust=")) != NULL) {
+      encryptend = strchr(encryptmode, ';');
+      if (encryptend) {
+           srvencrypt = ENCRYPT_SERV_CUST;
+           *encryptend = '\0';
+           srv_encrypt = stralloc(encryptmode + strlen("encrypt-serv-cust="));
+           *encryptend = ';';
+      }
+    } else if ((encryptmode = strstr(options, "encrypt-cust=")) != NULL) {
+      encryptend = strchr(encryptmode, ';');
+      if (encryptend) {
+           srvencrypt = ENCRYPT_CUST;
+           *encryptend = '\0';
+           clnt_encrypt = stralloc(encryptmode + strlen("encrypt-cust="));
+           *encryptend = ';';
+      }
+    } else {
+      srvencrypt = ENCRYPT_NONE;
+    }
+    /* get the decryption option parameter */
+    if ((decryptmode = strstr(options, "server-decrypt-option=")) != NULL) {
+      decryptend = strchr(decryptmode, ';');
+      if (decryptend) {
+       *decryptend = '\0';
+       srv_decrypt_opt = stralloc(decryptmode + strlen("server-decrypt-option="));
+       *decryptend = ';';
+      }
+    } else if ((decryptmode = strstr(options, "client-decrypt-option=")) != NULL) {
+      decryptend = strchr(decryptmode, ';');
+      if (decryptend) {
+       *decryptend = '\0';
+       clnt_decrypt_opt = stralloc(decryptmode + strlen("client-decrypt-option="));
+       *decryptend = ';';
+      }
     }
-    else
-       kamanda_port = ntohs(amandad->s_port);
-#endif
 }
 
 
-int main(main_argc, main_argv)
-int main_argc;
-char **main_argv;
+int
+main(main_argc, main_argv)
+    int main_argc;
+    char **main_argv;
 {
+    static struct databuf db;
     struct cmdargs cmdargs;
     cmd_t cmd;
-    int outfd, protocol_port, taper_port, rc;
-    dgram_t *msg;
+    int outfd = -1;
+    int taper_port, rc;
     unsigned long malloc_hist_1, malloc_size_1;
     unsigned long malloc_hist_2, malloc_size_2;
     char *conffile;
     char *q = NULL;
-    char *tmp_filename = NULL, *pc;
     int a;
 
     safe_fd(-1, 0);
 
     set_pname("dumper");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE);
@@ -217,42 +274,37 @@ char **main_argv;
     }
     amfree(conffile);
 
-    /* set up dgram port first thing */
-
-    msg = dgram_alloc();
-    if(dgram_bind(msg, &protocol_port) == -1)
-       error("could not bind result datagram port: %s", strerror(errno));
-
+    /*
+     * Make our effective uid nonprivlidged, but keep our real uid as root
+     * in case we need to get back (to bind privlidged ports, etc).
+     */
     if(geteuid() == 0) {
-       /* set both real and effective uid's to real uid, likewise for gid */
+       uid_t ruid = getuid();
+       setuid(0);
+       seteuid(ruid);
        setgid(getgid());
-       setuid(getuid());
     }
-#ifdef BSD_SECURITY
+#if defined BSD_SECURITY && !defined SSH_SECURITY
     else error("must be run setuid root to communicate correctly");
 #endif
 
     fprintf(stderr,
-           "%s: pid %ld executable %s version %s, using port %d\n",
+           "%s: pid %ld executable %s version %s\n",
            get_pname(), (long) getpid(),
-           main_argv[0], version(), protocol_port);
+           main_argv[0], version());
     fflush(stderr);
 
     /* now, make sure we are a valid user */
 
-    if(getpwuid(getuid()) == NULL)
+    if (getpwuid(getuid()) == NULL)
        error("can't get login name for my uid %ld", (long)getuid());
 
     signal(SIGPIPE, SIG_IGN);
 
-    interactive = isatty(0);
-
-    amfree(datestamp);
     datestamp = construct_datestamp(NULL);
     conf_dtimeout = getconf_int(CNF_DTIMEOUT);
 
-    service_ports_init();
-    proto_init(msg->socket, time(0), 16);
+    protocol_init();
 
     do {
        cmd = getcmd(&cmdargs);
@@ -260,158 +312,6 @@ char **main_argv;
        switch(cmd) {
        case QUIT:
            break;
-       case FILE_DUMP:
-           /*
-            * FILE-DUMP
-            *   handle
-            *   filename
-            *   host
-            *   features
-            *   disk
-            *   device
-            *   level
-            *   dumpdate
-            *   chunksize
-            *   progname
-            *   use
-            *   options
-            */
-           cmdargs.argc++;                     /* true count of args */
-           a = 2;
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: handle]");
-           }
-           handle = newstralloc(handle, cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: filename]");
-           }
-           filename = newstralloc(filename, cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: hostname]");
-           }
-           hostname = newstralloc(hostname, cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: features]");
-           }
-           am_release_feature_set(their_features);
-           their_features = am_string_to_feature(cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: diskname]");
-           }
-           diskname = newstralloc(diskname, cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: device]");
-           }
-           device = newstralloc(device, cmdargs.argv[a++]);
-           if(strcmp(device, "NODEVICE") == 0) amfree(device);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: level]");
-           }
-           level = atoi(cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: dumpdate]");
-           }
-           dumpdate = newstralloc(dumpdate, cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: chunksize]");
-           }
-           chunksize = am_floor(atoi(cmdargs.argv[a++]), DISK_BLOCK_KB);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: progname]");
-           }
-           progname = newstralloc(progname, cmdargs.argv[a++]);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: use]");
-           }
-           use = am_floor(atoi(cmdargs.argv[a++]), DISK_BLOCK_KB);
-
-           if(a >= cmdargs.argc) {
-               error("error [dumper FILE-DUMP: not enough args: options]");
-           }
-           options = newstralloc(options, cmdargs.argv[a++]);
-
-           if(a != cmdargs.argc) {
-               error("error [dumper FILE-DUMP: too many args: %d != %d]",
-                     cmdargs.argc, a);
-           }
-
-           cont_filename[0] = '\0';
-
-           tmp_filename = newvstralloc(tmp_filename, filename, ".tmp", NULL);
-           pc = strrchr(tmp_filename, '/');
-           *pc = '\0';
-           mkholdingdir(tmp_filename);
-           *pc = '/';
-           outfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
-           if(outfd == -1) {
-               int save_errno = errno;
-               q = squotef("[main holding file \"%s\": %s]",
-                           tmp_filename, strerror(errno));
-               if(save_errno == ENOSPC) {
-                   putresult(NO_ROOM, "%s %lu\n", handle, use);
-                   putresult(TRYAGAIN, "%s %s\n", handle, q);
-               }
-               else {
-                   putresult(FAILED, "%s %s\n", handle, q);
-               }
-               amfree(q);
-               break;
-           }
-           filename_seq = 1;
-
-           check_options(options);
-
-           rc = startup_dump(hostname,
-                             diskname,
-                             device,
-                             level,
-                             dumpdate,
-                             progname,
-                             options);
-           if(rc) {
-               q = squote(errstr);
-               putresult(rc == 2? FAILED : TRYAGAIN, "%s %s\n",
-                         handle, q);
-               if(rc == 2) {
-                   log_add(L_FAIL, "%s %s %s %d [%s]", hostname, diskname,
-                           datestamp, level, errstr);
-               }
-               amfree(q);
-               /* do need to close if TRY-AGAIN, doesn't hurt otherwise */
-               if (mesgfd != -1)
-                   aclose(mesgfd);
-               if (datafd != -1)
-                   aclose(datafd);
-               if (indexfd != -1)
-                   aclose(indexfd);
-               if (outfd != -1)
-                   aclose(outfd);
-               break;
-           }
-
-           abort_pending = 0;
-           split_size = (chunksize>use)?use:chunksize;
-           use -= split_size;
-           if(do_dump(mesgfd, datafd, indexfd, outfd)) {
-           }
-           aclose(mesgfd);
-           aclose(datafd);
-           if (indexfd != -1)
-               aclose(indexfd);
-           aclose(outfd);
-           if(abort_pending) putresult(ABORT_FINISHED, "%s\n", handle);
-           break;
 
        case PORT_DUMP:
            /*
@@ -436,12 +336,12 @@ char **main_argv;
            handle = newstralloc(handle, cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: port]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            taper_port = atoi(cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: hostname]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            hostname = newstralloc(hostname, cmdargs.argv[a++]);
 
@@ -452,33 +352,33 @@ char **main_argv;
            their_features = am_string_to_feature(cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: diskname]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            diskname = newstralloc(diskname, cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: device]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            device = newstralloc(device, cmdargs.argv[a++]);
            if(strcmp(device,"NODEVICE") == 0) amfree(device);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: level]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            level = atoi(cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: dumpdate]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            dumpdate = newstralloc(dumpdate, cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: progname]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            progname = newstralloc(progname, cmdargs.argv[a++]);
 
            if(a >= cmdargs.argc) {
-               error("error [dumper PORT-DUMP: not enough args: options]");
+               error("error [dumper PORT-DUMP: not enough args: handle]");
            }
            options = newstralloc(options, cmdargs.argv[a++]);
 
@@ -487,20 +387,17 @@ char **main_argv;
                      cmdargs.argc, a);
            }
 
-           filename = newstralloc(filename, "<taper program>");
-           cont_filename[0] = '\0';
-
            /* connect outf to taper port */
 
            outfd = stream_client("localhost", taper_port,
-                                 STREAM_BUFSIZE, -1, NULL);
-           if(outfd == -1) {
+                                 STREAM_BUFSIZE, -1, NULL, 0);
+           if (outfd == -1) {
                q = squotef("[taper port open: %s]", strerror(errno));
                putresult(FAILED, "%s %s\n", handle, q);
                amfree(q);
                break;
            }
-           filename_seq = 1;
+           databuf_init(&db, outfd);
 
            check_options(options);
 
@@ -511,37 +408,18 @@ char **main_argv;
                              dumpdate,
                              progname,
                              options);
-           if(rc) {
+           if (rc != 0) {
                q = squote(errstr);
                putresult(rc == 2? FAILED : TRYAGAIN, "%s %s\n",
-                         handle, q);
-               if(rc == 2) {
+                   handle, q);
+               if (rc == 2)
                    log_add(L_FAIL, "%s %s %s %d [%s]", hostname, diskname,
-                           datestamp, level, errstr);
-               }
+                       datestamp, level, errstr);
                amfree(q);
-               /* do need to close if TRY-AGAIN, doesn't hurt otherwise */
-               if (mesgfd != -1)
-                   aclose(mesgfd);
-               if (datafd != -1)
-                   aclose(datafd);
-               if (indexfd != -1)
-                   aclose(indexfd);
-               if (outfd != -1)
-                   aclose(outfd);
-               break;
-           }
-
-           abort_pending = 0;
-           split_size = -1;
-           if(do_dump(mesgfd, datafd, indexfd, outfd)) {
+           } else {
+               if (do_dump(&db)) {
+               }
            }
-           aclose(mesgfd);
-           aclose(datafd);
-           if (indexfd != -1)
-               aclose(indexfd);
-           aclose(outfd);
-           if(abort_pending) putresult(ABORT_FINISHED, "%s\n", handle);
            break;
 
        default:
@@ -554,372 +432,202 @@ char **main_argv;
            }
            putresult(BAD_COMMAND, "%s\n", q);
            amfree(q);
+           break;
        }
-       while(wait(NULL) != -1);
+
+       if (outfd != -1)
+           aclose(outfd);
     } while(cmd != QUIT);
 
-    amfree(tmp_filename);
     amfree(errstr);
-    amfree(msg);
     amfree(datestamp);
-    amfree(backup_name);
-    amfree(recover_cmd);
-    amfree(compress_suffix);
     amfree(handle);
-    amfree(filename);
     amfree(hostname);
     amfree(diskname);
     amfree(device);
     amfree(dumpdate);
     amfree(progname);
+    amfree(srvcompprog);
+    amfree(clntcompprog);
+    amfree(srv_encrypt);
+    amfree(clnt_encrypt);
+    amfree(srv_decrypt_opt);
+    amfree(clnt_decrypt_opt);
     amfree(options);
     amfree(config_dir);
     amfree(config_name);
-    amfree(our_feature_string);
-    am_release_feature_set(our_features);
-    our_features = NULL;
-    am_release_feature_set(their_features);
-    their_features = NULL;
 
     malloc_size_2 = malloc_inuse(&malloc_hist_2);
 
-    if(malloc_size_1 != malloc_size_2) {
+    if (malloc_size_1 != malloc_size_2)
        malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
-    }
 
-    return 0;
+    exit(0);
 }
 
 
-int write_dataptr(outf)
-int outf;
+/*
+ * Initialize a databuf.  Takes a writeable file descriptor.
+ */
+static void
+databuf_init(db, fd)
+    struct databuf *db;
+    int fd;
 {
-    int w;
-    int written;
 
-    written = w = 0;
-    while(dataout < datain) {
-       if((w = write(outf, dataout, datain - dataout)) < 0) {
-           break;
-       }
-       dataout += w;
-       written += w;
-    }
-    dumpbytes += written;
-    dumpsize += (dumpbytes / 1024);
-    filesize += (dumpbytes / 1024);
-    dumpbytes %= 1024;
-    if(w < 0) {
-       if(errno != ENOSPC) {
-           errstr = squotef("data write: %s", strerror(errno));
-           return 1;
-       }
-       /*
-        * NO-ROOM is informational only.  Later, RQ_MORE_DISK will be
-        * issued to use another holding disk.
-        */
-       putresult(NO_ROOM, "%s %lu\n", handle, use+split_size-dumpsize);
-       use = 0;                                /* force RQ_MORE_DISK */
-       split_size = dumpsize;
-    }
-    if(dataout == datain) {
-       /*
-        * We flushed the whole buffer so reset to use it all.
-        */
-       dataout = datain = databuf;
-    }
-    return 0;
+    db->fd = fd;
+    db->datain = db->dataout = db->datalimit = NULL;
+    db->compresspid = -1;
+    db->encryptpid = -1;
 }
 
-int update_dataptr(p_outfd, size)
-int *p_outfd, size;
+
 /*
  * Updates the buffer pointer for the input data buffer.  The buffer is
- * written if it is full or we are at EOF.
+ * written regardless of how much data is present, since we know we
+ * are writing to a socket (to chunker) and there is no need to maintain
+ * any boundaries.
  */
+static int
+databuf_write(db, buf, size)
+    struct databuf *db;
+    const void *buf;
+    int size;
 {
-    int outfd = *p_outfd;
-    int rc = 0;
-    char *arg_filename = NULL;
-    char *new_filename = NULL;
-    char *tmp_filename = NULL;
-    char *pc;
-    char sequence[NUM_STR_SIZE];
-    int new_outfd = -1;
-    struct cmdargs cmdargs;
-    cmd_t cmd;
-    filetype_t save_type;
-    long left_in_chunk;
-    int a;
-    char *q;
-
-    datain += size;
-
-    while(rc == 0 && ((size == 0 && dataout < datain) || datain >= datalimit)) {
-
-       NAUGHTY_BITS;
-
-       /* We open a new chunkfile if                                    */
-       /*   We have something to write (dataout < datain)               */
-       /*   We have a split_size defined (split_size > 0)               */
-       /*   The current file is already filled (dumpsize >= split_size) */
-
-       while(dataout < datain && split_size > 0 && dumpsize >= split_size) {
-           amfree(new_filename);
-           if(use == 0) {
-               /*
-                * Probably no more space on this disk.  Request more.
-                */
-                putresult(RQ_MORE_DISK, "%s\n", handle);
-                cmd = getcmd(&cmdargs);
-                if(cmd == CONTINUE) {
-                   /*
-                    * CONTINUE
-                    *   serial
-                    *   filename
-                    *   chunksize
-                    *   use
-                    */
-                   cmdargs.argc++;             /* true count of args */
-                   a = 3;
-
-                   if(a >= cmdargs.argc) {
-                       error("error [dumper CONTINUE: not enough args: filename]");
-                   }
-                   arg_filename = newstralloc(arg_filename, cmdargs.argv[a++]);
-
-                   if(a >= cmdargs.argc) {
-                       error("error [dumper CONTINUE: not enough args: chunksize]");
-                   }
-                   chunksize = atoi(cmdargs.argv[a++]);
-                   chunksize = am_floor(chunksize, DISK_BLOCK_KB);
-
-                   if(a >= cmdargs.argc) {
-                       error("error [dumper CONTINUE: not enough args: use]");
-                   }
-                    use = atoi(cmdargs.argv[a++]);
-
-                   if(a != cmdargs.argc) {
-                       error("error [dumper CONTINUE: too many args: %d != %d]",
-                             cmdargs.argc, a);
-                   }
-
-                   if(strcmp(filename, arg_filename) == 0) {
-                       /*
-                        * Same disk, so use what room is left up to the
-                        * next chunk boundary or the amount we were given,
-                        * whichever is less.
-                        */
-                       left_in_chunk = chunksize - filesize;
-                       if(left_in_chunk > use) {
-                           split_size += use;
-                           use = 0;
-                       } else {
-                           split_size += left_in_chunk;
-                           use -= left_in_chunk;
-                       }
-                       if(left_in_chunk > 0) {
-                           /*
-                            * We still have space in this chunk.
-                            */
-                           break;
-                       }
-                   } else {
-                       /*
-                        * Different disk, so use new file.
-                        */
-                       filename = newstralloc(filename, arg_filename);
-                   }
-                } else if(cmd == ABORT) {
-                    abort_pending = 1;
-                    errstr = newstralloc(errstr, "ERROR");
-                    rc = 1;
-                   goto common_exit;
-               } else {
-                   if(cmdargs.argc >= 1) {
-                       q = squote(cmdargs.argv[1]);
-                   } else if(cmdargs.argc >= 0) {
-                       q = squote(cmdargs.argv[0]);
-                   } else {
-                       q = stralloc("(no input?)");
-                   }
-                    error("error [bad command after RQ-MORE-DISK: \"%s\"]", q);
-                }
-           }
+    db->buf = (char *)buf;
+    db->datain = db->datalimit = db->buf + size;
+    db->dataout = db->buf;
+    return databuf_flush(db);
+}
 
-           ap_snprintf(sequence, sizeof(sequence), "%d", filename_seq);
-           new_filename = newvstralloc(new_filename,
-                                       filename,
-                                       ".",
-                                       sequence,
-                                       NULL);
-           tmp_filename = newvstralloc(tmp_filename,
-                                       new_filename,
-                                       ".tmp",
-                                       NULL);
-           pc = strrchr(tmp_filename, '/');
-           *pc = '\0';
-           mkholdingdir(tmp_filename);
-           *pc = '/';
-           new_outfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
-           if(new_outfd == -1) {
-               int save_errno = errno;
-
-               errstr = squotef("creating chunk holding file \"%s\": %s",
-                                tmp_filename,
-                                strerror(save_errno));
-               if(save_errno == ENOSPC) {
-                   putresult(NO_ROOM, "%s %lu\n",
-                             handle, 
-                             use + split_size - dumpsize);
-                   use = 0;            /* force RQ_MORE_DISK */
-                   split_size = dumpsize;
-                   continue;
-               }
-               aclose(outfd);
-               rc = 1;
-               goto common_exit;
-           }
-           save_type = file.type;
-           file.type = F_CONT_DUMPFILE;
-           file.cont_filename[0] = '\0';
-           if(write_tapeheader(new_outfd, &file)) {
-               int save_errno = errno;
-
-               aclose(new_outfd);
-               unlink(tmp_filename);
-               if(save_errno == ENOSPC) {
-                   putresult(NO_ROOM, "%s %lu\n",
-                             handle, 
-                             use + split_size - dumpsize);
-                   use = 0;                    /* force RQ_MORE_DISK */
-                   split_size = dumpsize;
-                   continue;
-               }
-               errstr = squotef("write_tapeheader file \"%s\": %s",
-                                tmp_filename, strerror(errno));
-               rc = 1;
-               goto common_exit;
-           }
-           if(lseek(outfd, (off_t)0, SEEK_SET) != 0) {
-               errstr = squotef("cannot lseek: %s", strerror(errno));
-               aclose(new_outfd);
-               unlink(tmp_filename);
-               rc = 1;
-               goto common_exit;
-           }
-           strncpy(file.cont_filename, new_filename, 
-                   sizeof(file.cont_filename));
-           file.cont_filename[sizeof(file.cont_filename)-1] = '\0';
-           file.type = save_type;
-           if(write_tapeheader(outfd, &file)) {
-               errstr = squotef("write_tapeheader file linked to \"%s\": %s",
-                                tmp_filename, strerror(errno));
-               aclose(new_outfd);
-               unlink(tmp_filename);
-               rc = 1;
-               goto common_exit;
-           }
-           file.type = F_CONT_DUMPFILE;
-           strncpy(cont_filename, new_filename, sizeof(cont_filename));
-           cont_filename[sizeof(cont_filename)-1] = '\0';
+/*
+ * Write out the buffer to chunker.
+ */
+static int
+databuf_flush(db)
+    struct databuf *db;
+{
+    int written;
 
-           aclose(outfd);
-           *p_outfd = outfd = new_outfd;
-           new_outfd = -1;
-
-           dumpsize += DISK_BLOCK_KB;
-           filesize = DISK_BLOCK_KB;
-           split_size += (chunksize>use)?use:chunksize;
-           use = (chunksize>use)?0:use-chunksize;
-           nb_header_block++;
-           filename_seq++;
-       }
-       rc = write_dataptr(outfd);
+    /*
+     * If there's no data, do nothing.
+     */
+    if (db->dataout >= db->datain) {
+       return 0;
     }
 
-common_exit:
-
-    amfree(new_filename);
-    amfree(tmp_filename);
-    amfree(arg_filename);
-    return rc;
+    /*
+     * Write out the buffer
+     */
+    written = fullwrite(db->fd, db->dataout, db->datain - db->dataout);
+    if (written > 0) {
+       db->dataout += written;
+        dumpbytes += written;
+    }
+    if (dumpbytes >= 1024) {
+       dumpsize += (dumpbytes / 1024);
+       dumpbytes %= 1024;
+    }
+    if (written < 0) {
+       errstr = squotef("data write: %s", strerror(errno));
+       return -1;
+    }
+    db->datain = db->dataout = db->buf;
+    return 0;
 }
 
+static int dump_result;
+static int status;
+#define        GOT_INFO_ENDLINE        (1 << 0)
+#define        GOT_SIZELINE            (1 << 1)
+#define        GOT_ENDLINE             (1 << 2)
+#define        HEADER_DONE             (1 << 3)
 
-static char *msgbuf = NULL;
-int got_info_endline;
-int got_sizeline;
-int got_endline;
-int dump_result;
 
-static void process_dumpeof()
+static void
+process_dumpeof()
 {
     /* process any partial line in msgbuf? !!! */
-    if(msgbuf != NULL) {
-       fprintf(errf,"? %s: error [partial line in msgbuf: %ld bytes]\n",
-               get_pname(), (long) strlen(msgbuf));
-       fprintf(errf,"? %s: error [partial line in msgbuf: \"%s\"]\n",
-               get_pname(), msgbuf);
-    }
-    if(!got_sizeline && dump_result < 2) {
+    add_msg_data(NULL, 0);
+    if(!ISSET(status, GOT_SIZELINE) && dump_result < 2) {
        /* make a note if there isn't already a failure */
-       fprintf(errf,"? %s: strange [missing size line from sendbackup]\n",
+       fprintf(errf,
+               "? %s: strange [missing size line from sendbackup]\n",
                get_pname());
+       if(errstr == NULL) {
+           errstr = stralloc("missing size line from sendbackup");
+       }
        dump_result = max(dump_result, 2);
     }
 
-    if(!got_endline && dump_result < 2) {
-       fprintf(errf,"? %s: strange [missing end line from sendbackup]\n",
+    if(!ISSET(status, GOT_ENDLINE) && dump_result < 2) {
+       fprintf(errf,
+               "? %s: strange [missing end line from sendbackup]\n",
                get_pname());
+       if(errstr == NULL) {
+           errstr = stralloc("missing end line from sendbackup");
+       }
        dump_result = max(dump_result, 2);
     }
 }
 
-/* Parse an information line from the client.
-** We ignore unknown parameters and only remember the last
-** of any duplicates.
-*/
-static void parse_info_line(str)
-char *str;
+/*
+ * Parse an information line from the client.
+ * We ignore unknown parameters and only remember the last
+ * of any duplicates.
+ */
+static void
+parse_info_line(str)
+    char *str;
 {
-    if(strcmp(str, "end") == 0) {
-       got_info_endline = 1;
+    static const struct {
+       const char *name;
+       char *value;
+       size_t len;
+    } fields[] = {
+       { "BACKUP", file.program, sizeof(file.program) },
+       { "RECOVER_CMD", file.recover_cmd, sizeof(file.recover_cmd) },
+       { "COMPRESS_SUFFIX", file.comp_suffix, sizeof(file.comp_suffix) },
+       { "SERVER_CUSTOM_COMPRESS", file.srvcompprog, sizeof(file.srvcompprog) },
+       { "CLIENT_CUSTOM_COMPRESS", file.clntcompprog, sizeof(file.clntcompprog) },
+       { "SERVER_ENCRYPT", file.srv_encrypt, sizeof(file.srv_encrypt) },
+       { "CLIENT_ENCRYPT", file.clnt_encrypt, sizeof(file.clnt_encrypt) },
+       { "SERVER_DECRYPT_OPTION", file.srv_decrypt_opt, sizeof(file.srv_decrypt_opt) },
+       { "CLIENT_DECRYPT_OPTION", file.clnt_decrypt_opt, sizeof(file.clnt_decrypt_opt) }
+    };
+    char *name, *value;
+    int i;
+
+    if (strcmp(str, "end") == 0) {
+       SET(status, GOT_INFO_ENDLINE);
        return;
     }
 
-#define sc "BACKUP="
-    if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-       backup_name = newstralloc(backup_name, str + sizeof(sc)-1);
+    name = strtok(str, "=");
+    if (name == NULL)
        return;
-    }
-#undef sc
-
-#define sc "RECOVER_CMD="
-    if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-       recover_cmd = newstralloc(recover_cmd, str + sizeof(sc)-1);
+    value = strtok(NULL, "");
+    if (value == NULL)
        return;
-    }
-#undef sc
 
-#define sc "COMPRESS_SUFFIX="
-    if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-       compress_suffix = newstralloc(compress_suffix, str + sizeof(sc)-1);
-       return;
+    for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) {
+       if (strcmp(name, fields[i].name) == 0) {
+           strncpy(fields[i].value, value, fields[i].len - 1);
+           fields[i].value[fields[i].len - 1] = '\0';
+           break;
+       }
     }
-#undef sc
 }
 
-static void process_dumpline(str)
-char *str;
+static void
+process_dumpline(str)
+    const char *str;
 {
-    char *s, *fp;
-    int ch;
+    char *buf, *tok;
 
-    s = str;
-    ch = *s++;
+    buf = stralloc(str);
 
-    switch(ch) {
+    switch (*buf) {
     case '|':
        /* normal backup output line */
        break;
@@ -929,241 +637,303 @@ char *str;
        break;
     case 's':
        /* a sendbackup line, just check them all since there are only 5 */
-#define sc "sendbackup: start"
-       if(strncmp(str, sc, sizeof(sc)-1) == 0) {
+       tok = strtok(buf, " ");
+       if (tok == NULL || strcmp(tok, "sendbackup:") != 0)
+           goto bad_line;
+
+       tok = strtok(NULL, " ");
+       if (tok == NULL)
+           goto bad_line;
+
+       if (strcmp(tok, "start") == 0)
            break;
-       }
-#undef sc
-#define sc "sendbackup: size"
-       if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-           s += sizeof(sc)-1;
-           ch = s[-1];
-           skip_whitespace(s, ch);
-           if(ch) {
-               origsize = (long)atof(str + sizeof(sc)-1);
-               got_sizeline = 1;
-               break;
+
+       if (strcmp(tok, "size") == 0) {
+           tok = strtok(NULL, "");
+           if (tok != NULL) {
+               origsize = (long)atof(tok);
+               SET(status, GOT_SIZELINE);
            }
+           break;
        }
-#undef sc
-#define sc "sendbackup: end"
-       if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-           got_endline = 1;
+
+       if (strcmp(tok, "end") == 0) {
+           SET(status, GOT_ENDLINE);
            break;
        }
-#undef sc
-#define sc "sendbackup: warning"
-       if(strncmp(str, sc, sizeof(sc)-1) == 0) {
+
+       if (strcmp(tok, "warning") == 0) {
            dump_result = max(dump_result, 1);
            break;
        }
-#undef sc
-#define sc "sendbackup: error"
-       if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-           s += sizeof(sc)-1;
-           ch = s[-1];
-#undef sc
-           got_endline = 1;
+
+       if (strcmp(tok, "error") == 0) {
+           SET(status, GOT_ENDLINE);
            dump_result = max(dump_result, 2);
-           skip_whitespace(s, ch);
-           if(ch == '\0' || ch != '[') {
-               errstr = newvstralloc(errstr,
-                                     "bad remote error: ", str,
-                                     NULL);
+
+           tok = strtok(NULL, "");
+           if (tok == NULL || *tok != '[') {
+               errstr = newvstralloc(errstr, "bad remote error: ", str, NULL);
            } else {
-               ch = *s++;
-               fp = s - 1;
-               while(ch && ch != ']') ch = *s++;
-               s[-1] = '\0';
-               errstr = newstralloc(errstr, fp);
-               s[-1] = ch;
+               char *enderr;
+
+               tok++;  /* skip over '[' */
+               if ((enderr = strchr(tok, ']')) != NULL)
+                   *enderr = '\0';
+               errstr = newstralloc(errstr, tok);
            }
            break;
        }
-#define sc "sendbackup: info"
-       if(strncmp(str, sc, sizeof(sc)-1) == 0) {
-           s += sizeof(sc)-1;
-           ch = s[-1];
-           skip_whitespace(s, ch);
-           parse_info_line(s - 1);
+
+       if (strcmp(tok, "info") == 0) {
+           tok = strtok(NULL, "");
+           if (tok != NULL)
+               parse_info_line(tok);
            break;
        }
-#undef sc
        /* else we fall through to bad line */
     default:
-       fprintf(errf, "??%s", str);
+bad_line:
+       /* prefix with ?? */
+       fprintf(errf, "??");
        dump_result = max(dump_result, 1);
-       return;
+       break;
     }
     fprintf(errf, "%s\n", str);
+    amfree(buf);
 }
 
-static void add_msg_data(str, len)
-char *str;
-int len;
+static void
+add_msg_data(str, len)
+    const char *str;
+    size_t len;
 {
-    char *t;
-    char *nl;
+    static struct {
+       char *buf;      /* buffer holding msg data */
+       size_t size;    /* size of alloced buffer */
+    } msg = { NULL, 0 };
+    char *line, *nl;
+    size_t buflen;
+
+    if (msg.buf != NULL)
+       buflen = strlen(msg.buf);
+    else
+       buflen = 0;
+
+    /*
+     * If our argument is NULL, then we need to flush out any remaining
+     * bits and return.
+     */
+    if (str == NULL) {
+       if (buflen == 0)
+           return;
+       fprintf(errf,"? %s: error [partial line in msgbuf: %ld bytes]\n",
+           get_pname(), (long)buflen);
+       fprintf(errf,"? %s: error [partial line in msgbuf: \"%s\"]\n",
+           get_pname(), msg.buf);
+       msg.buf[0] = '\0';
+       return;
+    }
 
-    while(len > 0) {
-       if((nl = strchr(str, '\n')) != NULL) {
-           *nl = '\0';
-       }
-       if(msgbuf) {
-           t = stralloc2(msgbuf, str);
-           amfree(msgbuf);
-           msgbuf = t;
-       } else if(nl == NULL) {
-           msgbuf = stralloc(str);
-       } else {
-           msgbuf = str;
-       }
-       if(nl == NULL) break;
-       process_dumpline(msgbuf);
-       if(msgbuf != str) free(msgbuf);
-       msgbuf = NULL;
-       len -= nl + 1 - str;
-       str = nl + 1;
+    /*
+     * Expand the buffer if it can't hold the new contents.
+     */
+    if (buflen + len + 1 > msg.size) {
+       char *newbuf;
+       size_t newsize;
+
+/* round up to next y, where y is a power of 2 */
+#define        ROUND(x, y)     (((x) + (y) - 1) & ~((y) - 1))
+
+       newsize = ROUND(buflen + len + 1, 256);
+       newbuf = alloc(newsize);
+
+       if (msg.buf != NULL) {
+           strcpy(newbuf, msg.buf);
+           amfree(msg.buf);
+       } else
+           newbuf[0] = '\0';
+       msg.buf = newbuf;
+       msg.size = newsize;
+    }
+
+    /*
+     * If there was a partial line from the last call, then
+     * append the new data to the end.
+     */
+    strncat(msg.buf, str, len);
+
+    /*
+     * Process all lines in the buffer
+     */
+    for (line = msg.buf;;) {
+       /*
+        * If there's no newline, then we've only got a partial line.
+        * We go back for more.
+        */
+       if ((nl = strchr(line, '\n')) == NULL)
+           break;
+       *nl = '\0';
+       process_dumpline(line);
+       line = nl + 1;
+    }
+
+    /*
+     * If we did not process all of the data, move it to the front
+     * of the buffer so it is there next time.
+     */
+    if (*line != '\0') {
+       buflen = strlen(line);
+       memmove(msg.buf, line, buflen + 1);
+    } else {
+       msg.buf[0] = '\0';
     }
 }
 
 
-static void log_msgout(typ)
-logtype_t typ;
+static void
+log_msgout(typ)
+    logtype_t typ;
 {
-    char *line = NULL;
+    char *line;
 
     fflush(errf);
     (void) fseek(errf, 0L, SEEK_SET);
-    for(; (line = agets(errf)) != NULL; free(line)) {
+    while ((line = agets(errf)) != NULL) {
        log_add(typ, "%s", line);
+       amfree(line);
     }
+
     afclose(errf);
 }
 
 /* ------------- */
 
-void make_tapeheader(file, type)
-dumpfile_t *file;
-filetype_t type;
+/*
+ * Fill in the rest of the tape header
+ */
+static void
+finish_tapeheader(file)
+    dumpfile_t *file;
 {
-    fh_init(file);
-    file->type = type;
-    strncpy(file->datestamp  , datestamp  , sizeof(file->datestamp)-1);
-    file->datestamp[sizeof(file->datestamp)-1] = '\0';
-    strncpy(file->name       , hostname   , sizeof(file->name)-1);
-    file->name[sizeof(file->name)-1] = '\0';
-    strncpy(file->disk       , diskname   , sizeof(file->disk)-1);
-    file->disk[sizeof(file->disk)-1] = '\0';
+
+    assert(ISSET(status, HEADER_DONE));
+
+    file->type = F_DUMPFILE;
+    strncpy(file->datestamp, datestamp, sizeof(file->datestamp) - 1);
+    strncpy(file->name, hostname, sizeof(file->name) - 1);
+    strncpy(file->disk, diskname, sizeof(file->disk) - 1);
     file->dumplevel = level;
-    strncpy(file->program    , backup_name, sizeof(file->program)-1);
-    file->program[sizeof(file->program)-1] = '\0';
-    strncpy(file->recover_cmd, recover_cmd, sizeof(file->recover_cmd)-1);
-    file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0';
-    file->blocksize = DISK_BLOCK_BYTES;
-
-    if (srvcompress) {
-       file->compressed=1;
-       ap_snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
-                   " %s %s |", UNCOMPRESS_PATH,
-#ifdef UNCOMPRESS_OPT
-                   UNCOMPRESS_OPT
-#else
-                   ""
+
+    /*
+     * If we're doing the compression here, we need to override what
+     * sendbackup told us the compression was.
+     */
+    if (srvcompress != COMP_NONE) {
+       file->compressed = 1;
+#ifndef UNCOMPRESS_OPT
+#define        UNCOMPRESS_OPT  ""
 #endif
-                   );
-       strncpy(file->comp_suffix, COMPRESS_SUFFIX,sizeof(file->comp_suffix)-1);
-       file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
-    }
-    else {
-       file->uncompress_cmd[0] = '\0';
-       file->compressed=compress_suffix!=NULL;
-       if(compress_suffix) {
-           strncpy(file->comp_suffix, compress_suffix,
-                   sizeof(file->comp_suffix)-1);
-           file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
+       if (srvcompress == COMP_SERV_CUST) {
+           snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
+                    " %s %s |", srvcompprog, "-d");
+           strcpy(file->comp_suffix, "cust");
+           strncpy(file->srvcompprog, srvcompprog, sizeof(file->srvcompprog));
+           file->srvcompprog[sizeof(file->srvcompprog)-1] = '\0';
+       } else if ( srvcompress == COMP_CUST ) {
+           snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
+                    " %s %s |", clntcompprog, "-d");
+           strcpy(file->comp_suffix, "cust");
+           strncpy(file->clntcompprog, clntcompprog, sizeof(file->clntcompprog));
+           file->clntcompprog[sizeof(file->clntcompprog)-1] = '\0';
        } else {
-           strncpy(file->comp_suffix, "N", sizeof(file->comp_suffix)-1);
+           snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
+               " %s %s |", UNCOMPRESS_PATH, UNCOMPRESS_OPT);
+           strncpy(file->comp_suffix, COMPRESS_SUFFIX,sizeof(file->comp_suffix)-1);
            file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
        }
+    } else {
+       if (file->comp_suffix[0] == '\0') {
+           file->compressed = 0;
+           assert(sizeof(file->comp_suffix) >= 2);
+           strcpy(file->comp_suffix, "N");
+       } else {
+           file->compressed = 1;
+       }
+    }
+    /* take care of the encryption header here */
+    if (srvencrypt != ENCRYPT_NONE) {
+      file->encrypted= 1;
+      if (srvencrypt == ENCRYPT_SERV_CUST) {
+       snprintf(file->decrypt_cmd, sizeof(file->decrypt_cmd),
+                " %s %s |", srv_encrypt, srv_decrypt_opt); 
+       strcpy(file->encrypt_suffix, "enc");
+       strncpy(file->srv_encrypt, srv_encrypt, sizeof(file->srv_encrypt));
+       file->srv_encrypt[sizeof(file->srv_encrypt)-1] = '\0';
+       strncpy(file->srv_decrypt_opt, srv_decrypt_opt, sizeof(file->srv_decrypt_opt));
+       file->srv_decrypt_opt[sizeof(file->srv_decrypt_opt)-1] = '\0';
+      } else if ( srvencrypt == ENCRYPT_CUST ) {
+       snprintf(file->decrypt_cmd, sizeof(file->decrypt_cmd),
+                " %s %s |", clnt_encrypt, clnt_decrypt_opt);
+       strcpy(file->encrypt_suffix, "enc");
+       strncpy(file->clnt_encrypt, clnt_encrypt, sizeof(file->clnt_encrypt));
+       file->clnt_encrypt[sizeof(file->clnt_encrypt)-1] = '\0';
+       strncpy(file->clnt_decrypt_opt, clnt_decrypt_opt, sizeof(file->clnt_decrypt_opt));
+       file->clnt_decrypt_opt[sizeof(file->clnt_decrypt_opt)-1] = '\0';
+      }
+    } else {
+      if (file->encrypt_suffix[0] == '\0') {
+       file->encrypted = 0;
+       assert(sizeof(file->encrypt_suffix) >= 2);
+       strcpy(file->encrypt_suffix, "N");
+      } else {
+       file->encrypted= 1;
+      }
     }
-    strncpy(file->cont_filename, cont_filename, sizeof(file->cont_filename)-1);
-    file->cont_filename[sizeof(file->cont_filename)-1] = '\0';
 }
 
-/* Send an Amanda dump header to the output file.
- * returns true if an error occured, false on success
+/*
+ * Send an Amanda dump header to the output file.
  */
-
-int write_tapeheader(outfd, file)
-int outfd;
-dumpfile_t *file;
+static int
+write_tapeheader(outfd, file)
+    int outfd;
+    dumpfile_t *file;
 {
     char buffer[DISK_BLOCK_BYTES];
-    int         written;
+    int written;
 
     build_header(buffer, file, sizeof(buffer));
 
-    written = fullwrite(outfd, buffer, sizeof(buffer));
+    written = write(outfd, buffer, sizeof(buffer));
     if(written == sizeof(buffer)) return 0;
     if(written < 0) return written;
     errno = ENOSPC;
     return -1;
 }
 
-
-int do_dump(mesgfd, datafd, indexfd, outfd)
-int mesgfd, datafd, indexfd, outfd;
+static int
+do_dump(db)
+    struct databuf *db;
 {
-    int maxfd, nfound, size1, size2, eof1, eof2;
-    int rc;
-    fd_set readset, selectset;
-    struct timeval timeout;
-    int outpipe[2];
-    int header_done;   /* flag - header has been written */
     char *indexfile_tmp = NULL;
     char *indexfile_real = NULL;
     char level_str[NUM_STR_SIZE];
-    char kb_str[NUM_STR_SIZE];
-    char kps_str[NUM_STR_SIZE];
-    char orig_kb_str[NUM_STR_SIZE];
     char *fn;
     char *q;
     times_t runtime;
     double dumptime;   /* Time dump took in secs */
-    int compresspid = -1, indexpid = -1, killerr;
     char *errfname = NULL;
-
-#ifndef DUMPER_SOCKET_BUFFERING
-#define DUMPER_SOCKET_BUFFERING 0
-#endif
-
-#if !defined(SO_RCVBUF) || !defined(SO_RCVLOWAT)
-#undef  DUMPER_SOCKET_BUFFERING
-#define DUMPER_SOCKET_BUFFERING 0
-#endif
-
-#if DUMPER_SOCKET_BUFFERING
-    int lowat = NETWORK_BLOCK_BYTES;
-    int recbuf = 0;
-    int sizeof_recbuf = sizeof(recbuf);
-    int lowwatset = 0;
-    int lowwatset_count = 0;
-#endif
+    int indexout;
+    pid_t indexpid = -1;
 
     startclock();
 
-    datain = dataout = databuf;
-    datalimit = databuf + sizeof(databuf);
-    dumpsize = dumpbytes = origsize = filesize = dump_result = 0;
-    nb_header_block = 0;
-    got_info_endline = got_sizeline = got_endline = 0;
-    header_done = 0;
-    amfree(backup_name);
-    amfree(recover_cmd);
-    amfree(compress_suffix);
-
-    ap_snprintf(level_str, sizeof(level_str), "%d", level);
+    dumpbytes = dumpsize = headersize = origsize = dump_result = 0;
+    status = 0;
+    fh_init(&file);
+
+    snprintf(level_str, sizeof(level_str), "%d", level);
     fn = sanitise_filename(diskname);
     errfname = newvstralloc(errfname,
                            AMANDA_TMPDIR,
@@ -1179,58 +949,13 @@ int mesgfd, datafd, indexfd, outfd;
                              strerror(errno),
                              NULL);
        amfree(errfname);
-       rc = 2;
        goto failed;
     }
     unlink(errfname);                          /* so it goes away on close */
     amfree(errfname);
 
-    /* insert pipe in the *READ* side, if server-side compression is desired */
-    compresspid = -1;
-    if (srvcompress) {
-       int tmpfd;
-
-       tmpfd = datafd;
-       pipe(outpipe); /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
-       datafd = outpipe[0];
-       if(datafd < 0 || datafd >= FD_SETSIZE) {
-           aclose(outpipe[0]);
-           aclose(outpipe[1]);
-           errstr = newstralloc(errstr, "descriptor out of range");
-           errno = EMFILE;
-           rc = 2;
-           goto failed;
-       }
-       switch(compresspid=fork()) {
-       case -1:
-           errstr = newstralloc2(errstr, "couldn't fork: ", strerror(errno));
-           rc = 2;
-           goto failed;
-       default:
-           aclose(outpipe[1]);
-           aclose(tmpfd);
-           break;
-       case 0:
-           aclose(outpipe[0]);
-           /* child acts on stdin/stdout */
-           if (dup2(outpipe[1],1) == -1)
-               fprintf(stderr, "err dup2 out: %s\n", strerror(errno));
-           if (dup2(tmpfd, 0) == -1)
-               fprintf(stderr, "err dup2 in: %s\n", strerror(errno));
-           safe_fd(-1, 0);
-           /* now spawn gzip -1 to take care of the rest */
-           execlp(COMPRESS_PATH, COMPRESS_PATH,
-                  (srvcompress == srvcomp_best ? COMPRESS_BEST_OPT
-                                               : COMPRESS_FAST_OPT),
-                  (char *)0);
-           error("error: couldn't exec %s.\n", COMPRESS_PATH);
-       }
-       /* Now the pipe has been inserted. */
-    }
-
-    indexpid = -1;
-    if (indexfd != -1) {
-       indexfile_real = getindexfname(hostname, diskname, datestamp, level),
+    if (streams[INDEXFD].fd != NULL) {
+       indexfile_real = getindexfname(hostname, diskname, datestamp, level);
        indexfile_tmp = stralloc2(indexfile_real, ".tmp");
 
        if (mkpdir(indexfile_tmp, 02755, (uid_t)-1, (gid_t)-1) == -1) {
@@ -1242,240 +967,57 @@ int mesgfd, datafd, indexfd, outfd;
                                 NULL);
           amfree(indexfile_real);
           amfree(indexfile_tmp);
-          rc = 2;
           goto failed;
        }
-
-       switch(indexpid=fork()) {
-       case -1:
-           errstr = newstralloc2(errstr, "couldn't fork: ", strerror(errno));
-           rc = 2;
-           goto failed;
-       default:
-           aclose(indexfd);
-           indexfd = -1;                       /* redundant */
-           break;
-       case 0:
-           if (dup2(indexfd, 0) == -1) {
-               error("err dup2 in: %s", strerror(errno));
-           }
-           indexfd = open(indexfile_tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-           if (indexfd == -1)
-               error("err open %s: %s", indexfile_tmp, strerror(errno));
-           if (dup2(indexfd,1) == -1)
-               error("err dup2 out: %s", strerror(errno));
-           safe_fd(-1, 0);
-           execlp(COMPRESS_PATH, COMPRESS_PATH, COMPRESS_BEST_OPT, (char *)0);
-           error("error: couldn't exec %s.", COMPRESS_PATH);
-       }
-    }
-
-    NAUGHTY_BITS_INITIALIZE;
-
-    maxfd = max(mesgfd, datafd) + 1;
-    eof1 = eof2 = 0;
-
-    FD_ZERO(&readset);
-
-    /* Just process messages for now.  Once we have done the header
-    ** we will start processing data too.
-    */
-    FD_SET(mesgfd, &readset);
-
-    if(datafd == -1) eof1 = 1; /* fake eof on data */
-
-#if DUMPER_SOCKET_BUFFERING
-
-#ifndef EST_PACKET_SIZE
-#define EST_PACKET_SIZE        512
-#endif
-#ifndef        EST_MIN_WINDOW
-#define        EST_MIN_WINDOW  EST_PACKET_SIZE*4 /* leave room for 2k in transit */
-#endif
-
-    else {
-       recbuf = STREAM_BUFSIZE;
-       if (setsockopt(datafd, SOL_SOCKET, SO_RCVBUF,
-                      (void *) &recbuf, sizeof_recbuf)) {
-           const int errornumber = errno;
-           fprintf(stderr, "%s: pid %ld setsockopt(SO_RCVBUF): %s\n",
-                   get_pname(), (long) getpid(), strerror(errornumber));
-       }
-       if (getsockopt(datafd, SOL_SOCKET, SO_RCVBUF,
-                      (void *) &recbuf, (void *)&sizeof_recbuf)) {
-           const int errornumber = errno;
-           fprintf(stderr, "%s: pid %ld getsockopt(SO_RCVBUF): %s\n",
-                   get_pname(), (long) getpid(), strerror(errornumber));
-           recbuf = 0;
-       }
-
-       /* leave at least EST_MIN_WINDOW between lowwat and recbuf */
-       if (recbuf-lowat < EST_MIN_WINDOW)
-           lowat = recbuf-EST_MIN_WINDOW;
-
-       /* if lowwat < ~512, don't bother */
-       if (lowat < EST_PACKET_SIZE)
-           recbuf = 0;
-       fprintf(stderr, "%s: pid %ld receive size is %d, low water is %d\n",
-               get_pname(), (long) getpid(), recbuf, lowat);
-    }
-#endif
-
-    while(!(eof1 && eof2)) {
-
-#if DUMPER_SOCKET_BUFFERING
-       /* Set socket buffering */
-       if (recbuf>0 && !lowwatset) {
-           if (setsockopt(datafd, SOL_SOCKET, SO_RCVLOWAT,
-                          (void *) &lowat, sizeof(lowat))) {
-               const int errornumber = errno;
-               fprintf(stderr,
-                       "%s: pid %ld setsockopt(SO_RCVLOWAT): %s\n",
-                       get_pname(), (long) getpid(), strerror(errornumber));
-           }
-           lowwatset = 1;
-           lowwatset_count++;
-       }
-#endif
-
-       timeout.tv_sec = conf_dtimeout;
-       timeout.tv_usec = 0;
-       memcpy(&selectset, &readset, sizeof(fd_set));
-
-       nfound = select(maxfd, (SELECT_ARG_TYPE *)(&selectset), NULL, NULL, &timeout);
-
-       /* check for errors or timeout */
-
-#if DUMPER_SOCKET_BUFFERING
-       if (nfound==0 && lowwatset) {
-           const int zero = 0;
-           /* Disable socket buffering and ... */
-           if (setsockopt(datafd, SOL_SOCKET, SO_RCVLOWAT,
-                          (void *) &zero, sizeof(zero))) {
-               const int errornumber = errno;
-               fprintf(stderr,
-                       "%s: pid %ld setsockopt(SO_RCVLOWAT): %s\n",
-                       get_pname(), (long) getpid(), strerror(errornumber));
-           }
-           lowwatset = 0;
-
-           /* ... try once more */
-           timeout.tv_sec = conf_dtimeout;
-           timeout.tv_usec = 0;
-           memcpy(&selectset, &readset, sizeof(fd_set));
-           nfound = select(maxfd, (SELECT_ARG_TYPE *)(&selectset), NULL, NULL, &timeout);
-       }
-#endif
-
-       if(nfound == 0)  {
-           errstr = newstralloc(errstr, "data timeout");
-           rc = 2;
-           goto failed;
-       }
-       if(nfound == -1) {
-           errstr = newstralloc2(errstr, "select: ", strerror(errno));
-           rc = 2;
+       indexout = open(indexfile_tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+       if (indexout == -1) {
+           errstr = newvstralloc(errstr, "err open ", indexfile_tmp, ": ",
+               strerror(errno), NULL);
            goto failed;
-       }
-
-       /* read/write any data */
-
-       if(datafd >= 0 && FD_ISSET(datafd, &selectset)) {
-           size1 = read(datafd, datain, datalimit - datain);
-           if(size1 < 0) {
-               errstr = newstralloc2(errstr, "data read: ", strerror(errno));
-               rc = 2;
-               goto failed;
-           }
-           if(update_dataptr(&outfd, size1)) {
-               rc = 2;
+       } else {
+           if (runcompress(indexout, &indexpid, COMP_BEST) < 0) {
+               aclose(indexout);
                goto failed;
            }
-           if(size1 == 0) {
-               eof1 = 1;
-               FD_CLR(datafd, &readset);
-               aclose(datafd);
-           }
        }
+       indexfderror = 0;
+       /*
+        * Schedule the indexfd for relaying to the index file
+        */
+       security_stream_read(streams[INDEXFD].fd, read_indexfd, &indexout);
+    }
 
-       if(mesgfd >= 0 && FD_ISSET(mesgfd, &selectset)) {
-           size2 = read(mesgfd, mesgbuf, sizeof(mesgbuf)-1);
-           switch(size2) {
-           case -1:
-               errstr = newstralloc2(errstr, "mesg read: ", strerror(errno));
-               rc = 2;
-               goto failed;
-           case 0:
-               eof2 = 1;
-               process_dumpeof();
-               FD_CLR(mesgfd, &readset);
-               aclose(mesgfd);
-               break;
-           default:
-               mesgbuf[size2] = '\0';
-               add_msg_data(mesgbuf, size2);
-           }
+    /*
+     * We only need to process messages initially.  Once we have done
+     * the header, we will start processing data too.
+     */
+    security_stream_read(streams[MESGFD].fd, read_mesgfd, db);
 
-           if (got_info_endline && !header_done) { /* time to do the header */
-               make_tapeheader(&file, F_DUMPFILE);
-               if (write_tapeheader(outfd, &file)) {
-                   int save_errno = errno;
-                   errstr = newstralloc2(errstr, "write_tapeheader: ", 
-                                         strerror(errno));
-                   if(save_errno == ENOSPC) {
-                       putresult(NO_ROOM, "%s %lu\n", handle, 
-                                 use+split_size-dumpsize);
-                       use = 0; /* force RQ_MORE_DISK */
-                       split_size = dumpsize;
-                       rc = 1;
-                   }
-                   else {
-                       rc = 2;
-                   }
-                   goto failed;
-               }
-               dumpsize += DISK_BLOCK_KB;
-               filesize += DISK_BLOCK_KB;
-               nb_header_block++;
-               header_done = 1;
-               strncat(cont_filename,filename,sizeof(cont_filename));
-               cont_filename[sizeof(cont_filename)-1] = '\0';
-
-               if (datafd != -1)
-                   FD_SET(datafd, &readset);   /* now we can read the data */
-           }
-       }
-    } /* end while */
+    /*
+     * Setup a read timeout
+     */
+    timeout(conf_dtimeout);
 
-#if DUMPER_SOCKET_BUFFERING
-    if(lowwatset_count > 1) {
-       fprintf(stderr, "%s: pid %ld low water set %d times\n",
-               get_pname(), (long) getpid(), lowwatset_count);
-    }
-#endif
+    /*
+     * Start the event loop.  This will exit when all three events
+     * (read the mesgfd, read the datafd, and timeout) are removed.
+     */
+    event_loop(0);
 
-    if(dump_result > 1) {
-       rc = 2;
+    if (dump_result > 1)
        goto failed;
-    }
 
     runtime = stopclock();
     dumptime = runtime.r.tv_sec + runtime.r.tv_usec/1000000.0;
 
-    dumpsize -= (nb_header_block * DISK_BLOCK_KB);/* don't count the header */
+    dumpsize -= headersize;            /* don't count the header */
     if (dumpsize < 0) dumpsize = 0;    /* XXX - maybe this should be fatal? */
 
-    ap_snprintf(kb_str, sizeof(kb_str), "%ld", dumpsize);
-    ap_snprintf(kps_str, sizeof(kps_str),
-               "%3.1f",
-               dumptime ? dumpsize / dumptime : 0.0);
-    ap_snprintf(orig_kb_str, sizeof(orig_kb_str), "%ld", origsize);
-    errstr = newvstralloc(errstr,
-                         "sec ", walltime_str(runtime),
-                         " ", "kb ", kb_str,
-                         " ", "kps ", kps_str,
-                         " ", "orig-kb ", orig_kb_str,
-                         NULL);
+    amfree(errstr);
+    errstr = alloc(128);
+    snprintf(errstr, 128, "sec %s kb %ld kps %3.1f orig-kb %ld",
+       walltime_str(runtime), dumpsize,
+       dumptime ? dumpsize / dumptime : 0.0, origsize);
     q = squotef("[%s]", errstr);
     putresult(DONE, "%s %ld %ld %ld %s\n", handle, origsize, dumpsize,
              (long)(dumptime+0.5), q);
@@ -1496,11 +1038,15 @@ int mesgfd, datafd, indexfd, outfd;
        break;
     }
 
-    if(errf) afclose(errf);
+    if (errf) afclose(errf);
 
+    aclose(db->fd);
     if (indexfile_tmp) {
-       waitpid(indexpid,NULL,0);
-       if(rename(indexfile_tmp, indexfile_real) != 0) {
+       amwait_t index_status;
+
+       aclose(indexout);
+       waitpid(indexpid,&index_status,0);
+       if (rename(indexfile_tmp, indexfile_real) != 0) {
            log_add(L_WARNING, "could not rename \"%s\" to \"%s\": %s",
                    indexfile_tmp, indexfile_real, strerror(errno));
        }
@@ -1508,62 +1054,69 @@ int mesgfd, datafd, indexfd, outfd;
        amfree(indexfile_real);
     }
 
-    return 0;
+    if(db->compresspid != -1) {
+       waitpid(db->compresspid,NULL,0);
+    }
+    if(db->encryptpid != -1) {
+       waitpid(db->encryptpid,NULL,0);
+    }
 
- failed:
+    amfree(errstr);
 
-#if DUMPER_SOCKET_BUFFERING
-    if(lowwatset_count > 1) {
-       fprintf(stderr, "%s: pid %ld low water set %d times\n",
-               get_pname(), (long) getpid(), lowwatset_count);
-    }
-#endif
+    return 1;
 
-    if(!abort_pending) {
-       q = squotef("[%s]", errstr);
-       if(rc==2)
-           putresult(FAILED, "%s %s\n", handle, q);
-       else
-           putresult(TRYAGAIN, "%s %s\n", handle, q);
-       amfree(q);
-    }
+failed:
+    q = squotef("[%s]", errstr);
+    putresult(FAILED, "%s %s\n", handle, q);
+    amfree(q);
 
+    aclose(db->fd);
     /* kill all child process */
-    if(compresspid != -1) {
-       killerr = kill(compresspid,SIGTERM);
-       if(killerr == 0) {
-           fprintf(stderr,"%s: kill compress command\n",get_pname());
-       }
-       else if ( killerr == -1 ) {
-           if(errno != ESRCH)
+    if (db->compresspid != -1) {
+       fprintf(stderr,"%s: kill compress command\n",get_pname());
+       if (kill(db->compresspid, SIGTERM) < 0) {
+           if (errno != ESRCH)
                fprintf(stderr,"%s: can't kill compress command: %s\n", 
-                              get_pname(), strerror(errno));
+                   get_pname(), strerror(errno));
+       }
+       else {
+           waitpid(db->compresspid,NULL,0);
        }
     }
 
-    if(indexpid != -1) {
-       killerr = kill(indexpid,SIGTERM);
-       if(killerr == 0) {
-           fprintf(stderr,"%s: kill index command\n",get_pname());
+    if (db->encryptpid != -1) {
+       fprintf(stderr,"%s: kill encrypt command\n",get_pname());
+       if (kill(db->encryptpid, SIGTERM) < 0) {
+           if (errno != ESRCH)
+               fprintf(stderr,"%s: can't kill encrypt command: %s\n", 
+                   get_pname(), strerror(errno));
        }
-       else if ( killerr == -1 ) {
-           if(errno != ESRCH)
-               fprintf(stderr,"%s: can't kill index command: %s\n", 
-                              get_pname(),strerror(errno));
+       else {
+           waitpid(db->encryptpid,NULL,0);
        }
     }
 
-    if(!abort_pending) {
-       log_start_multiline();
-       log_add(L_FAIL, "%s %s %s %d [%s]", hostname, diskname, 
-               datestamp, level, errstr);
-       if (errf) {
-           log_msgout(L_FAIL);
+    if (indexpid != -1) {
+       fprintf(stderr,"%s: kill index command\n",get_pname());
+       if (kill(indexpid, SIGTERM) < 0) {
+           if (errno != ESRCH)
+               fprintf(stderr,"%s: can't kill index command: %s\n", 
+                   get_pname(),strerror(errno));
+       }
+       else {
+           waitpid(indexpid,NULL,0);
        }
-       log_end_multiline();
     }
 
-    if(errf) afclose(errf);
+    log_start_multiline();
+    log_add(L_FAIL, "%s %s %s %d [%s]", hostname, diskname, datestamp,
+           level, errstr);
+    if (errf) {
+       log_msgout(L_FAIL);
+    }
+    log_end_multiline();
+
+    if (errf) afclose(errf);
 
     if (indexfile_tmp) {
        unlink(indexfile_tmp);
@@ -1571,224 +1124,623 @@ int mesgfd, datafd, indexfd, outfd;
        amfree(indexfile_real);
     }
 
-    return rc;
+    return 0;
 }
 
-/* -------------------- */
+/*
+ * Callback for reads on the mesgfd stream
+ */
+static void
+read_mesgfd(cookie, buf, size)
+    void *cookie, *buf;
+    ssize_t size;
+{
+    struct databuf *db = cookie;
 
-char *hostname, *disk;
-int response_error;
+    assert(db != NULL);
 
-void sendbackup_response(p, pkt)
-proto_t *p;
-pkt_t *pkt;
-{
-    int data_port = -1;
-    int mesg_port = -1;
-    int index_port = -1;
-    char *line;
-    char *fp;
-    char *s;
-    char *t;
-    int ch;
-    int tch;
-
-    am_release_feature_set(their_features);
-    their_features = NULL;
-
-    if(p->state == S_FAILED) {
-       if(pkt == NULL) {
-           if(p->prevstate == S_REPWAIT) {
-               errstr = newstralloc(errstr, "[reply timeout]");
+    switch (size) {
+    case -1:
+       errstr = newstralloc2(errstr, "mesg read: ",
+           security_stream_geterror(streams[MESGFD].fd));
+       dump_result = 2;
+       stop_dump();
+       return;
+    case 0:
+       /*
+        * EOF.  Just shut down the mesg stream.
+        */
+       process_dumpeof();
+       security_stream_close(streams[MESGFD].fd);
+       streams[MESGFD].fd = NULL;
+       /*
+        * If the data fd and index fd has also shut down, then we're done.
+        */
+       if (streams[DATAFD].fd == NULL && streams[INDEXFD].fd == NULL)
+           stop_dump();
+       return;
+    default:
+       assert(buf != NULL);
+       add_msg_data(buf, size);
+       security_stream_read(streams[MESGFD].fd, read_mesgfd, cookie);
+       break;
+    }
+
+    /*
+     * Reset the timeout for future reads
+     */
+    timeout(conf_dtimeout);
+
+    if (ISSET(status, GOT_INFO_ENDLINE) && !ISSET(status, HEADER_DONE)) {
+       SET(status, HEADER_DONE);
+       /* time to do the header */
+       finish_tapeheader(&file);
+       if (write_tapeheader(db->fd, &file)) {
+           errstr = newstralloc2(errstr, "write_tapeheader: ", 
+                                 strerror(errno));
+           dump_result = 2;
+           stop_dump();
+           return;
+       }
+       dumpsize += DISK_BLOCK_KB;
+       headersize += DISK_BLOCK_KB;
+
+       if (srvencrypt == ENCRYPT_SERV_CUST) {
+           if (runencrypt(db->fd, &db->encryptpid, srvencrypt) < 0) {
+               dump_result = 2;
+               stop_dump();
+               return;
            }
-           else {
-               errstr = newstralloc(errstr, "[request timeout]");
+       }
+       /*
+        * Now, setup the compress for the data output, and start
+        * reading the datafd.
+        */
+       if ((srvcompress != COMP_NONE) && (srvcompress != COMP_CUST)) {
+           if (runcompress(db->fd, &db->compresspid, srvcompress) < 0) {
+               dump_result = 2;
+               stop_dump();
+               return;
            }
-           response_error = 1;
-           return;
        }
+       security_stream_read(streams[DATAFD].fd, read_datafd, db);
     }
+}
 
-#if 0
-    fprintf(stderr, "got %sresponse:\n----\n%s----\n\n",
-           (p->state == S_FAILED) ? "NAK " : "", pkt->body);
-#endif
+/*
+ * Callback for reads on the datafd stream
+ */
+static void
+read_datafd(cookie, buf, size)
+    void *cookie, *buf;
+    ssize_t size;
+{
+    struct databuf *db = cookie;
+
+    assert(db != NULL);
+
+    /*
+     * The read failed.  Error out
+     */
+    if (size < 0) {
+       errstr = newstralloc2(errstr, "data read: ",
+           security_stream_geterror(streams[DATAFD].fd));
+       dump_result = 2;
+       stop_dump();
+       return;
+    }
 
-#ifdef KRB4_SECURITY
-    if(krb4_auth && !check_mutual_authenticator(&cred.session, pkt, p)) {
-       errstr = newstralloc(errstr, "mutual-authentication failed");
-       response_error = 2;
+    /*
+     * Reset the timeout for future reads
+     */
+    timeout(conf_dtimeout);
+
+    /* The header had better be written at this point */
+    assert(ISSET(status, HEADER_DONE));
+
+    /*
+     * EOF.  Stop and return.
+     */
+    if (size == 0) {
+       databuf_flush(db);
+       if (dumpbytes) {
+           dumpsize++;
+       }
+       security_stream_close(streams[DATAFD].fd);
+       streams[DATAFD].fd = NULL;
+       /*
+        * If the mesg fd and index fd has also shut down, then we're done.
+        */
+       if (streams[MESGFD].fd == NULL && streams[INDEXFD].fd == NULL)
+           stop_dump();
        return;
     }
-#endif
 
-    s = pkt->body;
-    ch = *s++;
-    while(ch) {
-       line = s - 1;
-       skip_line(s, ch);
-       if (s[-2] == '\n') {
-           s[-2] = '\0';
+    /*
+     * We read something.  Add it to the databuf and reschedule for
+     * more data.
+     */
+    assert(buf != NULL);
+    if (databuf_write(db, buf, size) < 0) {
+       errstr = newstralloc2(errstr, "data write: ", strerror(errno));
+       dump_result = 2;
+       stop_dump();
+       return;
+    }
+    security_stream_read(streams[DATAFD].fd, read_datafd, cookie);
+}
+
+/*
+ * Callback for reads on the index stream
+ */
+static void
+read_indexfd(cookie, buf, size)
+    void *cookie, *buf;
+    ssize_t size;
+{
+    int fd;
+
+    assert(cookie != NULL);
+    fd = *(int *)cookie;
+
+    if (size < 0) {
+       errstr = newstralloc2(errstr, "index read: ",
+           security_stream_geterror(streams[INDEXFD].fd));
+       dump_result = 2;
+       stop_dump();
+       return;
+    }
+
+    /*
+     * EOF.  Stop and return.
+     */
+    if (size == 0) {
+       security_stream_close(streams[INDEXFD].fd);
+       streams[INDEXFD].fd = NULL;
+       /*
+        * If the mesg fd has also shut down, then we're done.
+        */
+       if (streams[DATAFD].fd == NULL && streams[MESGFD].fd == NULL)
+           stop_dump();
+       return;
+    }
+
+    assert(buf != NULL);
+
+    /*
+     * We ignore error while writing to the index file.
+     */
+    if (fullwrite(fd, buf, size) < 0) {
+       /* Ignore error, but schedule another read. */
+       if(indexfderror == 0) {
+           indexfderror = 1;
+           log_add(L_INFO, "Index corrupted for %s:%s", hostname, diskname);
        }
+    }
+    security_stream_read(streams[INDEXFD].fd, read_indexfd, cookie);
+}
 
-#define sc "OPTIONS "
-       if(strncmp(line, sc, sizeof(sc)-1) == 0) {
-#undef sc
+/*
+ * Startup a timeout in the event handler.  If the arg is 0,
+ * then remove the timeout.
+ */
+static void
+timeout(seconds)
+    int seconds;
+{
+    static event_handle_t *ev_timeout = NULL;
+
+    /*
+     * First, remove a timeout if one is active.
+     */
+    if (ev_timeout != NULL) {
+       event_release(ev_timeout);
+       ev_timeout = NULL;
+    }
 
-#define sc "features="
-           t = strstr(line, sc);
-           if(t != NULL && (isspace((int)t[-1]) || t[-1] == ';')) {
-               t += sizeof(sc)-1;
-#undef sc
-               am_release_feature_set(their_features);
-               if((their_features = am_string_to_feature(t)) == NULL) {
-                   errstr = newvstralloc(errstr,
-                                         "bad features value: ",
-                                         line,
-                                         NULL);
-               }
-           }
+    /*
+     * Now, schedule a new one if 'seconds' is greater than 0
+     */
+    if (seconds > 0)
+       ev_timeout = event_register(seconds, EV_TIME, timeout_callback, NULL);
+}
 
-           continue;
+/*
+ * This is the callback for timeout().  If this is reached, then we
+ * have a data timeout.
+ */
+static void
+timeout_callback(unused)
+    void *unused;
+{
+    assert(unused == NULL);
+    errstr = newstralloc(errstr, "data timeout");
+    dump_result = 2;
+    stop_dump();
+}
+
+/*
+ * This is called when everything needs to shut down so event_loop()
+ * will exit.
+ */
+static void
+stop_dump()
+{
+    int i;
+
+    for (i = 0; i < NSTREAMS; i++) {
+       if (streams[i].fd != NULL) {
+           security_stream_close(streams[i].fd);
+           streams[i].fd = NULL;
        }
+    }
+    timeout(0);
+}
 
-#define sc "ERROR "
-       if(strncmp(line, sc, sizeof(sc)-1) == 0) {
-           t = line + sizeof(sc)-1;
-           tch = t[-1];
-#undef sc
 
-           fp = t - 1;
-           skip_whitespace(t, tch);
-           errstr = newvstralloc(errstr,
-                                 (p->state == S_FAILED) ? "nak error: " : "",
-                                 fp,
-                                 NULL);
-           response_error = ((p->state == S_FAILED) ? 1 : 2);
-           return;
+/*
+ * Runs compress with the first arg as its stdout.  Returns
+ * 0 on success or negative if error, and it's pid via the second
+ * argument.  The outfd arg is dup2'd to the pipe to the compress
+ * process.
+ */
+static int
+runcompress(outfd, pid, comptype)
+    int outfd;
+    pid_t *pid;
+    comp_t comptype;
+{
+    int outpipe[2], rval;
+
+    assert(outfd >= 0);
+    assert(pid != NULL);
+
+    /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
+    if (pipe(outpipe) < 0) {
+       errstr = newstralloc2(errstr, "pipe: ", strerror(errno));
+       return (-1);
+    }
+
+    switch (*pid = fork()) {
+    case -1:
+       errstr = newstralloc2(errstr, "couldn't fork: ", strerror(errno));
+       aclose(outpipe[0]);
+       aclose(outpipe[1]);
+       return (-1);
+    default:
+       rval = dup2(outpipe[1], outfd);
+       if (rval < 0)
+           errstr = newstralloc2(errstr, "couldn't dup2: ", strerror(errno));
+       aclose(outpipe[1]);
+       aclose(outpipe[0]);
+       return (rval);
+    case 0:
+       if (dup2(outpipe[0], 0) < 0)
+           error("err dup2 in: %s", strerror(errno));
+       if (dup2(outfd, 1) == -1)
+           error("err dup2 out: %s", strerror(errno));
+       safe_fd(-1, 0);
+       if (comptype != COMP_SERV_CUST) {
+           execlp(COMPRESS_PATH, COMPRESS_PATH, (  comptype == COMP_BEST ?
+               COMPRESS_BEST_OPT : COMPRESS_FAST_OPT), NULL);
+           error("error: couldn't exec %s: %s", COMPRESS_PATH, strerror(errno));
+       } else if (*srvcompprog) {
+           execlp(srvcompprog, srvcompprog, (char *)0);
+           error("error: couldn't exec server custom filter%s.\n", srvcompprog);
        }
+    }
+    /* NOTREACHED */
+    return (-1);
+}
 
-#define sc "CONNECT "
-       if(strncmp(line, sc, sizeof(sc)-1) == 0) {
-#undef sc
+/*
+ * Runs encrypt with the first arg as its stdout.  Returns
+ * 0 on success or negative if error, and it's pid via the second
+ * argument.  The outfd arg is dup2'd to the pipe to the encrypt
+ * process.
+ */
+static int
+runencrypt(outfd, pid, encrypttype)
+    int outfd;
+    pid_t *pid;
+    encrypt_t encrypttype;
+{
+    int outpipe[2], rval;
 
-#define sc "DATA "
-           t = strstr(line, sc);
-           if(t != NULL && isspace((int)t[-1])) {
-               t += sizeof(sc)-1;
-#undef sc
-               data_port = atoi(t);
-           }
+    assert(outfd >= 0);
+    assert(pid != NULL);
 
-#define sc "MESG "
-           t = strstr(line, sc);
-           if(t != NULL && isspace((int)t[-1])) {
-               t += sizeof(sc)-1;
-#undef sc
-               mesg_port = atoi(t);
-           }
+    /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
+    if (pipe(outpipe) < 0) {
+       errstr = newstralloc2(errstr, "pipe: ", strerror(errno));
+       return (-1);
+    }
 
-#define sc "INDEX "
-           t = strstr(line, sc);
-           if(t != NULL && isspace((int)t[-1])) {
-               t += sizeof(sc)-1;
-#undef sc
-               index_port = atoi(t);
-           }
-           continue;
+    switch (*pid = fork()) {
+    case -1:
+       errstr = newstralloc2(errstr, "couldn't fork: ", strerror(errno));
+       aclose(outpipe[0]);
+       aclose(outpipe[1]);
+       return (-1);
+    default:
+       rval = dup2(outpipe[1], outfd);
+       if (rval < 0)
+           errstr = newstralloc2(errstr, "couldn't dup2: ", strerror(errno));
+       aclose(outpipe[1]);
+       aclose(outpipe[0]);
+       return (rval);
+    case 0:
+       if (dup2(outpipe[0], 0) < 0)
+           error("err dup2 in: %s", strerror(errno));
+       if (dup2(outfd, 1) < 0 )
+           error("err dup2 out: %s", strerror(errno));
+       safe_fd(-1, 0);
+       if ((encrypttype == ENCRYPT_SERV_CUST) && *srv_encrypt) {
+           execlp(srv_encrypt, srv_encrypt, (char *)0);
+           error("error: couldn't exec server encryption%s.\n", srv_encrypt);
        }
+    }
+    /* NOTREACHED */
+    return (-1);
+}
 
-       errstr = newvstralloc(errstr,
-                             "unknown response: ",
-                             line,
-                             NULL);
-       response_error = 2;
+
+/* -------------------- */
+
+static void
+sendbackup_response(datap, pkt, sech)
+    void *datap;
+    pkt_t *pkt;
+    security_handle_t *sech;
+{
+    int ports[NSTREAMS], *response_error = datap, i;
+    char *p;
+    char *tok;
+    char *tok_end;
+    char *extra = NULL;
+
+    assert(response_error != NULL);
+    assert(sech != NULL);
+
+    if (pkt == NULL) {
+       errstr = newvstralloc(errstr, "[request failed: ",
+           security_geterror(sech), "]", NULL);
+       *response_error = 1;
        return;
     }
 
-    if (data_port == -1 || mesg_port == -1) {
-       errstr = newvstralloc(errstr, "bad CONNECT response", NULL);
-       response_error = 2;
+    if (pkt->type == P_NAK) {
+#if defined(PACKET_DEBUG)
+       fprintf(stderr, "got nak response:\n----\n%s\n----\n\n", pkt->body);
+#endif
+
+       tok = strtok(pkt->body, " ");
+       if (tok == NULL || strcmp(tok, "ERROR") != 0)
+           goto bad_nak;
+
+       tok = strtok(NULL, "\n");
+       if (tok != NULL) {
+           errstr = newvstralloc(errstr, "NAK: ", tok, NULL);
+           *response_error = 1;
+       } else {
+bad_nak:
+           errstr = newstralloc(errstr, "request NAK");
+           *response_error = 2;
+       }
        return;
     }
 
-    datafd = stream_client(hostname, data_port, -1, -1, NULL);
-    if(datafd == -1) {
-       errstr = newvstralloc(errstr,
-                             "could not connect to data port: ",
-                             strerror(errno),
-                             NULL);
-       response_error = 1;
+    if (pkt->type != P_REP) {
+       errstr = newvstralloc(errstr, "received strange packet type ",
+           pkt_type2str(pkt->type), ": ", pkt->body, NULL);
+       *response_error = 1;
        return;
     }
-    mesgfd = stream_client(hostname, mesg_port, -1, -1, NULL);
-    if(mesgfd == -1) {
-       errstr = newvstralloc(errstr,
-                             "could not connect to mesg port: ",
-                             strerror(errno),
-                             NULL);
-       aclose(datafd);
-       datafd = -1;                            /* redundant */
-       response_error = 1;
-       return;
+
+#if defined(PACKET_DEBUG)
+    fprintf(stderr, "got response:\n----\n%s\n----\n\n", pkt->body);
+#endif
+
+    for(i = 0; i < NSTREAMS; i++) {
+       ports[i] = -1;
+       streams[i].fd = NULL;
     }
 
-    if (index_port != -1) {
-       indexfd = stream_client(hostname, index_port, -1, -1, NULL);
-       if (indexfd == -1) {
-           errstr = newvstralloc(errstr,
-                                 "could not connect to index port: ",
-                                 strerror(errno),
-                                 NULL);
-           aclose(datafd);
-           aclose(mesgfd);
-           datafd = mesgfd = -1;               /* redundant */
-           response_error = 1;
+    p = pkt->body;
+    while((tok = strtok(p, " \n")) != NULL) {
+       p = NULL;
+
+       /*
+        * Error response packets have "ERROR" followed by the error message
+        * followed by a newline.
+        */
+       if (strcmp(tok, "ERROR") == 0) {
+           tok = strtok(NULL, "\n");
+           if (tok == NULL)
+               tok = "[bogus error packet]";
+           errstr = newstralloc(errstr, tok);
+           *response_error = 2;
            return;
        }
+
+       /*
+        * Regular packets have CONNECT followed by three streams
+        */
+       if (strcmp(tok, "CONNECT") == 0) {
+
+           /*
+            * Parse the three stream specifiers out of the packet.
+            */
+           for (i = 0; i < NSTREAMS; i++) {
+               tok = strtok(NULL, " ");
+               if (tok == NULL || strcmp(tok, streams[i].name) != 0) {
+                   extra = vstralloc("CONNECT token is \"",
+                                     tok ? tok : "(null)",
+                                     "\": expected \"",
+                                     streams[i].name,
+                                     "\"",
+                                     NULL);
+                   goto parse_error;
+               }
+               tok = strtok(NULL, " \n");
+               if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) {
+                   extra = vstralloc("CONNECT ",
+                                     streams[i].name,
+                                     " token is \"",
+                                     tok ? tok : "(null)",
+                                     "\": expected a port number",
+                                     NULL);
+                   goto parse_error;
+               }
+           }
+           continue;
+       }
+
+       /*
+        * OPTIONS [options string] '\n'
+        */
+       if (strcmp(tok, "OPTIONS") == 0) {
+           tok = strtok(NULL, "\n");
+           if (tok == NULL) {
+               extra = stralloc("OPTIONS token is missing");
+               goto parse_error;
+           }
+           tok_end = tok + strlen(tok);
+
+           while((p = strchr(tok, ';')) != NULL) {
+               *p++ = '\0';
+#define sc "features="
+               if(strncmp(tok, sc, sizeof(sc)-1) == 0) {
+                   tok += sizeof(sc) - 1;
+#undef sc
+                   am_release_feature_set(their_features);
+                   if((their_features = am_string_to_feature(tok)) == NULL) {
+                       errstr = newvstralloc(errstr,
+                                             "OPTIONS: bad features value: ",
+                                             tok,
+                                             NULL);
+                       goto parse_error;
+                   }
+               }
+               tok = p;
+           }
+           continue;
+       }
+
+       extra = vstralloc("next token is \"",
+                         tok ? tok : "(null)",
+                         "\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\"",
+                         NULL);
+       goto parse_error;
     }
 
-    /* everything worked */
+    /*
+     * Connect the streams to their remote ports
+     */
+    for (i = 0; i < NSTREAMS; i++) {
+       if (ports[i] == -1)
+           continue;
+       streams[i].fd = security_stream_client(sech, ports[i]);
+       if (streams[i].fd == NULL) {
+           errstr = newvstralloc(errstr,
+               "[could not connect ", streams[i].name, " stream: ",
+               security_geterror(sech), "]", NULL);
+           goto connect_error;
+       }
+    }
 
+    /*
+     * Authenticate the streams
+     */
+    for (i = 0; i < NSTREAMS; i++) {
+       if (streams[i].fd == NULL)
+           continue;
 #ifdef KRB4_SECURITY
-    if(krb4_auth && kerberos_handshake(datafd, cred.session) == 0) {
-       errstr = newstralloc(errstr,
-                            "mutual authentication in data stream failed");
-       aclose(datafd);
-       aclose(mesgfd);
-       if (indexfd != -1)
-           aclose(indexfd);
-       response_error = 1;
-       return;
+       /*
+        * XXX krb4 historically never authenticated the index stream!
+        * We need to reproduce this lossage here to preserve compatibility
+        * with old clients.
+        * It is wrong to delve into sech, but we have no choice here.
+        */
+       if (strcasecmp(sech->driver->name, "krb4") != 0 && i == INDEXFD)
+           continue;
+#endif
+       if (security_stream_auth(streams[i].fd) < 0) {
+           errstr = newvstralloc(errstr,
+               "[could not authenticate ", streams[i].name, " stream: ",
+               security_stream_geterror(streams[i].fd), "]", NULL);
+           goto connect_error;
+       }
     }
-    if(krb4_auth && kerberos_handshake(mesgfd, cred.session) == 0) {
-       errstr = newstralloc(errstr,
-                            "mutual authentication in mesg stream failed");
-       aclose(datafd);
-       if (indexfd != -1)
-           aclose(indexfd);
-       aclose(mesgfd);
-       response_error = 1;
-       return;
+
+    /*
+     * The MESGFD and DATAFD streams are mandatory.  If we didn't get
+     * them, complain.
+     */
+    if (streams[MESGFD].fd == NULL || streams[DATAFD].fd == NULL) {
+       errstr = newstralloc(errstr, "[couldn't open MESG or INDEX streams]");
+       goto connect_error;
     }
-#endif
-    response_error = 0;
+
+    /* everything worked */
+    *response_error = 0;
+    return;
+
+parse_error:
+    errstr = newvstralloc(errstr,
+                         "[parse of reply message failed: ",
+                         extra ? extra : "(no additional information)",
+                         "]",
+                         NULL);
+    amfree(extra);
+    *response_error = 2;
     return;
+
+connect_error:
+    stop_dump();
+    *response_error = 1;
 }
 
-int startup_dump(hostname, disk, device, level, dumpdate, progname, options)
-char *hostname, *disk, *device, *dumpdate, *progname, *options;
-int level;
+static int
+startup_dump(hostname, disk, device, level, dumpdate, progname, options)
+    const char *hostname, *disk, *device, *dumpdate, *progname, *options;
+    int level;
 {
     char level_string[NUM_STR_SIZE];
     char *req = NULL;
-    int rc;
+    char *authopt, *endauthopt, authoptbuf[64];
+    int response_error;
+    const security_driver_t *secdrv;
+    char *dumper_api;
 
     int has_features = am_has_feature(their_features, fe_req_options_features);
     int has_hostname = am_has_feature(their_features, fe_req_options_hostname);
     int has_device   = am_has_feature(their_features, fe_sendbackup_req_device);
 
-    ap_snprintf(level_string, sizeof(level_string), "%d", level);
+    /*
+     * Default to bsd authentication if none specified.  This is gross.
+     *
+     * Options really need to be pre-parsed into some sort of structure
+     * much earlier, and then flattened out again before transmission.
+     */
+    if ((authopt = strstr(options, "auth=")) == NULL
+       || (endauthopt = strchr(authopt, ';')) == NULL
+       || (sizeof(authoptbuf) - 1 < endauthopt - authopt)) {
+       authopt = "BSD";
+    } else {
+       authopt += strlen("auth=");
+       strncpy(authoptbuf, authopt, endauthopt - authopt);
+       authoptbuf[endauthopt - authopt] = '\0';
+       authopt = authoptbuf;
+    }
+
+    snprintf(level_string, sizeof(level_string), "%d", level);
+    if(strncmp(progname, "DUMP", 4) == 0
+       || strncmp(progname, "GNUTAR", 6) == 0) {
+       dumper_api = "";
+    } else {
+       dumper_api = "DUMPER ";
+    }
     req = vstralloc("SERVICE sendbackup\n",
                    "OPTIONS ",
                    has_features ? "features=" : "",
@@ -1798,74 +1750,28 @@ int level;
                    has_hostname ? hostname : "",
                    has_hostname ? ";" : "",
                    "\n",
-                   progname,
+                   dumper_api, progname,
                    " ", disk,
                    " ", device && has_device ? device : "",
                    " ", level_string,
                    " ", dumpdate,
-                   " ", "OPTIONS ", options,
+                   " OPTIONS ", options,
+                   /* compat: if auth=krb4, send krb4-auth */
+                   (strcasecmp(authopt, "krb4") ? "" : "krb4-auth"),
                    "\n",
                    NULL);
 
-    datafd = mesgfd = indexfd = -1;
+    secdrv = security_getdriver(authopt);
+    if (secdrv == NULL) {
+       error("no '%s' security driver available for host '%s'",
+           authopt, hostname);
+    }
 
-#ifdef KRB4_SECURITY
-    if(krb4_auth) {
-       char rc_str[NUM_STR_SIZE];
-
-       rc = make_krb_request(hostname, kamanda_port, req, NULL,
-                             STARTUP_TIMEOUT, sendbackup_response);
-       if(!rc) {
-           char inst[256], realm[256];
-#define HOSTNAME_INSTANCE inst
-           /*
-            * This repeats a lot of work with make_krb_request, but it's
-            * ultimately the kerberos library's fault: krb_mk_req calls
-            * krb_get_cred, but doesn't make the session key available!
-            * XXX: But admittedly, we could restructure a bit here and
-            * at least eliminate the duplicate gethostbyname().
-            */
-           if(host2krbname(hostname, inst, realm) == 0)
-               rc = -1;
-           else
-               rc = krb_get_cred(CLIENT_HOST_PRINCIPLE, CLIENT_HOST_INSTANCE,
-                                 realm, &cred);
-           if(rc > 0 ) {
-               ap_snprintf(rc_str, sizeof(rc_str), "%d", rc);
-               errstr = newvstralloc(errstr,
-                                     "[host ", hostname,
-                                     ": krb4 error (krb_get_cred) ",
-                                     rc_str,
-                                     ": ", krb_err_txt[rc],
-                                     NULL);
-               amfree(req);
-               return 2;
-           }
-       }
-       if(rc > 0) {
-           ap_snprintf(rc_str, sizeof(rc_str), "%d", rc);
-           errstr = newvstralloc(errstr,
-                                 "[host ", hostname,
-                                 ": krb4 error (make_krb_req) ",
-                                 rc_str,
-                                 ": ", krb_err_txt[rc],
-                                 NULL);
-           amfree(req);
-           return 2;
-       }
-    } else
-#endif
-       rc = make_request(hostname, amanda_port, req, NULL,
-                         STARTUP_TIMEOUT, sendbackup_response);
+    protocol_sendreq(hostname, secdrv, generic_get_security_conf, req,
+       STARTUP_TIMEOUT, sendbackup_response, &response_error);
 
-    req = NULL;                                        /* do not own this any more */
+    amfree(req);
 
-    if(rc) {
-       errstr = newvstralloc(errstr,
-                             "[could not resolve name \"", hostname, "\"]",
-                             NULL);
-       return 2;
-    }
-    run_protocol();
-    return response_error;
+    protocol_run();
+    return (response_error);
 }
index cc07fb1b804e47d277adc8cea48d7eb5ee7a2371..2f8c950f062b68bdbd84069911f6ad0cb3087463 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: find.c,v 1.6.2.4.4.2.2.5.2.1 2004/02/02 20:29:12 martinea Exp $
+ * $Id: find.c,v 1.23 2006/01/15 21:01:00 martinea Exp $
  *
  * controlling process for the Amanda backup system
  */
@@ -40,7 +40,10 @@ void find P((int argc, char **argv));
 int find_match P((char *host, char *disk));
 int search_logfile P((find_result_t **output_find, char *label, int datestamp, int datestamp_aux, char *logfile));
 void search_holding_disk P((find_result_t **output_find));
+void strip_failed_chunks P((find_result_t *output_find));
 char *find_nicedate P((int datestamp));
+static int find_compare P((const void *, const void *));
+static int parse_taper_datestamp_log P((char *, int *, char **));
 
 static char *find_sort_order = NULL;
 int dynamic_disklist = 0;
@@ -70,7 +73,7 @@ disklist_t* diskqp;
 
        tp = lookup_tapepos(tape);
        if(tp == NULL) continue;
-       ap_snprintf(ds_str, sizeof(ds_str), "%d", tp->datestamp);
+       snprintf(ds_str, sizeof(ds_str), "%d", tp->datestamp);
 
        /* search log files */
 
@@ -81,7 +84,7 @@ disklist_t* diskqp;
        for(seq = 0; 1; seq++) {
            char seq_str[NUM_STR_SIZE];
 
-           ap_snprintf(seq_str, sizeof(seq_str), "%d", seq);
+           snprintf(seq_str, sizeof(seq_str), "%d", seq);
            logfile = newvstralloc(logfile,
                        conf_logdir, "/log.", ds_str, ".", seq_str, NULL);
            if(access(logfile, R_OK) != 0) break;
@@ -110,6 +113,9 @@ disklist_t* diskqp;
     amfree(conf_logdir);
 
     search_holding_disk(&output_find);
+
+    strip_failed_chunks(output_find);
+    
     return(output_find);
 }
 
@@ -137,7 +143,7 @@ char **find_log()
 
        tp = lookup_tapepos(tape);
        if(tp == NULL) continue;
-       ap_snprintf(ds_str, sizeof(ds_str), "%d", tp->datestamp);
+       snprintf(ds_str, sizeof(ds_str), "%d", tp->datestamp);
 
        /* search log files */
 
@@ -148,7 +154,7 @@ char **find_log()
        for(seq = 0; 1; seq++) {
            char seq_str[NUM_STR_SIZE];
 
-           ap_snprintf(seq_str, sizeof(seq_str), "%d", seq);
+           snprintf(seq_str, sizeof(seq_str), "%d", seq);
            logfile = newvstralloc(logfile,
                        conf_logdir, "/log.", ds_str, ".", seq_str, NULL);
            if(access(logfile, R_OK) != 0) break;
@@ -192,6 +198,68 @@ char **find_log()
     return(output_find_log);
 }
 
+/*
+ * Remove CHUNK entries from dumps that ultimately failed from our report.
+ */
+void strip_failed_chunks(output_find)
+find_result_t *output_find;
+{
+    find_result_t *cur, *prev = NULL, *failed = NULL, *failures = NULL;
+
+    /* Generate a list of failures */
+    for(cur=output_find; cur; cur=cur->next) {
+       if(!cur->hostname || !cur->diskname) continue;
+
+       if(strcmp(cur->status, "OK")){
+           failed = alloc(sizeof(find_result_t));
+           memcpy(failed, cur, sizeof(find_result_t));
+           failed->next = failures;
+           failed->diskname = stralloc(cur->diskname);
+           failed->hostname = stralloc(cur->hostname);
+           failures = failed;
+       }
+    }
+
+    /* Now if a CHUNK matches the parameters of a failed dump, remove it */
+    for(failed=failures; failed; failed=failed->next) {
+       prev = NULL;
+       for(cur=output_find; cur; cur=cur->next) {
+           if(!cur->hostname || !cur->diskname ||
+                 !strcmp(cur->partnum, "--") || strcmp(cur->status, "OK")){
+               prev = cur;
+               continue;
+           }
+
+           if(!strcmp(cur->hostname, failed->hostname) &&
+                !strcmp(cur->diskname, failed->diskname) &&
+                cur->datestamp == failed->datestamp &&
+                cur->datestamp_aux == failed->datestamp_aux &&
+                cur->level == failed->level){
+               find_result_t *next = cur->next;
+               amfree(cur->diskname);
+               amfree(cur->hostname);
+               next = cur->next;
+               amfree(cur);
+               if(prev){
+                   prev->next = next;
+                   cur = prev;
+               }
+               else output_find = next;
+           }
+            else prev = cur;
+       }
+    }
+
+    for(failed=failures; failed;) {
+       find_result_t *fai = failed->next;
+       amfree(failed->diskname);
+       amfree(failed->hostname);
+       fai = failed->next;
+       amfree(failed);
+       failed=fai;
+    }
+}
+
 void search_holding_disk(output_find)
 find_result_t **output_find;
 {
@@ -274,6 +342,7 @@ find_result_t **output_find;
                    diskname = NULL;
                    new_output_find->level=level;
                    new_output_find->label=stralloc(destname);
+                   new_output_find->partnum=stralloc("--");
                    new_output_find->filenum=0;
                    new_output_find->status=stralloc("OK");
                    *output_find=new_output_find;
@@ -321,12 +390,30 @@ const void *j1;
                   break;
        case 'l' : compare=(*j)->level - (*i)->level;
                   break;
+       case 'f' : compare=(*i)->filenum - (*j)->filenum;
+                  break;
+       case 'F' : compare=(*j)->filenum - (*i)->filenum;
+                  break;
        case 'L' : compare=(*i)->level - (*j)->level;
                   break;
        case 'b' : compare=strcmp((*i)->label,(*j)->label);
                   break;
        case 'B' : compare=strcmp((*j)->label,(*i)->label);
                   break;
+       case 'p' :
+                  if(strcmp((*i)->partnum, "--") != 0 &&
+                     strcmp((*j)->partnum, "--") != 0){
+                     compare = atoi((*i)->partnum) - atoi((*j)->partnum);
+                  }
+                  else compare=strcmp((*i)->partnum,(*j)->partnum);
+                  break;
+       case 'P' :
+                  if(strcmp((*i)->partnum, "--") != 0 &&
+                     strcmp((*j)->partnum, "--") != 0){
+                     compare = atoi((*j)->partnum) - atoi((*i)->partnum);
+                  }
+                  else compare=strcmp((*j)->partnum,(*i)->partnum);
+                  break;
        }
        if(compare != 0)
            return compare;
@@ -387,6 +474,7 @@ find_result_t *output_find;
     int max_len_level     = 2;
     int max_len_label     =12;
     int max_len_filenum   = 4;
+    int max_len_part      = 4;
     int max_len_status    = 6;
     int len;
 
@@ -408,6 +496,9 @@ find_result_t *output_find;
 
        len=strlen(output_find_result->status);
        if(len>max_len_status) max_len_status=len;
+
+       len=strlen(output_find_result->partnum);
+       if(len>max_len_part) max_len_part=len;
     }
 
     /*
@@ -421,18 +512,19 @@ find_result_t *output_find;
        printf("\nNo dump to list\n");
     }
     else {
-       printf("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s status\n",
+       printf("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n",
               max_len_datestamp-4,"",
               max_len_hostname-4 ,"",
               max_len_diskname-4 ,"",
               max_len_level-2    ,"",
               max_len_label-12   ,"",
-              max_len_filenum-4  ,"");
+              max_len_filenum-4  ,"",
+              max_len_part-4  ,"");
         for(output_find_result=output_find;
                output_find_result;
                output_find_result=output_find_result->next) {
 
-           printf("%-*s %-*s %-*s %*d %-*s %*d %-*s\n",
+           printf("%-*s %-*s %-*s %*d %-*s %*d %*s %-*s\n",
                    max_len_datestamp, 
                        find_nicedate(output_find_result->datestamp),
                    max_len_hostname,  output_find_result->hostname,
@@ -440,7 +532,9 @@ find_result_t *output_find;
                    max_len_level,     output_find_result->level,
                    max_len_label,     output_find_result->label,
                    max_len_filenum,   output_find_result->filenum,
-                   max_len_status,    output_find_result->status);
+                   max_len_part,      output_find_result->partnum,
+                   max_len_status,    output_find_result->status
+                   );
        }
     }
 }
@@ -458,7 +552,9 @@ find_result_t **output_find;
        amfree(output_find_result->hostname);
        amfree(output_find_result->diskname);
        amfree(output_find_result->label);
+       amfree(output_find_result->partnum);
        amfree(output_find_result->status);
+       amfree(output_find_result->timestamp);
        prev = output_find_result;
     }
     if(prev != NULL) amfree(prev);
@@ -482,7 +578,7 @@ int datestamp;
     month = (datestamp / 100) % 100;
     day   = datestamp % 100;
 
-    ap_snprintf(nice, sizeof(nice), "%4d-%02d-%02d", year, month, day);
+    snprintf(nice, sizeof(nice), "%4d-%02d-%02d", year, month, day);
 
     return nice;
 }
@@ -539,6 +635,31 @@ char **label;
     return 1;
 }
 
+/*
+ * Check whether we've already seen a CHUNK log entry for the given dump.
+ * This is so we can interpret the final SUCCESS entry for a split dump as 
+ * 'list its parts' instead.  Return 1 if we have, 0 if not.
+ */
+int seen_chunk_of(output_find, date, host, disk, level)
+find_result_t *output_find;
+int date, level;
+char *host, *disk;
+{
+    find_result_t *cur;
+
+    if(!host || !disk) return(0);
+
+    for(cur=output_find; cur; cur=cur->next) {
+       if(atoi(cur->partnum) < 1 || !cur->hostname || !cur->diskname) continue;
+
+       if(cur->datestamp == date && strcmp(cur->hostname, host) == 0 &&
+               strcmp(cur->diskname, disk) == 0 && cur->level == level){
+           return(1);
+       }
+    }
+    return(0);
+}
+
 /* if output_find is NULL                                      */
 /*     return 1 if this is the logfile for this label          */
 /*     return 0 if this is not the logfile for this label      */
@@ -553,6 +674,7 @@ int datestamp, datestamp_aux;
     FILE *logf;
     char *host, *host_undo;
     char *disk, *disk_undo;
+    char *partnum=NULL, *partnum_undo;
     int   datestampI;
     char *rest;
     char *ck_label;
@@ -595,7 +717,10 @@ int datestamp, datestamp_aux;
     filenum = 0;
     passlabel = 1;
     while(get_logline(logf) && passlabel) {
-       if(curlog == L_SUCCESS && curprog == P_TAPER && passlabel) filenum++;
+       if((curlog == L_SUCCESS || curlog == L_CHUNK) &&
+                               curprog == P_TAPER && passlabel){
+           filenum++;
+       }
        if(curlog == L_START && curprog == P_TAPER) {
            if(parse_taper_datestamp_log(curstr,
                                         &ck_datestamp2, &ck_label) == 0) {
@@ -604,7 +729,8 @@ int datestamp, datestamp_aux;
                passlabel = !passlabel;
            }
        }
-       if(curlog == L_SUCCESS || curlog == L_FAIL) {
+       partnum = "--";
+       if(curlog == L_SUCCESS || curlog == L_FAIL || curlog == L_CHUNK) {
            s = curstr;
            ch = *s++;
 
@@ -640,6 +766,13 @@ int datestamp, datestamp_aux;
                datestampI = datestamp;
            }
            else {
+               if(curlog == L_CHUNK){
+                   skip_whitespace(s, ch);
+                   partnum = s - 1;
+                   skip_non_whitespace(s, ch);
+                   partnum_undo = s - 1;
+                   *partnum_undo = '\0';
+               }
                skip_whitespace(s, ch);
                if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
                    printf("strange log line \"%s\"\n", curstr);
@@ -663,24 +796,26 @@ int datestamp, datestamp_aux;
                if (dynamic_disklist == 0) {
                    continue;
                }
-               dp = add_disk(host, disk);
-               enqueue_disk(find_diskqp , dp);
+               dp = add_disk(find_diskqp, host, disk);
+               enqueue_disk(find_diskqp, dp);
            }
-           if(find_match(host, disk)) {
+            if(find_match(host, disk) && (curlog != L_SUCCESS ||
+               !seen_chunk_of(*output_find,datestampI,host,disk,level))){
                if(curprog == P_TAPER) {
                    find_result_t *new_output_find =
                        (find_result_t *)alloc(sizeof(find_result_t));
                    new_output_find->next=*output_find;
                    new_output_find->datestamp=datestampI;
                    new_output_find->timestamp = alloc(15);
-                   ap_snprintf(new_output_find->timestamp, 15, "%d000000", datestampI);
+                   snprintf(new_output_find->timestamp, 15, "%d000000", datestampI);
                    new_output_find->datestamp_aux=datestamp_aux;
                    new_output_find->hostname=stralloc(host);
                    new_output_find->diskname=stralloc(disk);
                    new_output_find->level=level;
+                   new_output_find->partnum = stralloc(partnum);
                    new_output_find->label=stralloc(label);
                    new_output_find->filenum=filenum;
-                   if(curlog == L_SUCCESS) 
+                   if(curlog == L_SUCCESS || curlog == L_CHUNK
                        new_output_find->status=stralloc("OK");
                    else
                        new_output_find->status=stralloc(rest);
@@ -693,11 +828,12 @@ int datestamp, datestamp_aux;
                    new_output_find->datestamp=datestamp;
                    new_output_find->datestamp_aux=datestamp_aux;
                    new_output_find->timestamp = alloc(15);
-                   ap_snprintf(new_output_find->timestamp, 15, "%d000000", datestamp);
+                   snprintf(new_output_find->timestamp, 15, "%d000000", datestamp);
                    new_output_find->hostname=stralloc(host);
                    new_output_find->diskname=stralloc(disk);
                    new_output_find->level=level;
-                   new_output_find->label=stralloc("---");
+                   new_output_find->label=stralloc(label);
+                   new_output_find->partnum=stralloc(partnum);
                    new_output_find->filenum=0;
                    new_output_find->status=vstralloc(
                         "FAILED (",
@@ -714,6 +850,55 @@ int datestamp, datestamp_aux;
     return 1;
 }
 
+
+/*
+ * Return the set of dumps that match *all* of the given patterns (we consider
+ * an empty pattern to match .*, though).  If 'ok' is true, will only match
+ * dumps with SUCCESS status.
+ */
+find_result_t *dumps_match(output_find,hostname,diskname,datestamp,level,ok)
+find_result_t *output_find;
+char *hostname;
+char *diskname;
+char *datestamp;
+char *level;
+int ok;
+{
+    find_result_t *cur_result;
+    find_result_t *matches = NULL;
+
+    for(cur_result=output_find;
+       cur_result;
+       cur_result=cur_result->next) {
+       char date_str[NUM_STR_SIZE];
+       char level_str[NUM_STR_SIZE];
+       snprintf(date_str, sizeof(date_str), "%d", cur_result->datestamp);
+       snprintf(level_str, sizeof(level_str), "%d", cur_result->level);
+       if((*hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
+          (*diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
+          (*datestamp== '\0' || match_datestamp(datestamp, date_str)) &&
+          (*level== '\0' || match_level(level, level_str)) &&
+          (!ok || !strcmp(cur_result->status, "OK"))){
+
+           find_result_t *curmatch = alloc(sizeof(find_result_t));
+           memcpy(curmatch, cur_result, sizeof(find_result_t));
+
+/*
+           curmatch->hostname = stralloc(cur_result->hostname);
+           curmatch->diskname = stralloc(cur_result->diskname);
+           curmatch->datestamp = stralloc(cur_result->datestamp);
+           curmatch->partnum = stralloc(cur_result->partnum);
+           curmatch->status = stralloc(cur_result->status);
+           curmatch->level = stralloc(cur_result->level);
+*/         
+           curmatch->next = matches;
+           matches = curmatch;
+       }
+    }
+
+    return(matches);
+}
+
 find_result_t *dump_exist(output_find, hostname, diskname, datestamp, level)
 find_result_t *output_find;
 char *hostname;
index c657dfc203e22c41774de1bf4b8e22891bf90789..5b9811db8e8c21e004cf631180d4a9268a1aa8b4 100644 (file)
@@ -1,5 +1,6 @@
+#include "diskfile.h"
 
-#define DEFAULT_SORT_ORDER      "hkdlb"
+#define DEFAULT_SORT_ORDER      "hkdlpb"
 
 typedef struct find_result_s {
     struct find_result_s *next;
@@ -14,12 +15,14 @@ typedef struct find_result_s {
     char *label;
     int  filenum;
     char *status;
+    char *partnum;
+    void *user_ptr;
 } find_result_t;
 
 find_result_t *find_dump P((int dyna_disklist, disklist_t* diskqp));
-char **find_log P(());
+char **find_log P((void));
 void sort_find_result P((char *sort_order, find_result_t **output_find));
 void print_find_result P((find_result_t *output_find));
 void free_find_result P((find_result_t **output_find));
 find_result_t *dump_exist P((find_result_t *output_find, char *hostname, char *diskname, int datestamp, int level));
-
+find_result_t *dumps_match P((find_result_t *output_find, char *hostname, char *diskname, char *datestamp, char *level, int ok));
index b495216d8ca4a7f71bdd51413c6afc577ed99946..c645ebdf3a812c42aad96f5c60fded247395a7c0 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: getconf.c,v 1.8.4.2.2.2.2.4.2.3 2005/09/21 19:04:22 jrjackson Exp $
+ * $Id: getconf.c,v 1.18 2006/01/14 04:37:19 paddy_s Exp $
  *
  * a little wrapper to extract config variables for shell scripts
  */
@@ -34,8 +34,6 @@
 #include "genversion.h"
 #include "conffile.h"
 
-#define HOSTNAME_INSTANCE "host_inst"
-
 int main P((int argc, char **argv));
 
 static struct build_info {
@@ -330,6 +328,9 @@ char **argv;
     }
     set_pname(pgm);
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     if(argc < 2) {
        fprintf(stderr, "Usage: %s [config] <parmname>\n", pgm);
        exit(1);
@@ -363,14 +364,14 @@ char **argv;
 #else
     i = -1;
 #endif
-    ap_snprintf(number, sizeof(number), "%ld", (long)i);
+    snprintf(number, sizeof(number), "%ld", (long)i);
     build_info[1].value = stralloc(number);
 #if defined(KRB4_SECURITY)
     i = TICKET_LIFETIME;
 #else
     i = -1;
 #endif
-    ap_snprintf(number, sizeof(number), "%ld", (long)i);
+    snprintf(number, sizeof(number), "%ld", (long)i);
     build_info[2].value = stralloc(number);
 
 #undef p
index a158fecc7fc3913c05f83d1c46ec0be181e7b722..9581e60550b3c5bdfaa7cd0333989ed110be0b27 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: holding.c,v 1.17.2.12.4.3.2.10.2.2 2004/10/21 13:12:29 martinea Exp $
+ * $Id: holding.c,v 1.52 2006/03/09 22:01:21 martinea Exp $
  *
  * Functions to access holding disk
  */
@@ -33,7 +33,6 @@
 #include "util.h"
 #include "holding.h"
 #include "fileheader.h"
-#include "util.h"
 #include "logfile.h"
 
 static sl_t *scan_holdingdisk P((sl_t *holding_list, char *diskdir, int verbose));
@@ -126,7 +125,7 @@ char *fname;
 }
 
 
-sl_t *scan_holdingdisk(holding_list, diskdir, verbose)
+static sl_t *scan_holdingdisk(holding_list, diskdir, verbose)
 sl_t *holding_list;
 char *diskdir;
 int verbose;
@@ -147,8 +146,7 @@ int verbose;
     if(verbose)
        printf("Scanning %s...\n", diskdir);
     while((workdir = readdir(topdir)) != NULL) {
-       if(is_dot_or_dotdot(workdir->d_name)
-          || strcmp(workdir->d_name, "lost+found") == 0) {
+       if(is_dot_or_dotdot(workdir->d_name)) {
            continue;
        }
        entryname = newvstralloc(entryname,
@@ -157,15 +155,18 @@ int verbose;
            printf("  %s: ", workdir->d_name);
        }
        if(!is_dir(entryname)) {
-           if(verbose)
+           if(verbose) {
                puts("skipping cruft file, perhaps you should delete it.");
+           }
        } else if(!is_datestr(workdir->d_name)) {
-           if(verbose)
+           if(verbose && (strcmp(workdir->d_name, "lost+found")!=0) ) {
                puts("skipping cruft directory, perhaps you should delete it.");
+           }
        } else {
            holding_list = insert_sort_sl(holding_list, workdir->d_name);
-           if(verbose)
+           if(verbose) {
                puts("found Amanda directory.");
+           }
        }
     }
     closedir(topdir);
@@ -235,6 +236,7 @@ char *datestamp;
 }
 
 
+
 sl_t *get_flush(dateargs, datestamp, amflush, verbose)
 sl_t *dateargs;
 char *datestamp;  /* don't do this date */
@@ -431,8 +433,9 @@ dumpfile_t *file;
 }
 
 
-long size_holding_files(holding_file)
+long size_holding_files(holding_file, strip_headers)
 char *holding_file;
+int strip_headers;
 {
     int fd;
     int buflen;
@@ -449,15 +452,22 @@ char *holding_file;
            amfree(filename);
            return -1;
        }
-       buflen = fullread(fd, buffer, sizeof(buffer));
-       parse_file_header(buffer, &file, buflen);
+       if ((buflen = fullread(fd, buffer, sizeof(buffer))) > 0) {
+               parse_file_header(buffer, &file, buflen);
+       }
        close(fd);
        if(stat(filename, &finfo) == -1) {
            printf("stat %s: %s\n", filename, strerror(errno));
            finfo.st_size = 0;
        }
        size += (finfo.st_size+1023)/1024;
-       filename = newstralloc(filename, file.cont_filename);
+       if(strip_headers) size -= DISK_BLOCK_BYTES/1024;
+       if(buflen > 0) {
+           filename = newstralloc(filename, file.cont_filename);
+       }
+       else {
+           amfree(filename);
+       }
     }
     amfree(filename);
     return size;
@@ -480,11 +490,17 @@ char *holding_file;
            amfree(filename);
            return 0;
        }
-       buflen = fullread(fd, buffer, sizeof(buffer));
-       parse_file_header(buffer, &file, buflen);
+       if ((buflen = fullread(fd, buffer, sizeof(buffer))) > 0) {
+           parse_file_header(buffer, &file, buflen);
+       }
        close(fd);
        unlink(filename);
-       filename = newstralloc(filename,file.cont_filename);
+       if(buflen > 0) {
+           filename = newstralloc(filename, file.cont_filename);
+       }
+       else {
+           amfree(filename);
+       }
     }
     amfree(filename);
     return 1;
@@ -520,7 +536,7 @@ int complete;
                    filename_tmp, filename, strerror(errno));
        }
 
-       if (buflen == 0) {
+       if (buflen <= 0) {
            fprintf(stderr,"rename_tmp_holding: %s: empty file?\n", filename);
            amfree(filename);
            amfree(filename_tmp);
@@ -569,10 +585,11 @@ int verbose;
        printf("Scanning %s...\n", diskdir);
     chdir(diskdir);
     while((workdir = readdir(topdir)) != NULL) {
-       if(is_dot_or_dotdot(workdir->d_name)
-          || strcmp(workdir->d_name, "lost+found") == 0) {
+       if(strcmp(workdir->d_name, ".") == 0
+          || strcmp(workdir->d_name, "..") == 0
+          || strcmp(workdir->d_name, "lost+found") == 0)
            continue;
-       }
+
        if(verbose)
            printf("  %s: ", workdir->d_name);
        if(!is_dir(workdir->d_name)) {
@@ -580,7 +597,7 @@ int verbose;
                puts("skipping cruft file, perhaps you should delete it.");
        }
        else if(!is_datestr(workdir->d_name)) {
-           if(verbose)
+           if(verbose && (strcmp(workdir->d_name, "lost+found")!=0) )
                puts("skipping cruft directory, perhaps you should delete it.");
        }
        else if(rmdir(workdir->d_name) == 0) {
index e2aead26e5982c981e3ae53576bd3adce75ad512..75284d5e39c74e8c521a8751c588dd5289de2757 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: holding.h,v 1.11.2.7.4.1.2.2 2003/06/03 20:14:44 martinea Exp $
+ * $Id: holding.h,v 1.22 2005/10/11 01:17:01 vectro Exp $
  *
  */
 
@@ -50,7 +50,7 @@ filetype_t get_amanda_names P((char *fname,
                               char **diskname,
                               int *level));
 void get_dumpfile P((char *fname, dumpfile_t *file));
-long size_holding_files P((char *holding_file));
+long size_holding_files P((char *holding_file, int strip_headers));
 int unlink_holding_files P((char *holding_file));
 int rename_tmp_holding P((char *holding_file, int complete));
 void cleanup_holdingdisk P((char *diskdir, int verbose));
index 68e0ec85275d2fee129670945b841dbc66edf6ea..ac331a7adb10e8f93743611f766dd1d948779436 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: infofile.c,v 1.44.4.4.8.5 2005/09/30 19:13:36 martinea Exp $
+ * $Id: infofile.c,v 1.57 2006/03/10 11:56:06 martinea Exp $
  *
  * manage current info file
  */
 #include "infofile.h"
 #include "token.h"
 
+static void zero_info P((info_t *));
+
 #ifdef TEXTDB
   static char *infodir = (char *)0;
   static char *infofile = (char *)0;
   static char *newinfofile;
   static int writing;
+
+  static FILE *open_txinfofile P((char *, char *, char *));
+  static int close_txinfofile P((FILE *));
+  static int read_txinfofile P((FILE *, info_t *));
+  static int write_txinfofile P((FILE *, info_t *));
+  static int delete_txinfofile P((char *, char *));
 #else
 #  define MAX_KEY 256
 /*#  define HEADER     (sizeof(info_t)-DUMP_LEVELS*sizeof(stats_t))*/
@@ -49,7 +57,7 @@
 
 #ifdef TEXTDB
 
-FILE *open_txinfofile(host, disk, mode)
+static FILE *open_txinfofile(host, disk, mode)
 char *host;
 char *disk;
 char *mode;
@@ -101,7 +109,7 @@ char *mode;
     return infof;
 }
 
-int close_txinfofile(infof)
+static int close_txinfofile(infof)
 FILE *infof;
 {
     int rc = 0;
@@ -124,7 +132,7 @@ FILE *infof;
     return rc;
 }
 
-int read_txinfofile(infof, info) /* XXX - code assumes AVG_COUNT == 3 */
+static int read_txinfofile(infof, info) /* XXX - code assumes AVG_COUNT == 3 */
 FILE *infof;
 info_t *info;
 {
@@ -259,7 +267,8 @@ info_t *info;
 
        onestat.date = date;    /* time_t not guarranteed to be long */
 
-       if(level < 0 || level > DUMP_LEVELS-1) break;
+       if(level < 0 || level > DUMP_LEVELS-1)
+           break;
 
        info->inf[level] = onestat;
     }
@@ -268,7 +277,7 @@ info_t *info;
 
     rc = sscanf(line, "last_level: %d %d", 
                &info->last_level, &info->consecutive_runs);
-               
+
     amfree(line);
     if(rc > 2) return -2;
     rc = 0;
@@ -277,6 +286,7 @@ info_t *info;
     for(i=0;i<=NB_HISTORY;i++) {
        info->history[i].level = -2;
     }
+
     for(rc = -2; (line = agets(infof)) != NULL; free(line)) {
        history_t onehistory;   /* one history record */
        long date;
@@ -295,6 +305,7 @@ info_t *info;
 
 #define sc "history:"
        if(strncmp(line, sc, sizeof(sc)-1) != 0) {
+           amfree(line);
            break;
        }
        s += sizeof(sc)-1;
@@ -303,24 +314,28 @@ info_t *info;
 
        skip_whitespace(s, ch);
        if(ch == '\0' || sscanf((s - 1), "%d", &onehistory.level) != 1) {
+           amfree(line);
            break;
        }
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
        if(ch == '\0' || sscanf((s - 1), "%ld", &onehistory.size) != 1) {
+           amfree(line);
            break;
        }
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
        if(ch == '\0' || sscanf((s - 1), "%ld", &onehistory.csize) != 1) {
+           amfree(line);
            break;
        }
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
        if(ch == '\0' || sscanf((s - 1), "%ld", &date) != 1) {
+           amfree(line);
            break;
        }
        skip_integer(s, ch);
@@ -331,6 +346,7 @@ info_t *info;
        skip_whitespace(s, ch);
        if(ch != '\0') {
            if(sscanf((s - 1), "%ld", &onehistory.secs) != 1) {
+               amfree(line);
                break;
            }
            skip_integer(s, ch);
@@ -338,6 +354,7 @@ info_t *info;
 
        info->history[nb_history++] = onehistory;
     }
+    amfree(line);
 
     if((line = agets(infof)) == NULL) return -1; /* // line */
     amfree(line);
@@ -345,7 +362,7 @@ info_t *info;
     return rc;
 }
 
-int write_txinfofile(infof, info)
+static int write_txinfofile(infof, info)
 FILE *infof;
 info_t *info;
 {
@@ -410,7 +427,7 @@ info_t *info;
     return 0;
 }
 
-int delete_txinfofile(host, disk)
+static int delete_txinfofile(host, disk)
 char *host;
 char *disk;
 {
@@ -513,7 +530,7 @@ int lev;
     }
 
     t = gmtime(&last);
-    ap_snprintf(stamp, sizeof(stamp), "%d:%d:%d:%d:%d:%d",
+    snprintf(stamp, sizeof(stamp), "%d:%d:%d:%d:%d:%d",
                t->tm_year+1900, t->tm_mon+1, t->tm_mday,
                t->tm_hour, t->tm_min, t->tm_sec);
 
@@ -545,7 +562,7 @@ double d;   /* default value */
     return sum / n;
 }
 
-void zero_info(info)
+static void zero_info(info)
 info_t *info;
 {
     int i;
index eb068f7df20e909961a3344eab1392742fb31fdc..3aa2ef2cb8eb5b0fcebb1f0e8e55c7aa847f9830 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: infofile.h,v 1.7.4.4.8.2 2005/03/16 18:15:28 martinea Exp $
+ * $Id: infofile.h,v 1.13 2005/03/16 18:15:05 martinea Exp $
  *
  * interface for current info file reading code
  */
index 14c908444ebf6a3f3cea68c4ab6e58612eaecbc6..c38a30639b6d84876d7c59075ff33d4df2b47eeb 100644 (file)
@@ -23,7 +23,7 @@
  * Authors: the Amanda Development Team.  Its members are listed in a
  * file named AUTHORS, in the root directory of this distribution.
  */
-/* $Id: list_dir.c,v 1.14.4.2.6.1 2002/03/24 19:23:24 jrjackson Exp $
+/* $Id: list_dir.c,v 1.17 2002/03/24 19:25:51 jrjackson Exp $
  *
  * manage directory listings from index files
  */
index 312fa600c59cdd9d6f3f483c320bdb1b229b3e31..fec34747f1008b44475facdf57a0bfc3a227c055 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: list_dir.h,v 1.2.4.1 1999/02/15 02:31:07 martinea Exp $
+ * $Id: list_dir.h,v 1.3 1999/02/15 02:30:26 martinea Exp $
  *
  */
 
index 9faf46f8da701bb2a94c14444e04a81a36d3cb3a..de063dcfd1782f023f03e8b51f55a98cf169c5a7 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: logfile.c,v 1.17.4.1.4.2.2.3 2003/01/01 23:28:56 martinea Exp $
+ * $Id: logfile.c,v 1.29 2005/12/04 22:56:55 martinea Exp $
  *
  * common log file writing routine
  */
 #include "amanda.h"
 #include "arglist.h"
+#include "util.h"
 #include "conffile.h"
 
 #include "logfile.h"
@@ -41,14 +42,16 @@ char *logtype_str[] = {
     "ERROR", "WARNING",        "INFO", "SUMMARY",       /* information messages */
     "START", "FINISH",                            /* start/end of a run */
     "DISK",                                                     /* disk */
-    "SUCCESS", "FAIL", "STRANGE",                  /* the end of a dump */
+    "SUCCESS", "PARTIAL", "FAIL", "STRANGE",       /* the end of a dump */
+    "CHUNK", "CHUNKSUCCESS",                            /* ... continued */
     "STATS",                                              /* statistics */
     "MARKER",                                    /* marker for reporter */
     "CONT"                                /* continuation line; special */
 };
 
 char *program_str[] = {
-    "UNKNOWN", "planner", "driver", "amreport", "dumper", "taper", "amflush"
+    "UNKNOWN", "planner", "driver", "amreport", "dumper", "chunker",
+    "taper", "amflush"
 };
 
 int curlinenum;
@@ -79,13 +82,37 @@ char *msg;
     log_add(L_FATAL, "%s", msg);
 }
 
+
+printf_arglist_function2(char *log_genstring, logtype_t, typ, char *, pname, char *, format)
+{
+    va_list argp;
+    char *leader = NULL;
+    char linebuf[STR_SIZE];
+
+
+    /* format error message */
+
+    if((int)typ <= (int)L_BOGUS || (int)typ > (int)L_MARKER) typ = L_BOGUS;
+
+    if(multiline > 0) {
+       leader = stralloc("  ");                /* continuation line */
+    } else {
+       leader = vstralloc(logtype_str[(int)typ], " ", pname, " ", NULL);
+    }
+
+    arglist_start(argp, format);
+    vsnprintf(linebuf, sizeof(linebuf)-1, format, argp);
+                                               /* -1 to allow for '\n' */
+    return(vstralloc(leader, linebuf, "\n", NULL));
+}
+
 printf_arglist_function1(void log_add, logtype_t, typ, char *, format)
 {
     va_list argp;
     int saved_errout;
     char *leader = NULL;
     char linebuf[STR_SIZE];
-    int l, n, s;
+    int n;
 
 
     /* format error message */
@@ -99,7 +126,7 @@ printf_arglist_function1(void log_add, logtype_t, typ, char *, format)
     }
 
     arglist_start(argp, format);
-    ap_vsnprintf(linebuf, sizeof(linebuf)-1, format, argp);
+    vsnprintf(linebuf, sizeof(linebuf)-1, format, argp);
                                                /* -1 to allow for '\n' */
     arglist_end(argp);
 
@@ -112,11 +139,8 @@ printf_arglist_function1(void log_add, logtype_t, typ, char *, format)
 
     if(multiline == -1) open_log();
 
-    for(l = 0, n = strlen(leader); l < n; l += s) {
-       if((s = write(logfd, leader + l, n - l)) < 0) {
-           error("log file write error: %s", strerror(errno));
-       }
-    }
+    if (fullwrite(logfd, leader, strlen(leader)) < 0)
+       error("log file write error: %s", strerror(errno));
 
     amfree(leader);
 
@@ -124,11 +148,8 @@ printf_arglist_function1(void log_add, logtype_t, typ, char *, format)
     if(n == 0 || linebuf[n-1] != '\n') linebuf[n++] = '\n';
     linebuf[n] = '\0';
 
-    for(l = 0; l < n; l += s) {
-       if((s = write(logfd, linebuf + l, n - l)) < 0) {
-           error("log file write error: %s", strerror(errno));
-       }
-    }
+    if (fullwrite(logfd, linebuf, n) < 0)
+       error("log file write error: %s", strerror(errno));
 
     if(multiline != -1) multiline++;
     else close_log();
@@ -174,7 +195,7 @@ char *datestamp;
     logfile = vstralloc(conf_logdir, "/log", NULL);
 
     for(seq = 0; 1; seq++) {   /* if you've got MAXINT files in your dir... */
-       ap_snprintf(seq_str, sizeof(seq_str), "%d", seq);
+       snprintf(seq_str, sizeof(seq_str), "%d", seq);
        fname = newvstralloc(fname,
                             logfile,
                             ".", datestamp,
@@ -183,10 +204,9 @@ char *datestamp;
        if(stat(fname, &statbuf) == -1 && errno == ENOENT) break;
     }
 
-    if(rename(logfile, fname) != 0) {
+    if(rename(logfile, fname) == -1)
        error("could not rename \"%s\" to \"%s\": %s",
              logfile, fname, strerror(errno));
-    }
 
     amfree(fname);
     amfree(logfile);
@@ -209,9 +229,8 @@ static void open_log()
 
     logfd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600);
 
-    if(logfd == -1) {
+    if(logfd == -1)
        error("could not open log file %s: %s", logfile, strerror(errno));
-    }
 
     if(amflock(logfd, "log") == -1)
        error("could not lock log file %s: %s", logfile, strerror(errno));
index d229f6ea9954168405ba59fa0d8244711832d7e2..fbeda341c6421a56440e403690339063731363c8 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: logfile.h,v 1.6.8.1.2.1 2002/02/10 03:31:53 jrjackson Exp $
+ * $Id: logfile.h,v 1.12 2005/11/29 22:19:08 martinea Exp $
  *
  * interface to logfile module
  */
@@ -46,14 +46,16 @@ typedef enum logtype_e {
     L_ERROR, L_WARNING,        L_INFO, L_SUMMARY,       /* information messages */
     L_START, L_FINISH,                              /* start/end of run */
     L_DISK,                                                     /* disk */
-    L_SUCCESS, L_FAIL, L_STRANGE,                  /* the end of a dump */
+    L_SUCCESS, L_PARTIAL, L_FAIL, L_STRANGE,       /* the end of a dump */
+    L_CHUNK, L_CHUNKSUCCESS,                            /* ... continued */
     L_STATS,                                              /* statistics */
     L_MARKER,                                    /* marker for reporter */
     L_CONT                      /* continuation line, used when reading */
 } logtype_t;
 
 typedef enum program_e {
-    P_UNKNOWN, P_PLANNER, P_DRIVER, P_REPORTER, P_DUMPER, P_TAPER, P_AMFLUSH
+    P_UNKNOWN, P_PLANNER, P_DRIVER, P_REPORTER, P_DUMPER, P_CHUNKER,
+    P_TAPER, P_AMFLUSH
 } program_t;
 #define P_LAST P_AMFLUSH
 
@@ -68,6 +70,8 @@ extern char *program_str[];
 void logerror P((char *));
 void log_add P((logtype_t typ, char * format, ...))
     __attribute__ ((format (printf, 2, 3)));
+char* log_genstring P((logtype_t typ, char *pname, char * format, ...));
+/*    __attribute__ ((format (printf, 3, 4))); */
 void log_start_multiline P((void));
 void log_end_multiline P((void));
 void log_rename P((char *datestamp));
index 8c886b4ce0b5898b010f37f44decac0c2f7925c5..92de8d830fda7a8856edb83ce25b2a75d61c9470 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: planner.c,v 1.76.2.15.2.13.2.32.2.20 2005/09/20 21:31:52 jrjackson Exp $
+ * $Id: planner.c,v 1.180 2006/03/10 13:51:06 martinea Exp $
  *
  * backup schedule planner for the Amanda backup system.
  */
@@ -36,7 +36,8 @@
 #include "infofile.h"
 #include "logfile.h"
 #include "clock.h"
-#include "dgram.h"
+#include "packet.h"
+#include "security.h"
 #include "protocol.h"
 #include "version.h"
 #include "amfeatures.h"
 #define RUNS_REDZONE               5   /* should be in conf file? */
 
 #define PROMOTE_THRESHOLD       0.05   /* if <5% unbalanced, don't promote */
-#define DEFAULT_DUMPRATE        30.0   /* K/s */
+#define DEFAULT_DUMPRATE        1024.0 /* K/s */
 
 /* configuration file stuff */
 
 char *conf_tapetype;
-int conf_maxdumpsize;
+am64_t conf_maxdumpsize;
 int conf_runtapes;
 int conf_dumpcycle;
 int conf_runspercycle;
@@ -96,25 +97,19 @@ typedef struct est_s {
 
 /* pestq = partial estimate */
 disklist_t startq, waitq, pestq, estq, failq, schedq;
-long total_size;
+am64_t total_size;
 double total_lev0, balanced_size, balance_threshold;
-unsigned long tape_length, tape_mark;
-int result_port, amanda_port;
-
-static am_feature_t *our_features = NULL;
-static char *our_feature_string = NULL;
-
-#ifdef KRB4_SECURITY
-int kamanda_port;
-#endif
+am64_t tape_length, tape_mark;
 
 tapetype_t *tape;
 long tt_blocksize;
 long tt_blocksize_kb;
 int runs_per_cycle = 0;
 time_t today;
+char *datestamp = NULL;
 
-dgram_t *msg;
+static am_feature_t *our_features = NULL;
+static char *our_feature_string = NULL;
 
 /* We keep a LIFO queue of before images for all modifications made
  * to schedq in our attempt to make the schedule fit on the tape.
@@ -137,8 +132,6 @@ typedef struct bilist_s {
 
 bilist_t biq;                  /* The BI queue itself */
 
-char *datestamp = NULL;
-
 /*
  * ========================================================================
  * MAIN PROGRAM
@@ -153,18 +146,19 @@ static void delay_dumps P((void));
 static int promote_highest_priority_incremental P((void));
 static int promote_hills P((void));
 static void output_scheduleline P((disk_t *dp));
+int main P((int, char **));
 
 int main(argc, argv)
 int argc;
 char **argv;
 {
-    disklist_t *origqp;
+    disklist_t origq;
     disk_t *dp;
     int moved_one;
-    char **vp;
     unsigned long malloc_hist_1, malloc_size_1;
     unsigned long malloc_hist_2, malloc_size_2;
     long initial_size;
+    int i;
     char *conffile;
     char *conf_diskfile;
     char *conf_tapelist;
@@ -194,6 +188,9 @@ char **argv;
 
     set_pname("planner");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE);
@@ -206,8 +203,8 @@ char **argv;
 
     fprintf(stderr, "%s: pid %ld executable %s version %s\n",
            get_pname(), (long) getpid(), argv[0], version());
-    for(vp = version_info; *vp != NULL; vp++)
-       fprintf(stderr, "%s: %s", get_pname(), *vp);
+    for (i = 0; version_info[i] != NULL; i++)
+       fprintf(stderr, "%s: %s", get_pname(), version_info[i]);
 
     /*
      * 1. Networking Setup
@@ -218,18 +215,13 @@ char **argv;
      * setuid root.
      */
 
-    /* set up dgram port first thing */
-
-    msg = dgram_alloc();
-
-    if(dgram_bind(msg, &result_port) == -1) {
-       error("could not bind result datagram port: %s", strerror(errno));
-    }
+    protocol_init();
 
     if(geteuid() == 0) {
-       /* set both real and effective uid's to real uid, likewise for gid */
+       uid_t ruid = getuid();
+       setuid(0);
+       seteuid(ruid);
        setgid(getgid());
-       setuid(getuid());
     }
 
     /*
@@ -238,9 +230,8 @@ char **argv;
      * are a valid user.
      */
 
-    if(getpwuid(getuid()) == NULL) {
+    if(getpwuid(getuid()) == NULL)
        error("can't get login name for my uid %ld", (long)getuid());
-    }
 
     /*
      * 2. Read in Configuration Information
@@ -255,21 +246,23 @@ char **argv;
        error("errors processing config file \"%s\"", conffile);
     }
     amfree(conffile);
+
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
        conf_diskfile = stralloc(conf_diskfile);
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((origqp = read_diskfile(conf_diskfile)) == NULL) {
+    if (read_diskfile(conf_diskfile, &origq) < 0) {
        error("could not load disklist \"%s\"", conf_diskfile);
     }
-    match_disklist(origqp, argc-2, argv+2);
-    for(dp = origqp->head; dp != NULL; dp = dp->next) {
+    match_disklist(&origq, argc-2, argv+2);
+    for(dp = origq.head; dp != NULL; dp = dp->next) {
        if(dp->todo)
            log_add(L_DISK, "%s %s", dp->host->hostname, dp->name);
     }
     amfree(conf_diskfile);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
@@ -280,6 +273,7 @@ char **argv;
        error("could not load tapelist \"%s\"", conf_tapelist);
     }
     amfree(conf_tapelist);
+
     conf_infofile = getconf_str(CNF_INFOFILE);
     if (*conf_infofile == '/') {
        conf_infofile = stralloc(conf_infofile);
@@ -292,7 +286,7 @@ char **argv;
     amfree(conf_infofile);
 
     conf_tapetype = getconf_str(CNF_TAPETYPE);
-    conf_maxdumpsize = getconf_int(CNF_MAXDUMPSIZE);
+    conf_maxdumpsize = getconf_am64(CNF_MAXDUMPSIZE);
     conf_runtapes = getconf_int(CNF_RUNTAPES);
     conf_dumpcycle = getconf_int(CNF_DUMPCYCLE);
     conf_runspercycle = getconf_int(CNF_RUNSPERCYCLE);
@@ -338,12 +332,6 @@ char **argv;
     tt_blocksize_kb = tape->blocksize;
     tt_blocksize = tt_blocksize_kb * 1024;
 
-    proto_init(msg->socket, today, 1000); /* XXX handles should eq nhosts */
-
-#ifdef KRB4_SECURITY
-    kerberos_service_init();
-#endif
-
     fprintf(stderr, "%s: time %s: startup took %s secs\n",
                    get_pname(),
                    walltime_str(curclock()),
@@ -357,6 +345,7 @@ char **argv;
      */
 
     fprintf(stderr,"\nSENDING FLUSHES...\n");
+
     if(conf_autoflush) {
        dumpfile_t file;
        sl_t *holding_list;
@@ -401,8 +390,8 @@ char **argv;
     section_start = curclock();
 
     startq.head = startq.tail = NULL;
-    while(!empty(*origqp)) {
-       disk_t *dp = dequeue_disk(origqp);
+    while(!empty(origq)) {
+       disk_t *dp = dequeue_disk(&origq);
        if(dp->todo == 1) {
            setup_estimate(dp);
        }
@@ -477,7 +466,7 @@ char **argv;
     {
        disk_t *dp;
 
-       fprintf(stderr, "INITIAL SCHEDULE (size %ld):\n", total_size);
+       fprintf(stderr, "INITIAL SCHEDULE (size " AM64_FMT "):\n", total_size);
        for(dp = schedq.head; dp != NULL; dp = dp->next) {
            fprintf(stderr, "  %s %s pri %d lev %d size %ld\n",
                    dp->host->hostname, dp->name, est(dp)->dump_priority,
@@ -499,7 +488,7 @@ char **argv;
      */
 
     fprintf(stderr,
-      "\nDELAYING DUMPS IF NEEDED, total_size %ld, tape length %lu mark %lu\n",
+      "\nDELAYING DUMPS IF NEEDED, total_size " AM64_FMT ", tape length " AM64_FMT " mark " AM64_FMT "\n",
            total_size, tape_length, tape_mark);
 
     initial_size = total_size;
@@ -561,7 +550,6 @@ char **argv;
     close_infofile();
     log_add(L_FINISH, "date %s time %s", datestamp, walltime_str(curclock()));
 
-    amfree(msg);
     amfree(datestamp);
     amfree(config_dir);
     amfree(config_name);
@@ -586,6 +574,7 @@ char **argv;
  *
  */
 
+static void askfor P((est_t *, int, int, info_t *));
 static int last_level P((info_t *info));                 /* subroutines */
 static long est_size P((disk_t *dp, int level));
 static long est_tape_size P((disk_t *dp, int level));
@@ -659,7 +648,7 @@ setup_estimate(dp)
 
     /* calculated fields */
 
-    if(info.command & FORCE_FULL) {
+    if (ISSET(info.command, FORCE_FULL)) {
        /* force a level 0, kind of like a new disk */
        if(dp->strategy == DS_NOFULL) {
            /*
@@ -678,8 +667,7 @@ setup_estimate(dp)
                    dp->host->hostname, dp->name);
 
            /* clear force command */
-           if(info.command & FORCE_FULL)
-               info.command ^= FORCE_FULL;
+           CLR(info.command, FORCE_FULL);
            if(put_info(dp->host->hostname, dp->name, &info))
                error("could not put info record for %s:%s: %s",
                      dp->host->hostname, dp->name, strerror(errno));
@@ -726,7 +714,7 @@ setup_estimate(dp)
            }
        }
     }
-    else if(info.command & FORCE_FULL)
+    else if (ISSET(info.command, FORCE_FULL))
        ep->dump_priority += 1;
     /* else XXX bump up the priority of incrementals that failed last night */
 
@@ -736,8 +724,7 @@ setup_estimate(dp)
        if(ep->next_level0 <= 0) {
            /* update the date field */
            info.inf[0].date = today;
-           if(info.command & FORCE_FULL)
-               info.command ^= FORCE_FULL;
+           CLR(info.command, FORCE_FULL);
            ep->next_level0 += conf_dumpcycle;
            ep->last_level = 0;
            if(put_info(dp->host->hostname, dp->name, &info))
@@ -769,6 +756,18 @@ setup_estimate(dp)
        }
     }
 
+    if(dp->strategy == DS_INCRONLY && ep->last_level == -1 && !ISSET(info.command, FORCE_FULL)) {
+       /* don't enqueue the disk */
+       askfor(ep, 0, -1, &info);
+       askfor(ep, 1, -1, &info);
+       askfor(ep, 2, -1, &info);
+       log_add(L_FAIL, "%s %s 19000101 1 [Skipping incronly because no full dump were done]",
+               dp->host->hostname, dp->name);
+       fprintf(stderr,"%s:%s lev 1 skipped due to strategy incronly and no full dump were done\n",
+               dp->host->hostname, dp->name);
+       return;
+    }
+
     /* handle "skip-incr" type archives */
 
     if(dp->skip_incr && ep->next_level0 > 0) {
@@ -810,12 +809,11 @@ setup_estimate(dp)
 
     i = 0;
 
-    if(dp->strategy == DS_NOINC ||
-       (!dp->skip_full &&
-        (!(info.command & FORCE_BUMP) ||
-         dp->skip_incr ||
-         ep->last_level == -1))){
-
+    if (dp->strategy == DS_NOINC ||
+       (!dp->skip_full &&
+        (!ISSET(info.command, FORCE_BUMP) ||
+         dp->skip_incr ||
+         ep->last_level == -1))) {
        if(info.command & FORCE_BUMP && ep->last_level == -1) {
            log_add(L_INFO,
                  "Remove force-bump command of %s:%s because it's a new disk.",
@@ -842,7 +840,7 @@ setup_estimate(dp)
            break;
 
        case DS_INCRONLY:
-           if (info.command & FORCE_FULL)
+           if (ISSET(info.command, FORCE_FULL))
                askfor(ep, i++, 0, &info);
            break;
        }
@@ -860,23 +858,20 @@ setup_estimate(dp)
 
            curr_level = ep->last_level;
 
-           if(info.command & FORCE_NO_BUMP) {
+           if (ISSET(info.command, FORCE_NO_BUMP)) {
                if(curr_level > 0) { /* level 0 already asked for */
                    askfor(ep, i++, curr_level, &info);
                }
                log_add(L_INFO,"Preventing bump of %s:%s as directed.",
                        dp->host->hostname, dp->name);
-           }
-           else if((info.command & FORCE_BUMP)
-                   && curr_level + 1 < DUMP_LEVELS) {
+           } else if (ISSET(info.command, FORCE_BUMP)
+                      && curr_level + 1 < DUMP_LEVELS) {
                askfor(ep, i++, curr_level+1, &info);
                log_add(L_INFO,"Bumping of %s:%s at level %d as directed.",
                        dp->host->hostname, dp->name, curr_level+1);
-           }
-           else if(curr_level == 0) {
+           } else if (curr_level == 0) {
                askfor(ep, i++, 1, &info);
-           }
-           else {
+           } else {
                askfor(ep, i++, curr_level, &info);
                /*
                 * If last time we dumped less than the threshold, then this
@@ -1102,28 +1097,15 @@ double bumpmult;
 
 static void getsize P((am_host_t *hostp));
 static disk_t *lookup_hostdisk P((am_host_t *hp, char *str));
-static void handle_result P((proto_t *p, pkt_t *pkt));
+static void handle_result P((void *datap, pkt_t *pkt, security_handle_t *sech));
 
 
 static void get_estimates P((void))
 {
     am_host_t *hostp;
     disk_t *dp;
-    struct servent *amandad;
     int something_started;
 
-    if((amandad = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL)
-       amanda_port = AMANDA_SERVICE_DEFAULT;
-    else
-       amanda_port = ntohs(amandad->s_port);
-
-#ifdef KRB4_SECURITY
-    if((amandad = getservbyname(KAMANDA_SERVICE_NAME, "udp")) == NULL)
-       kamanda_port = KAMANDA_SERVICE_DEFAULT;
-    else
-       kamanda_port = ntohs(amandad->s_port);
-#endif
-
     something_started = 1;
     while(something_started) {
        something_started = 0;
@@ -1132,7 +1114,7 @@ static void get_estimates P((void))
            if(hostp->up == HOST_READY) {
                something_started = 1;
                getsize(hostp);
-               check_protocol();
+               protocol_check();
                /*
                 * dp is no longer on startq, so dp->next is not valid
                 * and we have to start all over.
@@ -1141,7 +1123,7 @@ static void get_estimates P((void))
            }
        }
     }
-    run_protocol();
+    protocol_run();
 
     while(!empty(waitq)) {
        disk_t *dp = dequeue_disk(&waitq);
@@ -1155,15 +1137,15 @@ static void get_estimates P((void))
        if(est(dp)->level[0] != -1 && est(dp)->est_size[0] < 0) {
            if(est(dp)->est_size[0] == -1) {
                log_add(L_WARNING,
-                       "disk %s:%s, estimate of level %d failed: %lu.",
+                       "disk %s:%s, estimate of level %d failed.",
                        dp->host->hostname, dp->name,
-                       est(dp)->level[0], est(dp)->est_size[0]);
+                       est(dp)->level[0]);
            }
            else {
                log_add(L_WARNING,
-                       "disk %s:%s, estimate of level %d timed out: %lu.",
+                       "disk %s:%s, estimate of level %d timed out.",
                        dp->host->hostname, dp->name,
-                       est(dp)->level[0], est(dp)->est_size[0]);
+                       est(dp)->level[0]);
            }
            est(dp)->level[0] = -1;
        }
@@ -1171,15 +1153,15 @@ static void get_estimates P((void))
        if(est(dp)->level[1] != -1 && est(dp)->est_size[1] < 0) {
            if(est(dp)->est_size[1] == -1) {
                log_add(L_WARNING,
-                       "disk %s:%s, estimate of level %d failed: %lu.",
+                       "disk %s:%s, estimate of level %d failed.",
                        dp->host->hostname, dp->name,
-                       est(dp)->level[1], est(dp)->est_size[1]);
+                       est(dp)->level[1]);
            }
            else {
                log_add(L_WARNING,
-                       "disk %s:%s, estimate of level %d timed out: %lu.",
+                       "disk %s:%s, estimate of level %d timed out.",
                        dp->host->hostname, dp->name,
-                       est(dp)->level[1], est(dp)->est_size[1]);
+                       est(dp)->level[1]);
            }
            est(dp)->level[1] = -1;
        }
@@ -1187,15 +1169,15 @@ static void get_estimates P((void))
        if(est(dp)->level[2] != -1 && est(dp)->est_size[2] < 0) {
            if(est(dp)->est_size[2] == -1) {
                log_add(L_WARNING,
-                       "disk %s:%s, estimate of level %d failed: %lu.",
+                       "disk %s:%s, estimate of level %d failed.",
                        dp->host->hostname, dp->name,
-                       est(dp)->level[2], est(dp)->est_size[2]);
+                       est(dp)->level[2]);
            }
            else {
                log_add(L_WARNING,
-                       "disk %s:%s, estimate of level %d timed out: %lu.",
+                       "disk %s:%s, estimate of level %d timed out.",
                        dp->host->hostname, dp->name,
-                       est(dp)->level[2], est(dp)->est_size[2]);
+                       est(dp)->level[2]);
            }
            est(dp)->level[2] = -1;
        }
@@ -1216,11 +1198,11 @@ static void get_estimates P((void))
 static void getsize(hostp)
 am_host_t *hostp;
 {
-    disklist_t *destqp;
+    char number[NUM_STR_SIZE], *req;
     disk_t *dp;
-    char *req = NULL, *errstr = NULL;
-    int i, estimates, rc, timeout, disk_state, req_len;
-    char number[NUM_STR_SIZE];
+    int i, estimates, timeout, req_len;
+    const security_driver_t *secdrv;
+    char *dumper;
     char *calcsize;
 
     assert(hostp->disks != NULL);
@@ -1236,7 +1218,6 @@ am_host_t *hostp;
      * empty structure.  In either case, we do the disks on the second
      * (and subsequent) pass(es).
      */
-
     if(hostp->features != NULL) { /* sendsize service */
        int nb_client = 0;
        int nb_server = 0;
@@ -1248,7 +1229,7 @@ am_host_t *hostp;
        int has_maxdumps = am_has_feature(hostp->features,
                                          fe_req_options_maxdumps);
 
-       ap_snprintf(number, sizeof(number), "%d", hostp->maxdumps);
+       snprintf(number, sizeof(number), "%d", hostp->maxdumps);
        req = vstralloc("SERVICE ", "sendsize", "\n",
                        "OPTIONS ",
                        has_features ? "features=" : "",
@@ -1268,23 +1249,21 @@ am_host_t *hostp;
        for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
            char *s = NULL;
            int s_len = 0;
-    
+
            if(dp->todo == 0) continue;
 
-           if(est(dp)->state != DISK_READY) {
-               continue;
-           }
+           if(est(dp)->state != DISK_READY) continue;
 
            est(dp)->got_estimate = 0;
            if(est(dp)->level[0] == -1) {
                est(dp)->state = DISK_DONE;
-               continue;   /* ignore this disk */
+               continue;
            }
-    
+
            if(dp->estimate == ES_CLIENT ||
               dp->estimate == ES_CALCSIZE) {
                nb_client++;
-    
+
                for(i = 0; i < MAX_LEVELS; i++) {
                    char *l;
                    char *exclude1 = "";
@@ -1293,11 +1272,11 @@ am_host_t *hostp;
                    char spindle[NUM_STR_SIZE];
                    char level[NUM_STR_SIZE];
                    int lev = est(dp)->level[i];
-    
+
                    if(lev == -1) break;
-    
-                   ap_snprintf(level, sizeof(level), "%d", lev);
-                   ap_snprintf(spindle, sizeof(spindle), "%d", dp->spindle);
+
+                   snprintf(level, sizeof(level), "%d", lev);
+                   snprintf(spindle, sizeof(spindle), "%d", dp->spindle);
                    if(am_has_feature(hostp->features,fe_sendsize_req_options)){
                        exclude1 = " OPTIONS |";
                        exclude2 = optionstr(dp, hostp->features, NULL);
@@ -1315,6 +1294,7 @@ am_host_t *hostp;
                            exclude2 = dp->exclude_list->first->name;
                        }
                    }
+
                    if(dp->estimate == ES_CALCSIZE &&
                       !am_has_feature(hostp->features, fe_calcsize_estimate)) {
                        log_add(L_WARNING,"%s:%s does not support CALCSIZE for estimate, using CLIENT.\n",
@@ -1326,51 +1306,46 @@ am_host_t *hostp;
                    else
                        calcsize = "CALCSIZE ";
 
-                   if(dp->device) {
-                       l = vstralloc(calcsize,
-                                     dp->program,  " ",
-                                     dp->name, " ",
-                                     dp->device, " ",
-                                     level, " ",
-                                     est(dp)->dumpdate[i], " ", spindle,
-                                     exclude1,
-                                     exclude2,
-                                     "\n",
-                                     NULL);
-                   }
-                   else {
-                       l = vstralloc(calcsize,
-                                     dp->program, " ",
-                                     dp->name, " ",
-                                     level, " ",
-                                     est(dp)->dumpdate[i], " ", spindle,
-                                     exclude1,
-                                     exclude2,
-                                     "\n",
-                                     NULL);
+                   if(strncmp(dp->program,"DUMP",4) == 0 || 
+                      strncmp(dp->program,"GNUTAR",6) == 0) {
+                       dumper = "";
+                   } else {
+                       dumper = "DUMPER ";
                    }
-                   amfree(excludefree);
+                   l = vstralloc(calcsize,
+                                 dumper,
+                                 dp->program,
+                                 " ", dp->name,
+                                 " ", dp->device ? dp->device : "",
+                                 " ", level,
+                                 " ", est(dp)->dumpdate[i],
+                                 " ", spindle,
+                                 " ", exclude1, exclude2,
+                                 "\n",
+                                 NULL);
                    strappend(s, l);
                    s_len += strlen(l);
                    amfree(l);
+                   amfree(excludefree);
                }
                /*
                 * Allow 2X for err response.
                 */
-               if(req_len + s_len > MAX_DGRAM / 2) {
+               if(req_len + s_len > MAX_PACKET / 2) {
                    amfree(s);
                    break;
                }
-               estimates += i;
-               strappend(req, s);
-               req_len += s_len;
-               amfree(s);
+               if (s != NULL) {
+                   estimates += i;
+                   strappend(req, s);
+                   req_len += s_len;
+                   amfree(s);
+               }
                est(dp)->state = DISK_ACTIVE;
                remove_disk(&startq, dp);
            }
            else if (dp->estimate == ES_SERVER) {
                info_t info;
-
                nb_server++;
                get_info(dp->host->hostname, dp->name, &info);
                for(i = 0; i < MAX_LEVELS; i++) {
@@ -1405,7 +1380,6 @@ am_host_t *hostp;
                        int nb_day = 0;
                        long est_size_day[NB_DAY];
                        int nb_est_day[NB_DAY];
-
                        for(j=0;j<NB_DAY;j++) {
                            est_size_day[j]=0;
                            nb_est_day[j]=0;
@@ -1414,7 +1388,7 @@ am_host_t *hostp;
                        for(j=NB_HISTORY-2;j>=0;j--) {
                            if(info.history[j].level <= 0) continue;
                            if(info.history[j].size < 0) continue;
-                           if(info.history[j].level == info.history[j+1].level) {
+                           if(info.history[j].level==info.history[j+1].level) {
                                if(nb_day <NB_DAY-1) nb_day++;
                                est_size_day[nb_day] += info.history[j].size;
                                nb_est_day[nb_day]++;
@@ -1430,7 +1404,7 @@ am_host_t *hostp;
 
                        if(nb_est_day[nb_day] > 0) {
                            est(dp)->est_size[i] =
-                                     est_size_day[nb_day] / nb_est_day[nb_day];
+                                   est_size_day[nb_day] / nb_est_day[nb_day];
                        }
                        else if(info.inf[lev].size > 1000) { /* stats */
                            est(dp)->est_size[i] = info.inf[lev].size;
@@ -1462,7 +1436,7 @@ am_host_t *hostp;
                            est(dp)->est_size[i] = 100000;
                        }
                    }
-               }
+               }
                fprintf(stderr,"%s time %s: got result for host %s disk %s:",
                        get_pname(), walltime_str(curclock()),
                        dp->host->hostname, dp->name);
@@ -1475,6 +1449,7 @@ am_host_t *hostp;
                enqueue_disk(&estq, dp);
            }
        }
+
        if(estimates == 0) {
            amfree(req);
            hostp->up = HOST_DONE;
@@ -1499,42 +1474,26 @@ am_host_t *hostp;
        timeout = getconf_int(CNF_CTIMEOUT);
     }
 
-#ifdef KRB4_SECURITY
-    if(hostp->disks->auth == AUTH_KRB4)
-       rc = make_krb_request(hostp->hostname, kamanda_port, req,
-                             hostp, timeout, handle_result);
-    else
-#endif
-       rc = make_request(hostp->hostname, amanda_port, req,
-                         hostp, timeout, handle_result);
-
-    req = NULL;                                        /* do not own this any more */
-
-    if(rc) {
-       errstr = vstralloc("could not resolve hostname \"",
-                          hostp->hostname,
-                          "\"",
-                          NULL);
-       destqp = &failq;
-       hostp->up = HOST_DONE;
-       disk_state = DISK_DONE;
-    }
-    else {
-       errstr = NULL;
-       destqp = &waitq;
-       hostp->up = HOST_ACTIVE;
-       disk_state = DISK_ACTIVE;
+    secdrv = security_getdriver(hostp->disks->security_driver);
+    if (secdrv == NULL) {
+       error("could not find security driver '%s' for host '%s'",
+           hostp->disks->security_driver, hostp->hostname);
     }
+    hostp->up = HOST_ACTIVE;
 
     for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
-       if(dp->todo && est(dp)->state == DISK_ACTIVE) {
-           est(dp)->state = disk_state;
-           est(dp)->errstr = errstr;
-           errstr = NULL;
-           enqueue_disk(destqp, dp);
+       if(dp->todo == 0) {
+           continue;
+       }
+       if(est(dp)->state == DISK_ACTIVE) {
+           est(dp)->errstr = NULL;
+           enqueue_disk(&waitq, dp);
        }
     }
-    amfree(errstr);
+
+    protocol_sendreq(hostp->hostname, secdrv, generic_get_security_conf, 
+       req, timeout, handle_result, hostp);
+    amfree(req);
 }
 
 static disk_t *lookup_hostdisk(hp, str)
@@ -1550,52 +1509,55 @@ char *str;
 }
 
 
-static void handle_result(p, pkt)
-proto_t *p;
+static void handle_result(datap, pkt, sech)
+void *datap;
 pkt_t *pkt;
+security_handle_t *sech;
 {
     int level, i;
     long size;
     disk_t *dp;
     am_host_t *hostp;
     char *msgdisk=NULL, *msgdisk_undo=NULL, msgdisk_undo_ch = '\0';
-    char *errbuf = NULL;
-    char *line;
-    char *fp;
+    char *remoterr, *errbuf = NULL;
     char *s;
     char *t;
+    char *fp;
+    char *line;
     int ch;
     int tch;
 
-    hostp = (am_host_t *) p->datap;
+    hostp = (am_host_t *)datap;
     hostp->up = HOST_READY;
 
-    if(p->state == S_FAILED && pkt == NULL) {
-       if(p->prevstate == S_REPWAIT) {
-           errbuf = vstralloc("Estimate timeout from ", hostp->hostname,
-                              NULL);
-       }
-       else {
-           errbuf = vstralloc("Request to ", hostp->hostname, " timed out.",
-                              NULL);
-       }
+    if (pkt == NULL) {
+       errbuf = vstralloc("Request to ", hostp->hostname, " failed: ", 
+           security_geterror(sech), NULL);
        goto error_return;
     }
-
-#if 0
-    fprintf(stderr, "got %sresponse from %s:\n----\n%s----\n\n",
-           (p->state == S_FAILED) ? "NAK " : "", hostp->hostname, pkt->body);
-#endif
-
-#ifdef KRB4_SECURITY
-    if(hostp->disks->auth == AUTH_KRB4 &&
-       !check_mutual_authenticator(host2key(hostp->hostname), pkt, p)) {
-       errbuf = vstralloc(hostp->hostname,
-                          "[mutual-authentication failed]",
-                          NULL);
-       goto error_return;
+    if (pkt->type == P_NAK) {
+#define sc "ERROR "
+       if(strncmp(pkt->body, sc, sizeof(sc)-1) == 0) {
+           s = pkt->body + sizeof(sc)-1;
+           ch = *s++;
+#undef sc
+       } else {
+           goto NAK_parse_failed;
+       }
+       skip_whitespace(s, ch);
+       if(ch == '\0') goto NAK_parse_failed;
+       remoterr = s - 1;
+       if((s = strchr(remoterr, '\n')) != NULL) {
+           if(s == remoterr) goto NAK_parse_failed;
+               *s = '\0';
+       }
+       if (strcmp(remoterr, "unknown service: noop") != 0
+                  && strcmp(remoterr, "noop: invalid service") != 0) {
+           errbuf = vstralloc(hostp->hostname, " NAK: ", remoterr, NULL);
+           if(s) *s = '\n';
+           goto error_return;
+       }
     }
-#endif
 
     msgdisk_undo = NULL;
     s = pkt->body;
@@ -1647,13 +1609,13 @@ pkt_t *pkt;
             * We can ignore this.
             */
            if(hostp->features == NULL
-              && p->state == S_FAILED
+              && pkt->type == P_NAK
               && (strcmp(t - 1, "unknown service: noop") == 0
                   || strcmp(t - 1, "noop: invalid service") == 0)) {
                continue;
            } else {
                errbuf = vstralloc(hostp->hostname,
-                                  (p->state == S_FAILED) ? "NAK " : "",
+                                  (pkt->type == P_NAK) ? "NAK " : "",
                                   ": ",
                                   fp,
                                   NULL);
@@ -1705,6 +1667,7 @@ pkt_t *pkt;
        hostp->features = am_set_default_feature_set();
     }
 
+
     /* XXX what about disks that only got some estimates...  do we care? */
     /* XXX amanda 2.1 treated that case as a bad msg */
 
@@ -1754,23 +1717,23 @@ pkt_t *pkt;
 
                    if(est(dp)->level[2] != -1 && est(dp)->est_size[2] < 0) {
                        log_add(L_WARNING,
-                               "disk %s:%s, estimate of level %d failed: %lu.",
+                               "disk %s:%s, estimate of level %d failed.",
                                dp->host->hostname, dp->name,
-                               est(dp)->level[2], est(dp)->est_size[2]);
+                               est(dp)->level[2]);
                        est(dp)->level[2] = -1;
                    }
                    if(est(dp)->level[1] != -1 && est(dp)->est_size[1] < 0) {
                        log_add(L_WARNING,
-                               "disk %s:%s, estimate of level %d failed: %lu.",
+                               "disk %s:%s, estimate of level %d failed.",
                                dp->host->hostname, dp->name,
-                               est(dp)->level[1], est(dp)->est_size[1]);
+                               est(dp)->level[1]);
                        est(dp)->level[1] = -1;
                    }
                    if(est(dp)->level[0] != -1 && est(dp)->est_size[0] < 0) {
                        log_add(L_WARNING,
-                               "disk %s:%s, estimate of level %d failed: %lu.",
+                               "disk %s:%s, estimate of level %d failed.",
                                dp->host->hostname, dp->name,
-                               est(dp)->level[0], est(dp)->est_size[0]);
+                               est(dp)->level[0]);
                        est(dp)->level[0] = -1;
                    }
                    enqueue_disk(&estq, dp);
@@ -1795,6 +1758,18 @@ pkt_t *pkt;
     getsize(hostp);
     return;
 
+ NAK_parse_failed:
+
+    /* msgdisk_undo is always NULL */
+    /* if(msgdisk_undo) { */
+    /*         *msgdisk_undo = msgdisk_undo_ch; */
+    /* msgdisk_undo = NULL; */
+    /* } */
+    errbuf = stralloc2(hostp->hostname, " NAK: [NAK parse failed]");
+    fprintf(stderr, "got strange nak from %s:\n----\n%s----\n\n",
+           hostp->hostname, pkt->body);
+    goto error_return;
+
  bad_msg:
 
     if(msgdisk_undo) {
@@ -1802,18 +1777,16 @@ pkt_t *pkt;
        msgdisk_undo = NULL;
     }
     fprintf(stderr,"got a bad message, stopped at:\n");
-    fprintf(stderr,"----\n%s\n----\n\n", line);
+    fprintf(stderr,"----\n%s----\n\n", line);
     errbuf = stralloc2("badly formatted response from ", hostp->hostname);
     /* fall through to ... */
 
  error_return:
 
-    if(msgdisk_undo) {
-       *msgdisk_undo = msgdisk_undo_ch;
-       msgdisk_undo = NULL;
-    }
     i = 0;
     for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
+       if(est(dp)->state != DISK_ACTIVE) continue;
+       est(dp)->state = DISK_DONE;
        if(est(dp)->state == DISK_ACTIVE) {
            est(dp)->state = DISK_DONE;
            remove_disk(&waitq, dp);
@@ -1821,9 +1794,8 @@ pkt_t *pkt;
            i++;
 
            est(dp)->errstr = stralloc(errbuf);
-           fprintf(stderr, "%s: time %s: error result for host %s disk %s: %s\n",
-               get_pname(), walltime_str(curclock()),
-               dp->host->hostname, dp->name, errbuf);
+           fprintf(stderr, "error result for host %s disk %s: %s\n",
+               dp->host->hostname, dp->name, errbuf);
        }
     }
     if(i == 0) {
@@ -1950,7 +1922,7 @@ disk_t *dp;
        balanced_size += lev0size / runs_per_cycle;
     }
 
-    fprintf(stderr,"total size %ld total_lev0 %1.0f balanced-lev0size %1.0f\n",
+    fprintf(stderr,"total size " AM64_FMT " total_lev0 %1.0f balanced-lev0size %1.0f\n",
            total_size, total_lev0, balanced_size);
 }
 
@@ -1987,7 +1959,8 @@ disk_t *dp;
     fprintf(stderr, "%s: FAILED %s %s %s 0 [%s]\n",
        get_pname(), dp->host->hostname, dp->name, datestamp, errstr);
 
-    log_add(L_FAIL, "%s %s %s 0 [%s]", dp->host->hostname, dp->name, datestamp, errstr);
+    log_add(L_FAIL, "%s %s %s 0 [%s]", dp->host->hostname, dp->name, 
+           datestamp, errstr);
 
     /* XXX - memory leak with *dp */
 }
@@ -2110,7 +2083,7 @@ static void delay_dumps P((void))
 {
     disk_t *dp, *ndp, *preserve;
     bi_t *bi, *nbi;
-    long new_total;    /* New total_size */
+    am64_t new_total;  /* New total_size */
     char est_kb[20];     /* Text formatted dump size */
     int nb_forced_level_0;
     info_t info;
@@ -2131,14 +2104,19 @@ static void delay_dumps P((void))
     */
 
     for(dp = schedq.head; dp != NULL; dp = ndp) {
+       int avail_tapes = 1;
+       if (dp->tape_splitsize > 0)
+           avail_tapes = conf_runtapes;
+
        ndp = dp->next; /* remove_disk zaps this */
 
-       if (est(dp)->dump_size == -1 || est(dp)->dump_size <= tape->length) {
+       if (est(dp)->dump_size == -1 ||
+           est(dp)->dump_size <= tape->length * avail_tapes) {
            continue;
        }
 
         /* Format dumpsize for messages */
-       ap_snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
+       snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
 
        if(est(dp)->dump_level == 0) {
            if(dp->skip_incr) {
@@ -2166,7 +2144,7 @@ static void delay_dumps P((void))
            delete = 1;
            message = "skipping incremental";
        }
-       delay_one_dump(dp, delete, "dump larger than tape,", est_kb,
+       delay_one_dump(dp, delete, "dump larger than available tape space,", est_kb,
                       message, NULL);
     }
 
@@ -2207,7 +2185,7 @@ static void delay_dumps P((void))
        if(dp != preserve) {
 
             /* Format dumpsize for messages */
-           ap_snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
+           snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
 
            if(dp->skip_incr) {
                delete = 1;
@@ -2240,7 +2218,7 @@ static void delay_dumps P((void))
            if(est(dp)->dump_level == 0 && dp != preserve) {
 
                /* Format dumpsize for messages */
-               ap_snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
+               snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
 
                if(dp->skip_incr) {
                    delete = 1;
@@ -2280,7 +2258,7 @@ static void delay_dumps P((void))
        if(est(dp)->dump_level != 0) {
 
             /* Format dumpsize for messages */
-           ap_snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
+           snprintf(est_kb, 20, "%ld KB,", est(dp)->dump_size);
 
            delay_one_dump(dp, 1,
                           "dumps way too big,",
@@ -2300,15 +2278,17 @@ static void delay_dumps P((void))
     */
 
     for(bi = biq.tail; bi != NULL; bi = nbi) {
+       int avail_tapes = 1;
        nbi = bi->prev;
        dp = bi->dp;
+       if(dp->tape_splitsize > 0) avail_tapes = conf_runtapes;
 
        if(bi->deleted)
            new_total = total_size + tt_blocksize_kb + bi->size + tape_mark;
        else
            new_total = total_size - est(dp)->dump_size + bi->size;
 
-       if(new_total <= tape_length && bi->size < tape->length) {
+       if(new_total <= tape_length && bi->size < tape->length * avail_tapes) {
            /* reinstate it */
            total_size = new_total;
            if(bi->deleted) {
@@ -2363,7 +2343,7 @@ static void delay_dumps P((void))
        amfree(bi);
     }
 
-    fprintf(stderr, "  delay: Total size now %ld.\n", total_size);
+    fprintf(stderr, "  delay: Total size now " AM64_FMT ".\n", total_size);
 
     return;
 }
@@ -2404,7 +2384,7 @@ arglist_function1(static void delay_one_dump,
     bi->level = est(dp)->dump_level;
     bi->size = est(dp)->dump_size;
 
-    ap_snprintf(level_str, sizeof(level_str), "%d", est(dp)->dump_level);
+    snprintf(level_str, sizeof(level_str), "%d", est(dp)->dump_level);
     bi->errstr = vstralloc(dp->host->hostname,
                           " ", dp->name,
                           " ", datestamp ? datestamp : "?",
@@ -2529,7 +2509,7 @@ static int promote_highest_priority_incremental P((void))
        est(dp)->next_level0 = 0;
 
        fprintf(stderr,
-             "   promote: moving %s:%s up, total_lev0 %1.0f, total_size %ld\n",
+             "   promote: moving %s:%s up, total_lev0 %1.0f, total_size " AM64_FMT "\n",
                dp->host->hostname, dp->name,
                total_lev0, total_size);
 
@@ -2615,7 +2595,7 @@ static int promote_hills P((void))
            est(dp)->dump_size = new_size;
 
            fprintf(stderr,
-                   "   promote: moving %s:%s up, total_lev0 %1.0f, total_size %ld\n",
+                   "   promote: moving %s:%s up, total_lev0 %1.0f, total_size " AM64_FMT "\n",
                    dp->host->hostname, dp->name,
                    total_lev0, total_size);
 
@@ -2693,11 +2673,11 @@ static void output_scheduleline(dp)
     }
 
     if(ep->dump_level == 0 && ep->degr_size != -1) {
-       ap_snprintf(degr_level_str, sizeof(degr_level_str),
+       snprintf(degr_level_str, sizeof(degr_level_str),
                    "%d", ep->degr_level);
-       ap_snprintf(degr_size_str, sizeof(degr_size_str),
+       snprintf(degr_size_str, sizeof(degr_size_str),
                    "%ld", ep->degr_size);
-       ap_snprintf(degr_time_str, sizeof(degr_time_str),
+       snprintf(degr_time_str, sizeof(degr_time_str),
                    "%ld", degr_time);
        degr_str = vstralloc(" ", degr_level_str,
                             " ", degr_date,
@@ -2705,13 +2685,13 @@ static void output_scheduleline(dp)
                             " ", degr_time_str,
                             NULL);
     }
-    ap_snprintf(dump_priority_str, sizeof(dump_priority_str),
+    snprintf(dump_priority_str, sizeof(dump_priority_str),
                "%d", ep->dump_priority);
-    ap_snprintf(dump_level_str, sizeof(dump_level_str),
+    snprintf(dump_level_str, sizeof(dump_level_str),
                "%d", ep->dump_level);
-    ap_snprintf(dump_size_str, sizeof(dump_size_str),
+    snprintf(dump_size_str, sizeof(dump_size_str),
                "%ld", ep->dump_size);
-    ap_snprintf(dump_time_str, sizeof(dump_time_str),
+    snprintf(dump_time_str, sizeof(dump_time_str),
                "%ld", dump_time);
     features = am_feature_to_string(dp->host->features);
     schedline = vstralloc("DUMP ",dp->host->hostname,
index c9c75640545054db7b546872e7db1c26c4dbd44b..43cf3fe6f474f598e1f84a1151398817e48afc07 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: reporter.c,v 1.44.2.17.4.6.2.16.2.10 2005/10/11 14:50:00 martinea Exp $
+ * $Id: reporter.c,v 1.105 2006/03/09 16:51:42 martinea Exp $
  *
  * nightly Amanda Report generator
  */
@@ -70,31 +70,32 @@ typedef struct repdata_s {
     char *datestamp;
     timedata_t taper;
     timedata_t dumper;
+    timedata_t chunker;
     int level;
     struct repdata_s *next;
 } repdata_t;
 
 #define data(dp) ((repdata_t *)(dp)->up)
 
-struct cumulative_stats {
-    int dumpdisks, tapedisks;
+static struct cumulative_stats {
+    int dumpdisks, tapedisks, tapechunks;
     double taper_time, dumper_time;
     double outsize, origsize, tapesize;
     double coutsize, corigsize;                        /* compressed dump only */
 } stats[3];
 
-int dumpdisks[10], tapedisks[10];      /* by-level breakdown of disk count */
+static int dumpdisks[10], tapedisks[10], tapechunks[10];       /* by-level breakdown of disk count */
 
 typedef struct taper_s {
     char *label;
     double taper_time;
     double coutsize, corigsize;
-    int tapedisks;
+  int tapedisks, tapechunks;
     struct taper_s *next;
 } taper_t;
 
-taper_t *stats_by_tape = NULL;
-taper_t *current_tape = NULL;
+static taper_t *stats_by_tape = NULL;
+static taper_t *current_tape = NULL;
 
 typedef struct strange_s {
     char *hostname;
@@ -104,35 +105,35 @@ typedef struct strange_s {
     struct strange_s *next;
 } strange_t;
 
-strange_t *first_strange=NULL, *last_strange=NULL;
+static strange_t *first_strange=NULL, *last_strange=NULL;
 
-float total_time, startup_time, planner_time;
+static float total_time, startup_time, planner_time;
 
 /* count files to tape */
-int tapefcount = 0;
+static int tapefcount = 0;
 
-char *run_datestamp;
-char *today_datestamp;
-char *tape_labels = NULL;
-int last_run_tapes = 0;
+static char *run_datestamp;
+static char *today_datestamp;
+static char *tape_labels = NULL;
+static int last_run_tapes = 0;
 static int degraded_mode = 0; /* defined in driverio too */
-int normal_run = 0;
-int amflush_run = 0;
-int got_finish = 0;
+static int normal_run = 0;
+static int amflush_run = 0;
+static int got_finish = 0;
 
-char *tapestart_error = NULL;
+static char *tapestart_error = NULL;
 
-FILE *logfile, *mailf;
+static FILE *logfile, *mailf;
 
-FILE *postscript;
-char *printer;
+static FILE *postscript;
+static char *printer;
 
-disklist_t *diskq;
-disklist_t sortq;
+static disklist_t diskq;
+static disklist_t sortq;
 
-line_t *errsum = NULL;
-line_t *errdet = NULL;
-line_t *notes = NULL;
+static line_t *errsum = NULL;
+static line_t *errdet = NULL;
+static line_t *notes = NULL;
 
 static char MaxWidthsRequested = 0;    /* determined via config data */
 
@@ -140,41 +141,45 @@ char *displayunit;
 long int unitdivisor;
 
 /* local functions */
-int contline_next P((void));
-void addline P((line_t **lp, char *str));
-void usage P((void));
+static int contline_next P((void));
+static void addline P((line_t **lp, char *str));
+static void usage P((void));
 int main P((int argc, char **argv));
 
-void copy_template_file P((char *lbl_templ));
-void do_postscript_output P((void));
-void handle_start P((void));
-void handle_finish P((void));
-void handle_note P((void));
-void handle_summary P((void));
-void handle_stats P((void));
-void handle_error P((void));
-void handle_disk P((void));
-repdata_t *handle_success P((void));
-void handle_strange P((void));
-void handle_failed P((void));
-void generate_missing P((void));
-void output_tapeinfo P((void));
-void output_lines P((line_t *lp, FILE *f));
-void output_stats P((void));
-void output_summary P((void));
-void output_strange P((void));
-void sort_disks P((void));
-int sort_by_time P((disk_t *a, disk_t *b));
-int sort_by_name P((disk_t *a, disk_t *b));
-void bogus_line P((void));
-char *nicedate P((int datestamp));
+static void copy_template_file P((char *lbl_templ));
+static void do_postscript_output P((void));
+static void handle_start P((void));
+static void handle_finish P((void));
+static void handle_note P((void));
+static void handle_summary P((void));
+static void handle_stats P((void));
+static void handle_error P((void));
+static void handle_disk P((void));
+static repdata_t *handle_success P((logtype_t logtype));
+static repdata_t *handle_chunk P((void));
+static void handle_partial P((void));
+static void handle_strange P((void));
+static void handle_failed P((void));
+static void generate_missing P((void));
+static void output_tapeinfo P((void));
+static void output_lines P((line_t *lp, FILE *f));
+static void output_stats P((void));
+static void output_summary P((void));
+static void output_strange P((void));
+static void sort_disks P((void));
+static int sort_by_name P((disk_t *a, disk_t *b));
+static void bogus_line P((void));
+static char *nicedate P((int datestamp));
 static char *prefix P((char *host, char *disk, int level));
 static char *prefixstrange P((char *host, char *disk, int level, int len_host, int len_disk));
 static void addtostrange P((char *host, char *disk, int level, char *str));
-repdata_t *find_repdata P((disk_t *dp, char *datestamp, int level));
+static repdata_t *find_repdata P((disk_t *dp, char *datestamp, int level));
 
 
-static int ColWidth(int From, int To) {
+static int
+ColWidth(From, To)
+    int From, To;
+{
     int i, Width= 0;
     for (i=From; i<=To && ColumnData[i].Name != NULL; i++) {
        Width+= ColumnData[i].PrefixSpace + ColumnData[i].Width;
@@ -182,7 +187,10 @@ static int ColWidth(int From, int To) {
     return Width;
 }
 
-static char *Rule(int From, int To) {
+static char *
+Rule(From, To)
+    int From, To;
+{
     int i, ThisLeng;
     int Leng= ColWidth(0, ColumnDataCount());
     char *RuleSpace= alloc(Leng+1);
@@ -195,7 +203,11 @@ static char *Rule(int From, int To) {
     return RuleSpace;
 }
 
-static char *TextRule(int From, int To, char *s) {
+static char *
+TextRule(From, To, s)
+    int From, To;
+    char *s;
+{
     ColumnInfo *cd= &ColumnData[From];
     int leng, nbrules, i, txtlength;
     int RuleSpaceSize= ColWidth(0, ColumnDataCount());
@@ -204,8 +216,8 @@ static char *TextRule(int From, int To, char *s) {
     leng= strlen(s);
     if(leng >= (RuleSpaceSize - cd->PrefixSpace))
        leng = RuleSpaceSize - cd->PrefixSpace - 1;
-    ap_snprintf(RuleSpace, RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "", 
-               leng, leng, s);
+    snprintf(RuleSpace, RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "", 
+            leng, leng, s);
     txtlength = cd->PrefixSpace + leng + 1;
     nbrules = ColWidth(From,To) - txtlength;
     for(tmp=RuleSpace + txtlength, i=nbrules ; i>0; tmp++,i--)
@@ -214,21 +226,24 @@ static char *TextRule(int From, int To, char *s) {
     return RuleSpace;
 }
 
-char *sDivZero(float a, float b, int cn) {
+static char *
+sDivZero(a, b, cn)
+    double a, b;
+    int cn;
+{
     ColumnInfo *cd= &ColumnData[cn];
     static char PrtBuf[256];
     if (b == 0.0)
-       ap_snprintf(PrtBuf, sizeof(PrtBuf),
+       snprintf(PrtBuf, sizeof(PrtBuf),
          "%*s", cd->Width, "-- ");
     else
-       ap_snprintf(PrtBuf, sizeof(PrtBuf),
+       snprintf(PrtBuf, sizeof(PrtBuf),
          cd->Format, cd->Width, cd->Precision, a/b);
     return PrtBuf;
 }
 
-
-
-int contline_next()
+static int
+contline_next()
 {
     int ch;
 
@@ -238,9 +253,10 @@ int contline_next()
     return ch == ' ';
 }
 
-void addline(lp, str)
-line_t **lp;
-char *str;
+static void
+addline(lp, str)
+    line_t **lp;
+    char *str;
 {
     line_t *new, *p, *q;
 
@@ -255,14 +271,16 @@ char *str;
     else q->next = new;
 }
 
-void usage()
+static void
+usage()
 {
     error("Usage: amreport conf [-f output-file] [-l logfile] [-p postscript-file]");
 }
 
-int main(argc, argv)
-int argc;
-char **argv;
+int
+main(argc, argv)
+    int argc;
+    char **argv;
 {
     char *conffile;
     char *conf_diskfile;
@@ -284,6 +302,9 @@ char **argv;
 
     set_pname("amreport");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     /* Process options */
@@ -381,7 +402,7 @@ char **argv;
     } else {
        conf_diskfile = stralloc2(config_dir, conf_diskfile);
     }
-    if((diskq = read_diskfile(conf_diskfile)) == NULL) {
+    if(read_diskfile(conf_diskfile, &diskq) < 0) {
        error("could not load disklist \"%s\"", conf_diskfile);
     }
     amfree(conf_diskfile);
@@ -477,7 +498,10 @@ char **argv;
 
        case L_DISK:    handle_disk(); break;
 
-       case L_SUCCESS: handle_success(); break;
+       case L_SUCCESS: handle_success(curlog); break;
+       case L_CHUNKSUCCESS: handle_success(curlog); break;
+       case L_CHUNK:   handle_chunk(); break;
+       case L_PARTIAL: handle_partial(); break;
        case L_STRANGE: handle_strange(); break;
        case L_FAIL:    handle_failed(); break;
 
@@ -689,8 +713,10 @@ char **argv;
            fprintf((fp), "%7.1f",q);       \
     } while(0)
 
-void output_stats()
+static void
+output_stats()
 {
+    double idle_time;
     tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
     int tapesize, marksize, lv, first;
 
@@ -699,6 +725,7 @@ void output_stats()
 
     stats[2].dumpdisks   = stats[0].dumpdisks   + stats[1].dumpdisks;
     stats[2].tapedisks   = stats[0].tapedisks   + stats[1].tapedisks;
+    stats[2].tapechunks  = stats[0].tapechunks  + stats[1].tapechunks;
     stats[2].outsize     = stats[0].outsize     + stats[1].outsize;
     stats[2].origsize    = stats[0].origsize    + stats[1].origsize;
     stats[2].tapesize    = stats[0].tapesize    + stats[1].tapesize;
@@ -710,6 +737,9 @@ void output_stats()
     if(!got_finish)    /* no driver finish line, estimate total run time */
        total_time = stats[2].taper_time + planner_time;
 
+    idle_time = (total_time - startup_time) - stats[2].taper_time;
+    if(idle_time < 0) idle_time = 0.0;
+
     fprintf(mailf,"STATISTICS:\n");
     fprintf(mailf,
            "                          Total       Full      Incr.\n");
@@ -781,11 +811,11 @@ void output_stats()
            mb(stats[1].tapesize));
 
     fprintf(mailf, "Tape Used (%%)             ");
-    divzero(mailf, pct(stats[2].tapesize+marksize*stats[2].tapedisks),tapesize);
+    divzero(mailf, pct(stats[2].tapesize+marksize*(stats[2].tapedisks+stats[2].tapechunks)),tapesize);
     fputs("      ", mailf);
-    divzero(mailf, pct(stats[0].tapesize+marksize*stats[0].tapedisks),tapesize);
+    divzero(mailf, pct(stats[0].tapesize+marksize*(stats[0].tapedisks+stats[0].tapechunks)),tapesize);
     fputs("      ", mailf);
-    divzero(mailf, pct(stats[1].tapesize+marksize*stats[1].tapedisks),tapesize);
+    divzero(mailf, pct(stats[1].tapesize+marksize*(stats[1].tapedisks+stats[1].tapechunks)),tapesize);
 
     if(stats[1].tapedisks > 0) fputs("   (level:#disks ...)", mailf);
     putc('\n', mailf);
@@ -805,6 +835,24 @@ void output_stats()
     }
     putc('\n', mailf);
 
+    if(stats[1].tapechunks > 0) fputs("   (level:#chunks ...)", mailf);
+    putc('\n', mailf);
+
+    fprintf(mailf,
+           "Chunks Taped               %4d       %4d       %4d",
+           stats[2].tapechunks, stats[0].tapechunks, stats[1].tapechunks);
+
+    if(stats[1].tapechunks > 0) {
+       first = 1;
+       for(lv = 1; lv < 10; lv++) if(tapechunks[lv]) {
+           fputs(first?"   (":" ", mailf);
+           first = 0;
+           fprintf(mailf, "%d:%d", lv, tapechunks[lv]);
+       }
+       putc(')', mailf);
+    }
+    putc('\n', mailf);
+
     fprintf(mailf, "Avg Tp Write Rate (k/s) ");
     divzero_wide(mailf, stats[2].tapesize,stats[2].taper_time);
     fputs("    ", mailf);
@@ -816,7 +864,7 @@ void output_stats()
     if(stats_by_tape) {
        int label_length = strlen(stats_by_tape->label) + 5;
        fprintf(mailf,"\nUSAGE BY TAPE:\n");
-       fprintf(mailf,"  %-*s  Time      Size      %%    Nb\n",
+       fprintf(mailf,"  %-*s  Time      Size      %%    Nb    Nc\n",
                label_length, "Label");
        for(current_tape = stats_by_tape; current_tape != NULL;
            current_tape = current_tape->next) {
@@ -824,9 +872,10 @@ void output_stats()
            fprintf(mailf, " %2d:%02d", hrmn(current_tape->taper_time));
            fprintf(mailf, " %8.0f%s  ", du(current_tape->coutsize), displayunit);
            divzero(mailf, pct(current_tape->coutsize + 
-                              marksize * current_tape->tapedisks),
+                              marksize * (current_tape->tapedisks+current_tape->tapechunks)),
                           tapesize);
-           fprintf(mailf, "  %4d\n", current_tape->tapedisks);
+           fprintf(mailf, "  %4d", current_tape->tapedisks);
+           fprintf(mailf, "  %4d\n", current_tape->tapechunks);
        }
     }
 
@@ -834,7 +883,8 @@ void output_stats()
 
 /* ----- */
 
-void output_tapeinfo()
+static void
+output_tapeinfo()
 {
     tape_t *tp, *lasttp;
     int run_tapes;
@@ -864,9 +914,9 @@ void output_tapeinfo()
 
     run_tapes = getconf_int(CNF_RUNTAPES);
 
-    if (run_tapes <= 1)
+    if (run_tapes == 1)
        fputs("The next tape Amanda expects to use is: ", mailf);
-    else
+    else if(run_tapes > 1)
        fprintf(mailf, "The next %d tapes Amanda expects to use are: ",
                run_tapes);
     
@@ -914,7 +964,7 @@ void output_tapeinfo()
 }
 
 /* ----- */
-void output_strange()
+static void output_strange()
 {
     int len_host=0, len_disk=0;
     strange_t *strange;
@@ -933,9 +983,10 @@ void output_strange()
     }
 }
 
-void output_lines(lp, f)
-line_t *lp;
-FILE *f;
+static void
+output_lines(lp, f)
+    line_t *lp;
+    FILE *f;
 {
     line_t *next;
 
@@ -951,14 +1002,9 @@ FILE *f;
 
 /* ----- */
 
-int sort_by_time(a, b)
-disk_t *a, *b;
-{
-    return data(b)->dumper.sec - data(a)->dumper.sec;
-}
-
-int sort_by_name(a, b)
-disk_t *a, *b;
+static int
+sort_by_name(a, b)
+    disk_t *a, *b;
 {
     int rc;
 
@@ -967,13 +1013,14 @@ disk_t *a, *b;
     return rc;
 }
 
-void sort_disks()
+static void
+sort_disks()
 {
     disk_t *dp;
 
     sortq.head = sortq.tail = NULL;
-    while(!empty(*diskq)) {
-       dp = dequeue_disk(diskq);
+    while(!empty(diskq)) {
+       dp = dequeue_disk(&diskq);
        if(data(dp) == NULL) { /* create one */
            find_repdata(dp, run_datestamp, 0);
        }
@@ -981,7 +1028,11 @@ void sort_disks()
     }
 }
 
-void CheckStringMax(ColumnInfo *cd, char *s) {
+static void
+CheckStringMax(cd, s)
+    ColumnInfo *cd;
+    char *s;
+{
     if (cd->MaxWidth) {
        int l= strlen(s);
        if (cd->Width < l)
@@ -989,11 +1040,15 @@ void CheckStringMax(ColumnInfo *cd, char *s) {
     }
 }
 
-void CheckIntMax(ColumnInfo *cd, int n) {
+static void
+CheckIntMax(cd, n)
+    ColumnInfo *cd;
+    int n;
+{
     if (cd->MaxWidth) {
        char testBuf[200];
        int l;
-       ap_snprintf(testBuf, sizeof(testBuf),
+       snprintf(testBuf, sizeof(testBuf),
          cd->Format, cd->Width, cd->Precision, n);
        l= strlen(testBuf);
        if (cd->Width < l)
@@ -1001,11 +1056,15 @@ void CheckIntMax(ColumnInfo *cd, int n) {
     }
 }
 
-void CheckFloatMax(ColumnInfo *cd, double d) {
+static void
+CheckFloatMax(cd, d)
+    ColumnInfo *cd;
+    double d;
+{
     if (cd->MaxWidth) {
        char testBuf[200];
        int l;
-       ap_snprintf(testBuf, sizeof(testBuf),
+       snprintf(testBuf, sizeof(testBuf),
          cd->Format, cd->Width, cd->Precision, d);
        l= strlen(testBuf);
        if (cd->Width < l)
@@ -1024,7 +1083,9 @@ static int DumpRate;
 static int TapeTime;
 static int TapeRate;
 
-void CalcMaxWidth() {
+static void
+CalcMaxWidth()
+{
     /* we have to look for columspec's, that require the recalculation.
      * we do here the same loops over the sortq as is done in
      * output_summary. So, if anything is changed there, we have to
@@ -1046,7 +1107,8 @@ void CalcMaxWidth() {
                repdata->taper.result == L_BOGUS)
                continue;
            CheckIntMax(&ColumnData[Level], repdata->level);
-           if(repdata->dumper.result == L_SUCCESS) {
+            if(repdata->dumper.result == L_SUCCESS || 
+                   repdata->dumper.result == L_CHUNKSUCCESS) {
                CheckFloatMax(&ColumnData[OrigKB], du(repdata->dumper.origsize));
                CheckFloatMax(&ColumnData[OutKB], du(repdata->dumper.outsize));
                if(dp->compress == COMP_NONE)
@@ -1057,10 +1119,10 @@ void CalcMaxWidth() {
                        sDivZero(pct(repdata->dumper.outsize), f, Compress));
 
                if(!amflush_run)
-                   ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+                   snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                                "%3d:%02d", mnsc(repdata->dumper.sec));
                else
-                   ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+                   snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                                "N/A ");
                CheckStringMax(&ColumnData[DumpTime], TimeRateBuffer);
 
@@ -1072,16 +1134,18 @@ void CalcMaxWidth() {
                CheckStringMax(cd, "FAILED");
                continue;
            }
-           if(repdata->taper.result == L_SUCCESS)
-               ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), 
+           if(repdata->taper.result == L_SUCCESS ||
+              repdata->taper.result == L_CHUNKSUCCESS)
+               snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), 
                  "%3d:%02d", mnsc(repdata->taper.sec));
            else
-               ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+               snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                  "N/A ");
            CheckStringMax(cd, TimeRateBuffer);
 
            cd= &ColumnData[TapeRate];
-           if(repdata->taper.result == L_SUCCESS)
+           if(repdata->taper.result == L_SUCCESS ||
+                   repdata->taper.result == L_CHUNKSUCCESS)
                CheckFloatMax(cd, repdata->taper.kps);
            else
                CheckStringMax(cd, "N/A ");
@@ -1090,7 +1154,8 @@ void CalcMaxWidth() {
     }
 }
 
-void output_summary()
+static void
+output_summary()
 {
     disk_t *dp;
     repdata_t *repdata;
@@ -1215,20 +1280,30 @@ void output_summary()
                amfree(tmp);
                continue;
            }
-           if (repdata->dumper.result == L_FAIL) {
+           if (repdata->dumper.result == L_FAIL && (repdata->chunker.result != L_PARTIAL && repdata->taper.result  != L_PARTIAL)) {
                fprintf(mailf, "%s\n",
                        tmp=TextRule(OrigKB, TapeRate, "FAILED"));
                amfree(tmp);
                continue;
            }
 
-           if(repdata->dumper.result == L_SUCCESS)
+           if(repdata->dumper.result == L_SUCCESS ||
+              repdata->dumper.result == L_CHUNKSUCCESS)
                origsize = repdata->dumper.origsize;
-           else
+           else if(repdata->taper.result == L_SUCCESS ||
+                   repdata->taper.result == L_PARTIAL)
                origsize = repdata->taper.origsize;
+           else
+               origsize = repdata->chunker.origsize;
 
-           if(repdata->taper.result == L_SUCCESS) 
+           if(repdata->taper.result == L_SUCCESS ||
+              repdata->taper.result == L_PARTIAL ||
+              repdata->taper.result == L_CHUNKSUCCESS)
                outsize  = repdata->taper.outsize;
+           else if(repdata->chunker.result == L_SUCCESS ||
+                   repdata->chunker.result == L_PARTIAL ||
+                   repdata->chunker.result == L_CHUNKSUCCESS)
+               outsize  = repdata->chunker.outsize;
            else
                outsize  = repdata->dumper.outsize;
 
@@ -1258,17 +1333,19 @@ void output_summary()
 
            cd= &ColumnData[DumpTime];
            fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(repdata->dumper.result == L_SUCCESS)
-               ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+           if(repdata->dumper.result == L_SUCCESS ||
+              repdata->dumper.result == L_CHUNKSUCCESS)
+               snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                  "%3d:%02d", mnsc(repdata->dumper.sec));
            else
-               ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+               snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                  "N/A ");
            fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer);
 
            cd= &ColumnData[DumpRate];
            fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(repdata->dumper.result == L_SUCCESS)
+           if(repdata->dumper.result == L_SUCCESS ||
+                   repdata->dumper.result == L_CHUNKSUCCESS)
                fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->dumper.kps);
            else
                fprintf(mailf, "%*s", cd->Width, "N/A ");
@@ -1282,34 +1359,45 @@ void output_summary()
                continue;
            }
 
-           if(repdata->taper.result == L_SUCCESS)
-               ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+           if(repdata->taper.result == L_SUCCESS || 
+              repdata->taper.result == L_PARTIAL ||
+              repdata->taper.result == L_CHUNKSUCCESS)
+               snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                  "%3d:%02d", mnsc(repdata->taper.sec));
            else
-               ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
+               snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
                  "N/A ");
            fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer);
 
            cd= &ColumnData[TapeRate];
            fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(repdata->taper.result == L_SUCCESS)
+           if(repdata->taper.result == L_SUCCESS || 
+              repdata->taper.result == L_PARTIAL ||
+              repdata->taper.result == L_CHUNKSUCCESS)
                fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->taper.kps);
            else
                fprintf(mailf, "%*s", cd->Width, "N/A ");
+
+           if(repdata->chunker.result == L_PARTIAL ||
+              repdata->taper.result == L_PARTIAL) {
+               fprintf(mailf, " PARTIAL");
+           }
            fputc('\n', mailf);
        }
       }
     }
 }
 
-void bogus_line()
+static void
+bogus_line()
 {
     printf("line %d of log is bogus\n", curlinenum);
 }
 
 
-char *nicedate(datestamp)
-int datestamp;
+static char *
+nicedate(datestamp)
+    int datestamp;
 /*
  * Formats an integer of the form YYYYMMDD into the string
  * "Monthname DD, YYYY".  A pointer to the statically allocated string
@@ -1328,12 +1416,13 @@ int datestamp;
     day   = datestamp % 100;
     month = (datestamp / 100) % 100;
 
-    ap_snprintf(nice, sizeof(nice), "%s %d, %d", months[month], day, year);
+    snprintf(nice, sizeof(nice), "%s %d, %d", months[month], day, year);
 
     return nice;
 }
 
-void handle_start()
+static void
+handle_start()
 {
     static int started = 0;
     char *label;
@@ -1408,6 +1497,7 @@ void handle_start()
        current_tape->coutsize = 0.0;
        current_tape->corigsize = 0.0;
        current_tape->tapedisks = 0;
+       current_tape->tapechunks = 0;
        current_tape->next = NULL;
        tapefcount = 0;
 
@@ -1457,7 +1547,8 @@ void handle_start()
 }
 
 
-void handle_finish()
+static void
+handle_finish()
 {
     char *s;
     int ch;
@@ -1515,7 +1606,8 @@ void handle_finish()
     }
 }
 
-void handle_stats()
+static void
+handle_stats()
 {
     char *s;
     int ch;
@@ -1548,7 +1640,8 @@ void handle_stats()
 }
 
 
-void handle_note()
+static void
+handle_note()
 {
     char *str = NULL;
 
@@ -1560,7 +1653,8 @@ void handle_note()
 
 /* ----- */
 
-void handle_error()
+static void
+handle_error()
 {
     char *s = NULL, *nl;
     int ch;
@@ -1571,23 +1665,22 @@ void handle_error()
 
        skip_whitespace(s, ch);
 #define sc "no-tape"
-       if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
-           bogus_line();
-           return;
-       }
-       s += sizeof(sc)-1;
-       ch = s[-1];
+       if(ch != '\0' && strncmp(s - 1, sc, sizeof(sc)-1) == 0) {
+           s += sizeof(sc)-1;
+           ch = s[-1];
 #undef sc
 
-       skip_whitespace(s, ch);
-       if(ch != '\0') {
-           if((nl = strchr(s - 1, '\n')) != NULL) {
-               *nl = '\0';
+           skip_whitespace(s, ch);
+           if(ch != '\0') {
+               if((nl = strchr(s - 1, '\n')) != NULL) {
+                   *nl = '\0';
+               }
+               tapestart_error = newstralloc(tapestart_error, s - 1);
+               if(nl) *nl = '\n';
+               degraded_mode = 1;
+               return;
            }
-           tapestart_error = newstralloc(tapestart_error, s - 1);
-           if(nl) *nl = '\n';
-           degraded_mode = 1;
-           return;
+           /* else some other tape error, handle like other errors */
        }
        /* else some other tape error, handle like other errors */
     }
@@ -1599,15 +1692,17 @@ void handle_error()
 
 /* ----- */
 
-void handle_summary()
+static void
+handle_summary()
 {
     bogus_line();
 }
 
 /* ----- */
 
-int nb_disk=0;
-void handle_disk()
+static int nb_disk=0;
+static void
+handle_disk()
 {
     disk_t *dp;
     char *s, *fp;
@@ -1620,7 +1715,7 @@ void handle_disk()
     }
 
     if(nb_disk==0) {
-       for(dp = diskq->head; dp != NULL; dp = dp->next)
+       for(dp = diskq.head; dp != NULL; dp = dp->next)
            dp->todo = 0;
     }
     nb_disk++;
@@ -1642,6 +1737,7 @@ void handle_disk()
     skip_whitespace(s, ch);
     if(ch == '\0') {
        bogus_line();
+       amfree(hostname);
        return;
     }
     fp = s - 1;
@@ -1652,7 +1748,7 @@ void handle_disk()
 
     dp = lookup_disk(hostname, diskname);
     if(dp == NULL) {
-       dp = add_disk(hostname, diskname);
+       dp = add_disk(&diskq, hostname, diskname);
     }
 
     amfree(hostname);
@@ -1660,7 +1756,154 @@ void handle_disk()
     dp->todo = 1;
 }
 
-repdata_t *handle_success()
+/* XXX Just a placeholder, in case we decide to do something with L_CHUNK
+ * log entries.  Right now they're just the equivalent of L_SUCCESS, but only
+ * for a split chunk of the overall dumpfile.
+ */
+static repdata_t *
+handle_chunk()
+{
+    disk_t *dp;
+    float sec, kps, kbytes;
+    timedata_t *sp;
+    int i;
+    char *s, *fp;
+    int ch;
+    char *hostname = NULL;
+    char *diskname = NULL;
+    repdata_t *repdata;
+    int level, chunk;
+    char *datestamp;
+    
+    if(curprog != P_TAPER) {
+       bogus_line();
+       return NULL;
+    }
+    
+    s = curstr;
+    ch = *s++;
+    
+    skip_whitespace(s, ch);
+    if(ch == '\0') {
+       bogus_line();
+       return NULL;
+    }
+    fp = s - 1;
+    skip_non_whitespace(s, ch);
+    s[-1] = '\0';
+    hostname = stralloc(fp);
+    s[-1] = ch;
+    
+    skip_whitespace(s, ch);
+    if(ch == '\0') {
+       bogus_line();
+       amfree(hostname);
+       return NULL;
+    }
+    fp = s - 1;
+    skip_non_whitespace(s, ch);
+    s[-1] = '\0';
+    diskname = stralloc(fp);
+    s[-1] = ch;
+    
+    skip_whitespace(s, ch);
+    if(ch == '\0') {
+       bogus_line();
+       amfree(hostname);
+       amfree(diskname);
+       return NULL;
+    }
+    fp = s - 1;
+    skip_non_whitespace(s, ch);
+    s[-1] = '\0';
+    datestamp = stralloc(fp);
+    s[-1] = ch;
+    
+    level = atoi(datestamp);
+    if(level < 100)  {
+       datestamp = newstralloc(datestamp, run_datestamp);
+    }
+    else {
+       skip_whitespace(s, ch);
+       if(ch == '\0' || sscanf(s - 1, "%d", &chunk) != 1) {
+           bogus_line();
+           amfree(hostname);
+           amfree(diskname);
+           amfree(datestamp);
+           return NULL;
+       }
+       skip_integer(s, ch);
+       
+       skip_whitespace(s, ch);
+       if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
+           bogus_line();
+           amfree(hostname);
+           amfree(diskname);
+           amfree(datestamp);
+           return NULL;
+       }
+       skip_integer(s, ch);
+    }
+    skip_whitespace(s, ch);
+    
+    if(level < 0 || level > 9) {
+       amfree(hostname);
+       amfree(diskname);
+       amfree(datestamp);
+       return NULL;
+    }
+    
+    if(sscanf(s - 1,"[sec %f kb %f kps %f", &sec, &kbytes, &kps) != 3)  {
+       bogus_line();
+       amfree(hostname);
+       amfree(diskname);
+       amfree(datestamp);
+       return NULL;
+    }
+    
+    
+    dp = lookup_disk(hostname, diskname);
+    if(dp == NULL) {
+       char *str = NULL;
+       
+       str = vstralloc("  ", prefix(hostname, diskname, level),
+                       " ", "ERROR [not in disklist]",
+                       NULL);
+       addline(&errsum, str);
+       amfree(str);
+       amfree(hostname);
+       amfree(diskname);
+       amfree(datestamp);
+       return NULL;
+    }
+    
+    repdata = find_repdata(dp, datestamp, level);
+    
+    sp = &(repdata->taper);
+    
+    i = level > 0;
+    
+    amfree(hostname);
+    amfree(diskname);
+    amfree(datestamp);
+    
+    if(current_tape == NULL) {
+       error("current_tape == NULL");
+    }
+    if (sp->filenum == 0) {
+       sp->filenum = ++tapefcount;
+       sp->tapelabel = current_tape->label;
+    }
+    tapechunks[level] +=1;
+    stats[i].tapechunks +=1;
+    current_tape->taper_time += sec;
+    current_tape->coutsize += kbytes;
+    current_tape->tapechunks += 1;
+    return repdata;
+}
+
+static repdata_t *
+handle_success(logtype_t logtype)
 {
     disk_t *dp;
     float sec, kps, kbytes, origkb;
@@ -1674,7 +1917,8 @@ repdata_t *handle_success()
     int level;
     char *datestamp;
 
-    if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER) {
+    if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER &&
+       curprog != P_CHUNKER) {
        bogus_line();
        return NULL;
     }
@@ -1733,6 +1977,12 @@ repdata_t *handle_success()
        }
        skip_integer(s, ch);
     }
+    if(level < 0 || level > 9) {
+       amfree(hostname);
+       amfree(diskname);
+       amfree(datestamp);
+       return NULL;
+    }
 
     skip_whitespace(s, ch);
                                /* Planner success messages (for skipped
@@ -1778,7 +2028,9 @@ repdata_t *handle_success()
 
     if(curprog == P_TAPER)
        sp = &(repdata->taper);
-    else sp = &(repdata->dumper);
+    else if(curprog == P_DUMPER)
+       sp = &(repdata->dumper);
+    else sp = &(repdata->chunker);
 
     i = level > 0;
 
@@ -1820,8 +2072,17 @@ repdata_t *handle_success()
        tapedisks[level] +=1;
        stats[i].tapedisks +=1;
        stats[i].tapesize += kbytes;
-       current_tape->taper_time += sec;
-       current_tape->coutsize += kbytes;
+       sp->outsize = kbytes;
+       if(repdata->chunker.outsize == 0.0 && repdata->dumper.outsize != 0.0) { /* dump to tape */
+           stats[i].outsize += kbytes;
+           if(dp->compress != COMP_NONE) {
+               stats[i].coutsize += kbytes;
+           }
+       }
+       if (logtype == L_SUCCESS || logtype== L_PARTIAL) {
+           current_tape->taper_time += sec;
+           current_tape->coutsize += kbytes;
+       }
        current_tape->corigsize += origkb;
        current_tape->tapedisks += 1;
     }
@@ -1832,25 +2093,48 @@ repdata_t *handle_success()
            sp->origsize = kbytes;
        }
        else {
-           stats[i].coutsize += kbytes;
            stats[i].corigsize += sp->origsize;
        }
        dumpdisks[level] +=1;
        stats[i].dumpdisks +=1;
        stats[i].origsize += sp->origsize;
-       stats[i].outsize += kbytes;
     }
 
+    if(curprog == P_CHUNKER) {
+       sp->outsize = kbytes;
+       stats[i].outsize += kbytes;
+       if(dp->compress != COMP_NONE) {
+           stats[i].coutsize += kbytes;
+       }
+    }
     return repdata;
 }
 
-void handle_strange()
+static void
+handle_partial()
+{
+    repdata_t *repdata;
+    timedata_t *sp;
+
+    repdata = handle_success(L_PARTIAL);
+
+    if(curprog == P_TAPER)
+       sp = &(repdata->taper);
+    else if(curprog == P_DUMPER)
+       sp = &(repdata->dumper);
+    else sp = &(repdata->chunker);
+
+    sp->result = L_PARTIAL;
+}
+
+static void
+handle_strange()
 {
     char *str = NULL;
     char *strangestr = NULL;
     repdata_t *repdata;
 
-    repdata = handle_success();
+    repdata = handle_success(L_SUCCESS);
 
     addline(&errdet,"");
     str = vstralloc("/-- ", prefix(repdata->disk->host->hostname, 
@@ -1877,7 +2161,8 @@ void handle_strange()
     amfree(strangestr);
 }
 
-void handle_failed()
+static void
+handle_failed()
 {
     disk_t *dp;
     char *hostname;
@@ -1986,17 +2271,20 @@ void handle_failed()
     return;
 }
 
-void generate_missing()
+
+static void
+generate_missing()
 {
     disk_t *dp;
 
-    for(dp = diskq->head; dp != NULL; dp = dp->next) {
+    for(dp = diskq.head; dp != NULL; dp = dp->next) {
        if(dp->todo && data(dp) == NULL) {
            addtostrange(dp->host->hostname, dp->name, -987, "RESULTS MISSING");
        }
     }
 }
 
+
 static char *
 prefix (host, disk, level)
     char *host;
@@ -2006,7 +2294,7 @@ prefix (host, disk, level)
     char number[NUM_STR_SIZE];
     static char *str = NULL;
 
-    ap_snprintf(number, sizeof(number), "%d", level);
+    snprintf(number, sizeof(number), "%d", level);
     str = newvstralloc(str,
                       " ", host ? host : "(host?)",
                       " ", disk ? disk : "(disk?)",
@@ -2016,6 +2304,7 @@ prefix (host, disk, level)
     return str;
 }
 
+
 static char *
 prefixstrange (host, disk, level, len_host, len_disk)
     char *host;
@@ -2028,7 +2317,7 @@ prefixstrange (host, disk, level, len_host, len_disk)
     char number[NUM_STR_SIZE];
     static char *str = NULL;
 
-    ap_snprintf(number, sizeof(number), "%d", level);
+    snprintf(number, sizeof(number), "%d", level);
     h=malloc(len_host+1);
     if(host) {
        strncpy(h, host, len_host);
@@ -2060,6 +2349,7 @@ prefixstrange (host, disk, level, len_host, len_disk)
     return str;
 }
 
+
 static void
 addtostrange (host, disk, level, str)
     char *host;
@@ -2084,8 +2374,10 @@ addtostrange (host, disk, level, str)
     last_strange = strange;
 }
 
-void copy_template_file(lbl_templ)
-char *lbl_templ;
+
+static void
+copy_template_file(lbl_templ)
+    char *lbl_templ;
 {
   char buf[BUFSIZ];
   int fd;
@@ -2106,6 +2398,7 @@ char *lbl_templ;
                       NULL);
     handle_error();
     amfree(curstr);
+    amfree(lbl_templ);
     afclose(postscript);
     return;
   }
@@ -2120,6 +2413,7 @@ char *lbl_templ;
                         NULL);
       handle_error();
       amfree(curstr);
+      amfree(lbl_templ);
       afclose(postscript);
       return;
     }
@@ -2134,6 +2428,7 @@ char *lbl_templ;
                       NULL);
     handle_error();
     amfree(curstr);
+    amfree(lbl_templ);
     afclose(postscript);
     return;
   }
@@ -2141,10 +2436,11 @@ char *lbl_templ;
   amfree(lbl_templ);
 }
 
-repdata_t *find_repdata(dp, datestamp, level)
-disk_t *dp;
-char *datestamp;
-int level;
+static repdata_t *
+find_repdata(dp, datestamp, level)
+    disk_t *dp;
+    char *datestamp;
+    int level;
 {
     repdata_t *repdata, *prev;
 
@@ -2172,7 +2468,7 @@ int level;
 }
 
 
-void do_postscript_output()
+static void do_postscript_output()
 {
     tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
     disk_t *dp;
@@ -2203,7 +2499,7 @@ void do_postscript_output()
              mb(current_tape->coutsize));
        fprintf(postscript, "(Tape Used (%%)       ");
        divzero(postscript, pct(current_tape->coutsize + 
-                               marksize * current_tape->tapedisks),
+                               marksize * (current_tape->tapedisks + current_tape->tapechunks)),
                                tapesize);
        fprintf(postscript," %%) DrawStat\n");
        fprintf(postscript, "(Compression Ratio:  ");
@@ -2228,17 +2524,20 @@ void do_postscript_output()
                    continue;
                }
 
-               if(repdata->dumper.result == L_SUCCESS)
+               if(repdata->dumper.result == L_SUCCESS ||
+                  repdata->dumper.result == L_PARTIAL)
                    origsize = repdata->dumper.origsize;
                else
                    origsize = repdata->taper.origsize;
 
-               if(repdata->taper.result == L_SUCCESS) 
+               if(repdata->taper.result == L_SUCCESS ||
+                  repdata->taper.result == L_PARTIAL)
                    outsize  = repdata->taper.outsize;
                else
                    outsize  = repdata->dumper.outsize;
 
-               if (repdata->taper.result == L_SUCCESS) {
+               if (repdata->taper.result == L_SUCCESS ||
+                   repdata->taper.result == L_PARTIAL) {
                    if(origsize != 0.0) {
                        fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8.0f) (%8.0f) DrawHost\n",
                            dp->host->hostname, dp->name, repdata->level,
index fff4e6e03cad6ad77543a777c837bb710a8b398c..3e3fceeaafaa8801254f79cac6b0c55dbd44b891 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: server_util.c,v 1.1.2.1.4.2.2.3 2002/04/13 19:24:17 jrjackson Exp $
+ * $Id: server_util.c,v 1.13 2005/10/20 23:18:15 martinea Exp $
  *
  */
 
 #include "token.h"
 
 const char *cmdstr[] = {
-    "BOGUS", "QUIT", "QUITTING", "DONE",
+    "BOGUS", "QUIT", "QUITTING", "DONE", "PARTIAL", 
     "FILE-DUMP", "PORT-DUMP", "CONTINUE", "ABORT",     /* dumper cmds */
     "FAILED", "TRY-AGAIN", "NO-ROOM", "RQ-MORE-DISK",  /* dumper results */
-    "ABORT-FINISHED", "FATAL-TRYAGAIN", "BAD-COMMAND", /* dumper results */
+    "ABORT-FINISHED", "BAD-COMMAND",                   /* dumper results */
     "START-TAPER", "FILE-WRITE", "PORT-WRITE",         /* taper cmds */
-    "PORT", "TAPE-ERROR", "TAPER-OK",                  /* taper results */
+    "PORT", "TAPE-ERROR", "TAPER-OK", "SPLIT-NEEDNEXT", /* taper results */
+    "SPLIT-CONTINUE",
     NULL
 };
 
+
 cmd_t getcmd(cmdargs)
 struct cmdargs *cmdargs;
 {
@@ -67,9 +69,9 @@ struct cmdargs *cmdargs;
 #if DEBUG
     {
        int i;
-       printf("argc = %d\n", cmdargs->argc);
-       for (i = 0; i < cmdargs->argc; i++)
-           printf("argv[%d] = \"%s\"\n", i, cmdargs->argv[i]);
+       fprintf(stderr,"argc = %d\n", cmdargs->argc);
+       for (i = 0; i < cmdargs->argc+1; i++)
+           fprintf(stderr,"argv[%d] = \"%s\"\n", i, cmdargs->argv[i]);
     }
 #endif
 
@@ -93,4 +95,3 @@ printf_arglist_function1(void putresult, cmd_t, result, const char *, format)
     fflush(stdout);
     arglist_end(argp);
 }
-
index 8e66b90e4a9abb3f97fd69f3e00040d46b4c9d2d..324bafc1b5af74f49d3eb876dfcb3cafea63e138 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: server_util.h,v 1.1.2.1.4.2.2.2 2002/04/13 19:24:17 jrjackson Exp $
+ * $Id: server_util.h,v 1.8 2005/10/11 01:17:01 vectro Exp $
  *
  */
 #ifndef SERVER_UTIL_H
 #define MAX_ARGS 32
 
 typedef enum {
-    BOGUS, QUIT, QUITTING, DONE,
+    BOGUS, QUIT, QUITTING, DONE, PARTIAL,
     FILE_DUMP, PORT_DUMP, CONTINUE, ABORT,             /* dumper cmds */
     FAILED, TRYAGAIN, NO_ROOM, RQ_MORE_DISK,           /* dumper results */
-    ABORT_FINISHED, FATAL_TRYAGAIN, BAD_COMMAND,       /* dumper results */
+    ABORT_FINISHED, BAD_COMMAND,                       /* dumper results */
     START_TAPER, FILE_WRITE, PORT_WRITE,               /* taper cmds */
-    PORT, TAPE_ERROR, TAPER_OK,                                /* taper results */
+    PORT, TAPE_ERROR, TAPER_OK,        SPLIT_NEEDNEXT,         /* taper results */
+    SPLIT_CONTINUE,
     LAST_TOK
 } cmd_t;
 extern const char *cmdstr[];
index 6d2b86453cf9667fd21e126deb50436256bf9f72..6cbbd96d203f8555bd6bf88528f3d996c4911c43 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: tapefile.c,v 1.15.2.6.6.7 2003/10/24 13:44:49 martinea Exp $
+ * $Id: tapefile.c,v 1.28 2003/10/24 13:44:35 martinea Exp $
  *
  * routines to read and write the amanda active tape list
  */
index 875ab51e211b2e4111007430f66b09d78df4823f..c9d866aeefea48356f3548d36ee02ac36e7d752e 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: tapefile.h,v 1.6 1998/09/11 23:25:32 jrj Exp $
+ * $Id: tapefile.h,v 1.7 1999/05/14 21:40:21 kashmir Exp $
  *
  * interface for active tape list manipulation routines
  */
@@ -48,7 +48,7 @@ void clear_tapelist P((void));
 tape_t *lookup_tapelabel P((char *label));
 tape_t *lookup_tapepos P((int pos));
 tape_t *lookup_tapedate P((int datestamp));
-int lookup_nb_tape P(());
+int lookup_nb_tape P((void));
 tape_t *lookup_last_reusable_tape P((int skip));
 void remove_tapelabel P((char *label));
 tape_t *add_tapelabel P((int datestamp, char *label));
index 612e822012a86a21be9925ed26e985b85bbb6d4e..aa883eae66d3410a5872b004b790b3174bbf7149 100644 (file)
  * Authors: the Amanda Development Team.  Its members are listed in a
  * file named AUTHORS, in the root directory of this distribution.
  */
-/* $Id: taper.c,v 1.47.2.14.4.8.2.17.2.4 2005/10/11 11:10:20 martinea Exp $
+/* $Id: taper.c,v 1.118 2006/03/17 15:34:12 vectro Exp $
  *
  * moves files from holding disk to tape, or from a socket to tape
  */
 
 #include "amanda.h"
+#include "util.h"
 #include "conffile.h"
 #include "tapefile.h"
 #include "clock.h"
 #include "stream.h"
+#include "holding.h"
 #include "logfile.h"
 #include "tapeio.h"
 #include "changer.h"
 #include "amfeatures.h"
 #include "fileheader.h"
 #include "server_util.h"
+#include "taperscan.c"
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
 #ifdef HAVE_LIBVTBLC
 #include <vtblc.h>
 #include <strings.h>
+#include <math.h>
+
 
 static int vtbl_no   = -1;
 static int len       =  0;
@@ -66,11 +76,32 @@ static vtbl_lbls vtbl_entry[MAX_VOLUMES];
  * XXX advance to next tape first in next_tape
  * XXX label is being read twice?
  */
+long splitsize = 0; /* max size of dumpfile before split (Kb) */
+char *splitbuf = NULL;
+char *splitbuf_wr_ptr = NULL; /* the number of Kb we've written into splitbuf */
+int orig_holdfile = -1;
 
 /* NBUFS replaced by conf_tapebufs */
 /* #define NBUFS               20 */
 int conf_tapebufs;
 
+off_t maxseek = (off_t)1 << ((sizeof(off_t) * 8) - 11);
+
+char *holdfile_path = NULL;
+char *holdfile_path_thischunk = NULL;
+int num_holdfile_chunks = 0;
+dumpfile_t holdfile_hdr;
+dumpfile_t holdfile_hdr_thischunk;
+off_t holdfile_offset_thischunk = (off_t)0;
+int splitbuffer_fd = -1;
+char *splitbuffer_path = NULL;
+
+#define MODE_NONE 0
+#define MODE_FILE_WRITE 1
+#define MODE_PORT_WRITE 2
+
+int mode = MODE_NONE;
+
 /* This is now the number of empties, not full bufs */
 #define THRESHOLD      1
 
@@ -100,15 +131,20 @@ void tape_writer_side P((int rdpipe, int wrpipe));
 char *attach_buffers P((unsigned int size));
 void detach_buffers P((char *bufp));
 void destroy_buffers P((void));
+#define REMOVE_SHARED_MEMORY() \
+    detach_buffers(buffers); \
+    if (strcmp(procname, "reader") == 0) { \
+       destroy_buffers(); \
+    }
 
 /* synchronization pipe routines */
 void syncpipe_init P((int rd, int wr));
-char syncpipe_get P((void));
+char syncpipe_get P((int *intp));
 int  syncpipe_getint P((void));
 char *syncpipe_getstr P((void));
-void syncpipe_put P((int ch));
+void syncpipe_put P((int ch, int intval));
 void syncpipe_putint P((int i));
-void syncpipe_putstr P((char *str));
+void syncpipe_putstr P((const char *str));
 
 /* tape manipulation subsystem */
 int first_tape P((char *new_datestamp));
@@ -116,6 +152,16 @@ int next_tape P((int writerr));
 int end_tape P((int writerr));
 int write_filemark P((void));
 
+/* support crap */
+int seek_holdfile P((int fd, buffer_t *bp, long kbytes));
+
+/* signal handling */
+static void install_signal_handlers P((void));
+static void signal_handler P((int));
+
+/* exit routine */
+static void cleanup P((void));
+
 /*
  * ========================================================================
  * GLOBAL STATE
@@ -132,6 +178,7 @@ int bufdebug = 0;
 
 char *buffers = NULL;
 buffer_t *buftable = NULL;
+int err;
 
 char *procname = "parent";
 
@@ -149,6 +196,14 @@ long buffer_size;
 int tt_file_pad;
 static unsigned long malloc_hist_1, malloc_size_1;
 static unsigned long malloc_hist_2, malloc_size_2;
+dumpfile_t file;
+dumpfile_t *save_holdfile = NULL;
+long cur_span_chunkstart = 0; /* start of current split dump chunk (Kb) */
+char *holdfile_name;
+int num_splits = 0;
+int expected_splits = 0;
+int num_holdfiles = 0;
+times_t curdump_rt;
 
 am_feature_t *their_features = NULL;
 
@@ -180,6 +235,9 @@ char **main_argv;
 
     set_pname("taper");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     fprintf(stderr, "%s: pid %ld executable %s version %s\n",
@@ -205,6 +263,9 @@ char **main_argv;
 
     safe_cd();
 
+    install_signal_handlers();
+    atexit(cleanup);
+
     /* print prompts and debug messages if running interactive */
 
     interactive = (main_argc > 1 && strcmp(main_argv[1],"-t") == 0);
@@ -351,12 +412,133 @@ char **main_argv;
  * FILE READER SIDE
  *
  */
-void read_file P((int fd, char *handle,
+int read_file P((int fd, char *handle,
                  char *host, char *disk, char *datestamp, 
-                 int level, int port_flag));
+                 int level));
 int taper_fill_buffer P((int fd, buffer_t *bp, int buflen));
 void dumpbufs P((char *str1));
 void dumpstatus P((buffer_t *bp));
+int get_next_holding_file P((int fd, buffer_t *bp, char *strclosing, int rc));
+int predict_splits P((char *filename));
+void create_split_buffer P((char *split_diskbuffer, long fallback_splitsize, char *id_string));
+void free_split_buffer P(());
+
+
+/*
+ * Create a buffer, either in an mmapped file or in memory, where PORT-WRITE
+ * dumps can buffer the current split chunk in case of retry.
+ */
+void create_split_buffer(split_diskbuffer, fallback_splitsize, id_string)
+char *split_diskbuffer;
+long fallback_splitsize;
+char *id_string;
+{
+    char *buff_err = NULL;
+    void *nulls = NULL;
+    int c;
+    
+    /* don't bother if we're not actually splitting */
+    if(splitsize <= 0){
+       splitbuf = NULL;
+       splitbuf_wr_ptr = NULL;
+       return;
+    }
+
+#ifdef HAVE_MMAP
+#ifdef HAVE_SYS_MMAN_H
+    if(strcmp(split_diskbuffer, "NULL")){
+       splitbuffer_path = vstralloc(split_diskbuffer,
+                                    "/splitdump_buffer_XXXXXX",
+                                    NULL);
+#ifdef HAVE_MKSTEMP
+       splitbuffer_fd = mkstemp(splitbuffer_path);
+#else
+       log_add(L_INFO, "mkstemp not available, using plain open() for split buffer- make sure %s has safe permissions", split_diskbuffer);
+       splitbuffer_fd = open(splitbuffer_path, O_RDWR|O_CREAT, 0600);
+#endif
+       if(splitbuffer_fd == -1){
+           buff_err = newvstralloc(buff_err, "mkstemp/open of ", 
+                                   splitbuffer_path, "failed (",
+                                   strerror(errno), ")", NULL);
+           goto fallback;
+       }
+       nulls = alloc(1024); /* lame */
+       memset(nulls, 0, 1024);
+       for(c = 0; c < splitsize ; c++) {
+           if(fullwrite(splitbuffer_fd, nulls, 1024) < 1024){
+               buff_err = newvstralloc(buff_err, "write to ", splitbuffer_path,
+                                       "failed (", strerror(errno), ")", NULL);
+               free_split_buffer();
+               goto fallback;
+           }
+       }
+       amfree(nulls);
+
+        splitbuf = mmap(NULL, (size_t)splitsize*1024, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, splitbuffer_fd, (off_t)0);
+       if(splitbuf == (char*)-1){
+           buff_err = newvstralloc(buff_err, "mmap failed (", strerror(errno),
+                                   ")", NULL);
+           free_split_buffer();
+           goto fallback;
+       }
+       fprintf(stderr,
+               "taper: r: buffering %ldkb split chunks in mmapped file %s\n",
+               splitsize, splitbuffer_path);
+       splitbuf_wr_ptr = splitbuf;
+       return;
+    }
+    else{
+       buff_err = stralloc("no split_diskbuffer specified");
+    }
+#else
+    buff_err = stralloc("mman.h not available");
+    goto fallback;
+#endif
+#else
+    buff_err = stralloc("mmap not available");
+    goto fallback;
+#endif
+
+    /*
+      Buffer split dumps in memory, if we can't use a file.
+    */
+    fallback:
+        splitsize = fallback_splitsize;
+       log_add(L_INFO,
+               "%s: using fallback split size of %dkb to buffer %s in-memory",
+               buff_err, splitsize, id_string);
+       splitbuf = alloc(splitsize * 1024);
+       splitbuf_wr_ptr = splitbuf;
+}
+
+/*
+ * Free up resources that create_split_buffer eats.
+ */
+void free_split_buffer()
+{
+    if(splitbuffer_fd != -1){
+#ifdef HAVE_MMAP
+#ifdef HAVE_SYS_MMAN_H
+       if(splitbuf != NULL) munmap(splitbuf, splitsize);
+#endif
+#endif
+       aclose(splitbuffer_fd);
+       splitbuffer_fd = -1;
+
+       if(unlink(splitbuffer_path) == -1){
+           log_add(L_WARNING, "Failed to unlink %s: %s",
+                   splitbuffer_path, strerror(errno));
+       }
+       amfree(splitbuffer_path);
+       splitbuffer_path = NULL;
+    }
+    else if(splitbuf){
+       amfree(splitbuf);
+       splitbuf = NULL;
+    }
+}
+
 
 void file_reader_side(rdpipe, wrpipe)
 int rdpipe, wrpipe;
@@ -369,12 +551,17 @@ int rdpipe, wrpipe;
     char *diskname = NULL;
     char *result = NULL;
     char *datestamp = NULL;
+    char *split_diskbuffer = NULL;
+    char *id_string = NULL;
     char tok;
     char *q = NULL;
     int level, fd, data_port, data_socket, wpid;
+    char level_str[64];
     struct stat stat_file;
     int tape_started;
     int a;
+    long fallback_splitsize = 0;
+    int tmpint;
 
     procname = "reader";
     syncpipe_init(rdpipe, wrpipe);
@@ -394,12 +581,12 @@ int rdpipe, wrpipe;
     taper_datestamp = newstralloc(taper_datestamp, cmdargs.argv[2]);
 
     tape_started = 0;
-    syncpipe_put('S');
+    syncpipe_put('S', 0);
     syncpipe_putstr(taper_datestamp);
 
     /* get result of start command */
 
-    tok = syncpipe_get();
+    tok = syncpipe_get(&tmpint);
     switch(tok) {
     case 'S':
        putresult(TAPER_OK, "\n");
@@ -412,9 +599,9 @@ int rdpipe, wrpipe;
        q = squotef("[%s]", result ? result : "(null)");
        putresult(TAPE_ERROR, "%s\n", q);
        amfree(q);
-       log_add(L_ERROR,"no-tape [%s]", result);
+       log_add(L_ERROR,"no-tape [%s]", "No writable valid tape found");
        amfree(result);
-       syncpipe_put('e');                      /* ACK error */
+       syncpipe_put('e', 0);                   /* ACK error */
        break;
     default:
        error("expected 'S' or 'E' for START-TAPER, got '%c'", tok);
@@ -440,7 +627,10 @@ int rdpipe, wrpipe;
             *   diskname
             *   level
             *   datestamp
+            *   splitsize
+            *   split_diskbuffer
             */
+           mode = MODE_PORT_WRITE;
            cmdargs.argc++;                     /* true count of args */
            a = 2;
 
@@ -475,15 +665,35 @@ int rdpipe, wrpipe;
            }
            datestamp = newstralloc(datestamp, cmdargs.argv[a++]);
 
+           if(a >= cmdargs.argc) {
+               error("error [taper PORT-WRITE: not enough args: splitsize]");
+           }
+           splitsize = atoi(cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [taper PORT-WRITE: not enough args: split_diskbuffer]");
+           }
+           split_diskbuffer = newstralloc(split_diskbuffer, cmdargs.argv[a++]);
+
+           if(a >= cmdargs.argc) {
+               error("error [taper PORT-WRITE: not enough args: fallback_splitsize]");
+           }
+           fallback_splitsize = atoi(cmdargs.argv[a++]);
+
            if(a != cmdargs.argc) {
                error("error [taper file_reader_side PORT-WRITE: too many args: %d != %d]",
                      cmdargs.argc, a);
            }
 
+           snprintf(level_str, sizeof(level_str), "%d", level);
+           id_string = newvstralloc(id_string, hostname, ":", diskname, ".",
+                                    level_str, NULL);
+
+           create_split_buffer(split_diskbuffer, fallback_splitsize, id_string);
+           amfree(id_string);
+
            data_port = 0;
-           data_socket = stream_server(&data_port,
-                                       -1,
-                                       STREAM_BUFSIZE);        
+           data_socket = stream_server(&data_port, -1, STREAM_BUFSIZE);        
            if(data_socket < 0) {
                char *m;
 
@@ -494,6 +704,7 @@ int rdpipe, wrpipe;
                q = squote(m);
                putresult(TAPE_ERROR, "%s %s\n", handle, q);
                amfree(m);
+               amfree(q);
                break;
            }
            putresult(PORT, "%d\n", data_port);
@@ -503,10 +714,15 @@ int rdpipe, wrpipe;
                q = squote("[port connect timeout]");
                putresult(TAPE_ERROR, "%s %s\n", handle, q);
                aclose(data_socket);
+               amfree(q);
                break;
            }
-           read_file(fd, handle, hostname, diskname, datestamp, level, 1);
+           expected_splits = -1;
+
+           while(read_file(fd,handle,hostname,diskname,datestamp,level));
+
            aclose(data_socket);
+           free_split_buffer();
            break;
 
        case FILE_WRITE:
@@ -519,7 +735,9 @@ int rdpipe, wrpipe;
             *   diskname
             *   level
             *   datestamp
+            *   splitsize
             */
+           mode = MODE_FILE_WRITE;
            cmdargs.argc++;                     /* true count of args */
            a = 2;
 
@@ -559,22 +777,49 @@ int rdpipe, wrpipe;
            }
            datestamp = newstralloc(datestamp, cmdargs.argv[a++]);
 
+           if(a >= cmdargs.argc) {
+               error("error [taper FILE-WRITE: not enough args: splitsize]");
+           }
+           splitsize = atoi(cmdargs.argv[a++]);
+
            if(a != cmdargs.argc) {
                error("error [taper file_reader_side FILE-WRITE: too many args: %d != %d]",
                      cmdargs.argc, a);
            }
+           if(holdfile_name != NULL) {
+               filename = newstralloc(filename, holdfile_name);
+           }
 
-           if(stat(filename,&stat_file)!=0) {
+           if((expected_splits = predict_splits(filename)) < 0) {
+               break;
+           }
+           if(stat(filename, &stat_file)!=0) {
                q = squotef("[%s]", strerror(errno));
                putresult(TAPE_ERROR, "%s %s\n", handle, q);
+               amfree(q);
                break;
            }
            if((fd = open(filename, O_RDONLY)) == -1) {
                q = squotef("[%s]", strerror(errno));
                putresult(TAPE_ERROR, "%s %s\n", handle, q);
+               amfree(q);
                break;
            }
-           read_file(fd, handle, hostname, diskname, datestamp, level, 0);
+           holdfile_path = stralloc(filename);
+           holdfile_path_thischunk = stralloc(filename);
+           holdfile_offset_thischunk = (off_t)0;
+
+           while(read_file(fd,handle,hostname,diskname,datestamp,level)){
+               if(splitsize > 0 && holdfile_path_thischunk)
+                   filename = newstralloc(filename, holdfile_path_thischunk);
+               if((fd = open(filename, O_RDONLY)) == -1) {
+                   q = squotef("[%s]", strerror(errno));
+                   putresult(TAPE_ERROR, "%s %s\n", handle, q);
+                   amfree(q);
+                   break;
+               }
+           }
+
            break;
 
        case QUIT:
@@ -582,7 +827,7 @@ int rdpipe, wrpipe;
            fprintf(stderr,"taper: DONE [idle wait: %s secs]\n",
                    walltime_str(total_wait));
            fflush(stderr);
-           syncpipe_put('Q');  /* tell writer we're exiting gracefully */
+           syncpipe_put('Q', 0);       /* tell writer we're exiting gracefully */
            aclose(wrpipe);
 
            if((wpid = wait(NULL)) != writerpid) {
@@ -592,15 +837,17 @@ int rdpipe, wrpipe;
                fflush(stderr);
            }
 
-           detach_buffers(buffers);
-           destroy_buffers();
-           amfree(datestamp);
+           if (datestamp != NULL)
+               amfree(datestamp);
            amfree(label);
            amfree(errstr);
            amfree(changer_resultstr);
            amfree(tapedev);
+           amfree(conf_tapelist);
+           amfree(filename);
            amfree(config_dir);
            amfree(config_name);
+           if(holdfile_name != NULL) amfree(holdfile_name);
 
            malloc_size_2 = malloc_inuse(&malloc_hist_2);
 
@@ -619,14 +866,15 @@ int rdpipe, wrpipe;
                q = stralloc("(no input?)");
            }
            putresult(BAD_COMMAND, "%s\n", q);
+           amfree(q);
            break;
        }
     }
-    amfree(q);
     amfree(handle);
-    amfree(filename);
+    am_release_feature_set(their_features);
     amfree(hostname);
     amfree(diskname);
+    fprintf(stderr, "TAPER AT END OF READER SIDE\n");
 }
 
 void dumpbufs(str1)
@@ -666,15 +914,15 @@ buffer_t *bp;
 
     pn[0] = procname[0];
     pn[1] = '\0';
-    ap_snprintf(bt, sizeof(bt), "%d", (int)(bp-buftable));
+    snprintf(bt, sizeof(bt), "%d", (int)(bp-buftable));
 
     switch(bp->status) {
-    case FULL:         ap_snprintf(status, sizeof(status), "F%d", bp->size);
+    case FULL:         snprintf(status, sizeof(status), "F%d", bp->size);
                        break;
     case FILLING:      status[0] = 'f'; status[1] = '\0'; break;
     case EMPTY:                status[0] = 'E'; status[1] = '\0'; break;
     default:
-       ap_snprintf(status, sizeof(status), "%ld", bp->status);
+       snprintf(status, sizeof(status), "%ld", bp->status);
        break;
     }
 
@@ -683,21 +931,115 @@ buffer_t *bp;
     amfree(str);
 }
 
+/*
+  Handle moving to the next chunk of holding file, if any.  Returns -1 for
+  errors, 0 if there's no more file, or a positive integer for the amount of
+  stuff read that'll go into 'rc' (XXX That's fugly, maybe that should just
+  be another global.  What is rc anyway, 'read count?' I keep thinking it
+  should be 'return code')
+*/
+int get_next_holding_file(fd, bp, strclosing, rc)
+     int fd;
+     buffer_t *bp;
+     char *strclosing;
+{
+    int save_fd, rc1;
+    struct stat stat_file;
+    int ret = -1;
+    
+    save_fd = fd;
+    close(fd);
+    
+    /* see if we're fresh out of file */
+    if(file.cont_filename[0] == '\0') {
+       err = 0;
+       ret = 0;
+    } else if(stat(file.cont_filename, &stat_file) != 0) {
+       err = errno;
+       ret = -1;
+       strclosing = newvstralloc(strclosing,"can't stat: ",file.cont_filename,NULL);
+    } else if((fd = open(file.cont_filename,O_RDONLY)) == -1) {
+       err = errno;
+       ret = -1;
+       strclosing = newvstralloc(strclosing,"can't open: ",file.cont_filename,NULL);
+    } else if((fd != save_fd) && dup2(fd, save_fd) == -1) {
+       err = errno;
+       ret = -1;
+       strclosing = newvstralloc(strclosing,"can't dup2: ",file.cont_filename,NULL);
+    } else {
+       buffer_t bp1;
+       holdfile_path = stralloc(file.cont_filename);
+       
+       fprintf(stderr, "taper: r: switching to next holding chunk '%s'\n", file.cont_filename); 
+       num_holdfile_chunks++;
+       
+       bp1.status = EMPTY;
+       bp1.size = DISK_BLOCK_BYTES;
+       bp1.buffer = malloc(DISK_BLOCK_BYTES);
+       
+       if(fd != save_fd) {
+           close(fd);
+           fd = save_fd;
+       }
+       
+       rc1 = taper_fill_buffer(fd, &bp1, DISK_BLOCK_BYTES);
+       if(rc1 <= 0) {
+           amfree(bp1.buffer);
+           err = (rc1 < 0) ? errno : 0;
+           ret = -1;
+           strclosing = newvstralloc(strclosing,
+                                     "Can't read header: ",
+                                     file.cont_filename,
+                                     NULL);
+       } else {
+           parse_file_header(bp1.buffer, &file, rc1);
+           
+           amfree(bp1.buffer);
+           bp1.buffer = bp->buffer + rc;
+           
+           rc1 = taper_fill_buffer(fd, &bp1, tt_blocksize - rc);
+           if(rc1 <= 0) {
+               err = (rc1 < 0) ? errno : 0;
+               ret = -1;
+               if(rc1 < 0) {
+                   strclosing = newvstralloc(strclosing,
+                                             "Can't read data: ",
+                                             file.cont_filename,
+                                             NULL);
+               }
+           }
+           else {
+               ret = rc1;
+               num_holdfiles++;
+           }
+       }
+    }
+    
+    return(ret);
+}
+
 
-void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
-    int fd, level, port_flag;
+int read_file(fd, handle, hostname, diskname, datestamp, level)
+    int fd, level;
     char *handle, *hostname, *diskname, *datestamp;
 {
     buffer_t *bp;
     char tok;
-    int rc, err, opening, closing, bufnum, need_closing;
+    int rc, opening, closing, bufnum, need_closing, nexting;
     long filesize;
     times_t runtime;
     char *strclosing = NULL;
+    char seekerrstr[STR_SIZE];
     char *str;
-    int header_read = 0;
+    int header_written = 0;
     int buflen;
-    dumpfile_t file;
+    dumpfile_t first_file;
+    dumpfile_t cur_holdfile;
+    long kbytesread = 0;
+    int header_read = 0;
+    char *cur_filename = NULL;
+    int retry_from_splitbuf = 0;
+    char *splitbuf_rd_ptr = NULL;
 
     char *q = NULL;
 
@@ -713,8 +1055,18 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
     filesize = 0;
     closing = 0;
     need_closing = 0;
+    nexting = 0;
     err = 0;
+
+    /* don't break this if we're still on the same file as a previous init */
+    if(cur_span_chunkstart <= 0){
     fh_init(&file);
+      header_read = 0;
+    }
+    else if(mode == MODE_FILE_WRITE){
+      memcpy(&file, save_holdfile, sizeof(dumpfile_t));
+      memcpy(&cur_holdfile, save_holdfile, sizeof(dumpfile_t));
+    }
 
     if(bufdebug) {
        fprintf(stderr, "taper: r: start file\n");
@@ -728,46 +1080,78 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
     bp = buftable;
     if(interactive || bufdebug) dumpstatus(bp);
 
+    if(cur_span_chunkstart >= 0 && splitsize > 0){
+        /* We're supposed to start at some later part of the file, not read the
+          whole thing. "Seek" forward to where we want to be. */
+       if(label) putresult(SPLIT_CONTINUE, "%s %s\n", handle, label);
+        if(mode == MODE_FILE_WRITE && cur_span_chunkstart > 0){
+           fprintf(stderr, "taper: r: seeking %s to " OFF_T_FMT " kb\n",
+                           holdfile_path_thischunk, holdfile_offset_thischunk);
+           fflush(stderr);
+
+           if(holdfile_offset_thischunk > maxseek){
+             snprintf(seekerrstr, sizeof(seekerrstr), "Can't seek by " OFF_T_FMT " kb (compiled for %d-bit file offsets), recompile with large file support or set holdingdisk chunksize to <%ld Mb", holdfile_offset_thischunk, (int)(sizeof(off_t) * 8), (long)(maxseek/1024));
+             log_add(L_ERROR, "%s", seekerrstr);
+             fprintf(stderr, "taper: r: FATAL: %s\n", seekerrstr);
+             fflush(stderr);
+             syncpipe_put('X', 0);
+             return -1;
+           }
+           if(lseek(fd, holdfile_offset_thischunk*1024, SEEK_SET) == (off_t)-1){
+             fprintf(stderr, "taper: r: FATAL: seek_holdfile lseek error while seeking into %s by " OFF_T_FMT "kb: %s\n", holdfile_path_thischunk, holdfile_offset_thischunk, strerror(errno));
+             fflush(stderr);
+             syncpipe_put('X', 0);
+             return -1;
+           }
+        }
+        else if(mode == MODE_PORT_WRITE){
+           fprintf(stderr, "taper: r: re-reading split dump piece from buffer\n");
+           fflush(stderr);
+           retry_from_splitbuf = 1;
+           splitbuf_rd_ptr = splitbuf;
+           if(splitbuf_rd_ptr >= splitbuf_wr_ptr) retry_from_splitbuf = 0;
+        }
+        if(cur_span_chunkstart > 0) header_read = 1; /* really initialized in prior run */
+    }
+
     /* tell writer to open tape */
 
     opening = 1;
-    syncpipe_put('O');
+    syncpipe_put('O', 0);
     syncpipe_putstr(datestamp);
     syncpipe_putstr(hostname);
     syncpipe_putstr(diskname);
     syncpipe_putint(level);
 
     startclock();
-
+    
     /* read file in loop */
-
+    
     while(1) {
-       tok = syncpipe_get();
+       tok = syncpipe_get(&bufnum);
        switch(tok) {
-
+           
        case 'O':
            assert(opening);
            opening = 0;
            err = 0;
            break;
-
+           
        case 'R':
-           bufnum = syncpipe_getint();
-
            if(bufdebug) {
                fprintf(stderr, "taper: r: got R%d\n", bufnum);
                fflush(stderr);
            }
-
+           
            if(need_closing) {
-               syncpipe_put('C');
+               syncpipe_put('C', 0);
                closing = 1;
                need_closing = 0;
                break;
            }
-
+           
            if(closing) break;  /* ignore extra read tokens */
-
+           
            assert(!opening);
            if(bp->status != EMPTY || bufnum != bp-buftable) {
                /* XXX this SHOULD NOT HAPPEN.  Famous last words. */
@@ -790,167 +1174,207 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
                if(bp->status == EMPTY)
                    fprintf(stderr, "taper: result now correct!\n");
                fflush(stderr);
-
+               
                errstr = newstralloc(errstr,
                                     "[fatal buffer mismanagement bug]");
                q = squote(errstr);
                putresult(TRYAGAIN, "%s %s\n", handle, q);
+               cur_span_chunkstart = 0;
                amfree(q);
                log_add(L_INFO, "retrying %s:%s.%d on new tape due to: %s",
                        hostname, diskname, level, errstr);
                closing = 1;
-               syncpipe_put('X');      /* X == buffer snafu, bail */
+               syncpipe_put('X', 0);   /* X == buffer snafu, bail */
                do {
-                   tok = syncpipe_get();
-                   if(tok == 'R')
-                       bufnum = syncpipe_getint();
+                   tok = syncpipe_get(&bufnum);
                } while(tok != 'x');
                aclose(fd);
-               return;
-           }
+               return -1;
+           } /* end 'if (bf->status != EMPTY || bufnum != bp-buftable)' */
 
            bp->status = FILLING;
            buflen = header_read ? tt_blocksize : DISK_BLOCK_BYTES;
            if(interactive || bufdebug) dumpstatus(bp);
-           if((rc = taper_fill_buffer(fd, bp, buflen)) < 0) {
-               err = errno;
-               closing = 1;
-               strclosing = newvstralloc(strclosing,"Can't read data: ",NULL);
-               syncpipe_put('C');
-           } else {
-               if(rc < buflen) { /* switch to next file */
-                   int save_fd;
-                   struct stat stat_file;
-
-                   save_fd = fd;
-                   close(fd);
-                   if(file.cont_filename[0] == '\0') { /* no more file */
-                       err = 0;
-                       need_closing = 1;
-                   } else if(stat(file.cont_filename, &stat_file) != 0) {
-                       err = errno;
-                       need_closing = 1;
-                       strclosing = newvstralloc(strclosing,"can't stat: ",file.cont_filename,NULL);
-                   } else if((fd = open(file.cont_filename,O_RDONLY)) == -1) {
-                       err = errno;
-                       need_closing = 1;
-                       strclosing = newvstralloc(strclosing,"can't open: ",file.cont_filename,NULL);
-                   } else if((fd != save_fd) && dup2(fd, save_fd) == -1) {
-                       err = errno;
-                       need_closing = 1;
-                       strclosing = newvstralloc(strclosing,"can't dup2: ",file.cont_filename,NULL);
-                   } else {
-                       buffer_t bp1;
-                       int rc1;
-
-                       bp1.status = EMPTY;
-                       bp1.size = DISK_BLOCK_BYTES;
-                       bp1.buffer = malloc(DISK_BLOCK_BYTES);
-
-                       if(fd != save_fd) {
-                           close(fd);
-                           fd = save_fd;
-                       }
+           if(header_written == 0 && (header_read == 1 || cur_span_chunkstart > 0)){
+               /* for split dumpfiles, modify headers for the second - nth
+                  pieces that signify that they're continuations of the last
+                  normal one */
+               char *cont_filename;
+               file.type = F_SPLIT_DUMPFILE;
+               file.partnum = num_splits + 1;
+               file.totalparts = expected_splits;
+                 cont_filename = stralloc(file.cont_filename);
+               file.cont_filename[0] = '\0';
+               build_header(bp->buffer, &file, tt_blocksize);
+  
+               if(cont_filename[0] != '\0') {
+                 file.type = F_CONT_DUMPFILE;
+                   strncpy(file.cont_filename, cont_filename,
+                           sizeof(file.cont_filename));
+                       }
+               memcpy(&cur_holdfile, &file, sizeof(dumpfile_t));
+  
+               if(interactive || bufdebug) dumpstatus(bp);
+               bp->size = tt_blocksize;
+               rc = tt_blocksize;
+               header_written = 1;
+               amfree(cont_filename);
+                       }
+           else if(retry_from_splitbuf){
+               /* quietly pull dump data from our in-memory cache, and the
+                  writer side need never know the wiser */
+               memcpy(bp->buffer, splitbuf_rd_ptr, tt_blocksize);
+               bp->size = tt_blocksize;
+               rc = tt_blocksize;
+               splitbuf_rd_ptr += tt_blocksize;
+               if(splitbuf_rd_ptr >= splitbuf_wr_ptr) retry_from_splitbuf = 0;
+           }
+           else if((rc = taper_fill_buffer(fd, bp, buflen)) < 0) {
+               err = errno;
+               closing = 1;
+               strclosing = newvstralloc(strclosing,"Can't read data: ",NULL);
+               syncpipe_put('C', 0);
+           }
+  
+           if(!closing) {
+               if(rc < buflen) { /* switch to next holding file */
+                   int ret;
+                   if(file.cont_filename[0] != '\0'){
+                      cur_filename = newvstralloc(cur_filename, file.cont_filename, NULL);
+                               }
+                   ret = get_next_holding_file(fd, bp, strclosing, rc);
+                   if(ret <= 0){
+                       need_closing = 1;
+                           }
+                           else {
+                       memcpy(&cur_holdfile, &file, sizeof(dumpfile_t));
+                       rc += ret;
+                               bp->size = rc;
+                           }
+                       }
+               if(rc > 0) {
+                   bp->status = FULL;
+                   /* rebuild the header block, which might have CONT junk */
+                   if(header_read == 0) {
+                       char *cont_filename;
+                       /* write the "real" filename if the holding-file
+                          is a partial one */
+                       parse_file_header(bp->buffer, &file, rc);
+                       parse_file_header(bp->buffer, &first_file, rc);
+                       cont_filename = stralloc(file.cont_filename);
+                       file.cont_filename[0] = '\0';
+                       if(splitsize > 0){
+                           file.type = F_SPLIT_DUMPFILE;
+                           file.partnum = 1;
+                           file.totalparts = expected_splits;
+                       }
+                       file.blocksize = tt_blocksize;
+                       build_header(bp->buffer, &file, tt_blocksize);
+                       kbytesread += tt_blocksize/1024; /* XXX shady */
+                       file.type = F_CONT_DUMPFILE;
+                       /* add CONT_FILENAME back to in-memory header */
+                       strncpy(file.cont_filename, cont_filename, 
+                               sizeof(file.cont_filename));
+                       if(interactive || bufdebug) dumpstatus(bp);
+                       bp->size = tt_blocksize; /* output a full tape block */
+                       /* save the header, we'll need it if we jump tapes */
+                       memcpy(&cur_holdfile, &file, sizeof(dumpfile_t));
+                       header_read = 1;
+                       header_written = 1;
+                       amfree(cont_filename);
+                   }
+                   else {
+                       filesize = kbytesread;
+                   }
 
-                       rc1 = taper_fill_buffer(fd, &bp1, DISK_BLOCK_BYTES);
-                       if(rc1 <= 0) {
-                           amfree(bp1.buffer);
-                           err = (rc1 < 0) ? errno : 0;
-                           need_closing = 1;
-                           strclosing = newvstralloc(strclosing,
-                                                     "Can't read header: ",
-                                                     file.cont_filename,
-                                                     NULL);
-                       } else {
-                           parse_file_header(bp1.buffer, &file, rc1);
-
-                           amfree(bp1.buffer);
-                           bp1.buffer = bp->buffer + rc;
-
-                           rc1 = taper_fill_buffer(fd, &bp1, tt_blocksize - rc);
-                           if(rc1 <= 0) {
-                               err = (rc1 < 0) ? errno : 0;
-                               need_closing = 1;
-                               if(rc1 < 0) {
-                                   strclosing = newvstralloc(strclosing,
-                                                             "Can't read data: ",
-                                                             file.cont_filename,
-                                                             NULL);
-                               }
-                           }
-                           else {
-                               rc += rc1;
-                               bp->size = rc;
-                           }
-                       }
-                   }
-               }
-               if(rc > 0) {
-                   bp->status = FULL;
-                   if(header_read == 0) {
-                       char *cont_filename;
-
-                       parse_file_header(bp->buffer, &file, rc);
-                       cont_filename = stralloc(file.cont_filename);
-                       file.cont_filename[0] = '\0';
-                       file.blocksize = tt_blocksize;
-                       build_header(bp->buffer, &file, tt_blocksize);
-
-                       /* add CONT_FILENAME back to in-memory header */
-                       strncpy(file.cont_filename, cont_filename, 
-                               sizeof(file.cont_filename));
-                       if(interactive || bufdebug) dumpstatus(bp);
-                       bp->size = tt_blocksize; /* output a full tape block */
-                       header_read = 1;
-                       amfree(cont_filename);
-                   }
-                   else {
-                       filesize += am_round(rc, 1024) / 1024;
-                   }
-                   if(interactive || bufdebug) dumpstatus(bp);
                    if(bufdebug) {
                        fprintf(stderr,"taper: r: put W%d\n",(int)(bp-buftable));
                        fflush(stderr);
                    }
-                   syncpipe_put('W');
-                   syncpipe_putint(bp-buftable);
+                   syncpipe_put('W', bp-buftable);
                    bp = nextbuf(bp);
                }
+
+               if(kbytesread + DISK_BLOCK_BYTES/1024 >= splitsize && splitsize > 0 && !need_closing){
+
+                   if(mode == MODE_PORT_WRITE){
+                       splitbuf_wr_ptr = splitbuf;
+                       splitbuf_rd_ptr = splitbuf;
+                       memset(splitbuf, 0, sizeof(splitbuf));
+                       retry_from_splitbuf = 0;
+                   }
+
+                   fprintf(stderr,"taper: r: end %s.%s.%s.%d part %d, splitting chunk that started at %ldkb after %ldkb (next chunk will start at %ldkb)\n", hostname, diskname, datestamp, level, num_splits+1, cur_span_chunkstart, kbytesread, cur_span_chunkstart+kbytesread);
+                   fflush(stderr);
+
+                   nexting = 1;
+                   need_closing = 1;
+               } /* end '(kbytesread >= splitsize && splitsize > 0)' */
                if(need_closing && rc <= 0) {
-                   syncpipe_put('C');
+                   syncpipe_put('C', 0);
                    need_closing = 0;
                    closing = 1;
                }
-           }
+                kbytesread += rc/1024;
+           } /* end the 'if(!closing)' (successful buffer fill) */
            break;
 
        case 'T':
        case 'E':
-           syncpipe_put('e');  /* ACK error */
+           syncpipe_put('e', 0);       /* ACK error */
 
-           aclose(fd);
            str = syncpipe_getstr();
            errstr = newvstralloc(errstr, "[", str ? str : "(null)", "]", NULL);
            amfree(str);
 
            q = squote(errstr);
            if(tok == 'T') {
-               putresult(TRYAGAIN, "%s %s\n", handle, q);
-               log_add(L_INFO, "retrying %s:%s.%d on new tape due to: %s",
-                       hostname, diskname, level, errstr);
+               if(splitsize > 0){
+                   /* we'll be restarting this chunk on the next tape */
+                   if(mode == MODE_FILE_WRITE){
+                     aclose(fd);
+                   }
+
+                   putresult(SPLIT_NEEDNEXT, "%s %ld\n", handle, cur_span_chunkstart);
+                   log_add(L_INFO, "continuing %s:%s.%d on new tape from %ldkb mark: %s",
+                           hostname, diskname, level, cur_span_chunkstart, errstr);
+                   return 1;
+               }
+               else{
+                   /* restart the entire dump (failure propagates to driver) */
+                   aclose(fd);
+                   putresult(TRYAGAIN, "%s %s\n", handle, q);
+                   cur_span_chunkstart = 0;
+                   log_add(L_INFO, "retrying %s:%s.%d on new tape due to: %s",
+                           hostname, diskname, level, errstr);
+               }
            } else {
+               aclose(fd);
                putresult(TAPE_ERROR, "%s %s\n", handle, q);
                log_add(L_FAIL, "%s %s %s %d [out of tape]",
                        hostname, diskname, datestamp, level);
-               log_add(L_ERROR,"no-tape [%s]", errstr);
+               log_add(L_ERROR,"no-tape [%s]", "No more writable valid tape found");
            }
            amfree(q);
-           return;
+
+           return 0;
 
        case 'C':
            assert(!opening);
            assert(closing);
 
+           if(nexting){
+             cur_span_chunkstart += kbytesread; /* XXX possibly wrong */
+             holdfile_name = newvstralloc(holdfile_name, cur_filename, NULL);
+
+             kbytesread = 0;
+             if(cur_filename != NULL) amfree(cur_filename);
+           }
+
+
            str = syncpipe_getstr();
            label = newstralloc(label, str ? str : "(null)");
            amfree(str);
@@ -961,8 +1385,13 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
                    label, filenum);
            fflush(stderr);
 
+           /* we'll need that file descriptor if we're gonna write more */
+           if(!nexting){
            aclose(fd);
+           }
+
            runtime = stopclock();
+           if(nexting) startclock();
            if(err) {
                if(strclosing) {
                    errstr = newvstralloc(errstr,
@@ -976,35 +1405,100 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
                                          NULL);
                q = squote(errstr);
                putresult(TAPE_ERROR, "%s %s\n", handle, q);
+
                amfree(q);
+               if(splitsize){
+                 log_add(L_FAIL, "%s %s %s.%d %d %s", hostname, diskname,
+                         datestamp, num_splits, level, errstr);
+               }
+               else{
                log_add(L_FAIL, "%s %s %s %d %s",
                        hostname, diskname, datestamp, level, errstr);
+               }
                str = syncpipe_getstr();        /* reap stats */
                amfree(str);
+                amfree(errstr);
            } else {
                char kb_str[NUM_STR_SIZE];
                char kps_str[NUM_STR_SIZE];
                double rt;
 
                rt = runtime.r.tv_sec+runtime.r.tv_usec/1000000.0;
-               ap_snprintf(kb_str, sizeof(kb_str), "%ld", filesize);
-               ap_snprintf(kps_str, sizeof(kps_str), "%3.1f",
+               curdump_rt = timesadd(runtime, curdump_rt);
+               snprintf(kb_str, sizeof(kb_str), "%ld", filesize);
+               snprintf(kps_str, sizeof(kps_str), "%3.1f",
                                     rt ? filesize / rt : 0.0);
                str = syncpipe_getstr();
                errstr = newvstralloc(errstr,
                                      "[sec ", walltime_str(runtime),
                                      " kb ", kb_str,
                                      " kps ", kps_str,
-                                     " ", str ? str : "(null)",
+                                     " ", str,
                                      "]",
                                      NULL);
-               amfree(str);
                q = squote(errstr);
-               putresult(DONE, "%s %s %d %s\n",
-                         handle, label, filenum, q);
-               amfree(q);
-               log_add(L_SUCCESS, "%s %s %s %d %s",
-                       hostname, diskname, datestamp, level, errstr);
+               if (splitsize == 0) { /* Ordinary dump */
+                   if(first_file.is_partial) {
+                       putresult(PARTIAL, "%s %s %d %s\n",
+                                 handle, label, filenum, q);
+                       log_add(L_PARTIAL, "%s %s %s %d %s",
+                               hostname, diskname, datestamp, level, errstr);
+                   }
+                   else {
+                       putresult(DONE, "%s %s %d %s\n",
+                                 handle, label, filenum, q);
+                       log_add(L_SUCCESS, "%s %s %s %d %s",
+                               hostname, diskname, datestamp, level, errstr);
+                   }
+               } else { /* Chunked dump */
+                   num_splits++;
+                   if(mode == MODE_FILE_WRITE){
+                       holdfile_path_thischunk = stralloc(holdfile_path);
+                       holdfile_offset_thischunk = (lseek(fd, (off_t)0, SEEK_CUR))/1024;
+                       if(!save_holdfile){
+                           save_holdfile = alloc(sizeof(dumpfile_t));
+                       }
+                       memcpy(save_holdfile, &cur_holdfile,sizeof(dumpfile_t));
+                   }
+                   log_add(L_CHUNK, "%s %s %s %d %d %s", hostname, diskname,
+                           datestamp, num_splits, level, errstr);
+                   if(!nexting){ /* split dump complete */
+                       rt =curdump_rt.r.tv_sec+curdump_rt.r.tv_usec/1000000.0;
+                       snprintf(kb_str, sizeof(kb_str), "%ld",
+                                   filesize+cur_span_chunkstart);
+                       snprintf(kps_str, sizeof(kps_str), "%3.1f",
+                                   rt ? (filesize+cur_span_chunkstart) / rt : 0.0);
+                        amfree(errstr);
+                       errstr = newvstralloc(errstr,
+                                             "[sec ", walltime_str(curdump_rt),
+                                             " kb ", kb_str,
+                                             " kps ", kps_str,
+                                             " ", str,
+                                             "]",
+                                             NULL);
+                        q = squote(errstr);
+                       putresult(DONE, "%s %s %d %s\n", handle, label,
+                                 filenum, q);
+                       log_add(L_CHUNKSUCCESS, "%s %s %s %d %s",
+                               hostname, diskname, datestamp, level, errstr);
+                       amfree(save_holdfile);
+                       amfree(holdfile_path_thischunk);
+                        amfree(q);
+                    }
+               }
+               amfree(str);
+
+               if(!nexting){
+                   num_splits = 0;
+                   expected_splits = 0;
+                   amfree(holdfile_name);
+                   num_holdfiles = 0;
+                   cur_span_chunkstart = 0;
+                   curdump_rt = times_zero;
+               }
+               
+               amfree(errstr);
+               
 #ifdef HAVE_LIBVTBLC
                /* 
                 *  We have 44 characters available for the label string:
@@ -1045,8 +1539,7 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
                fflush(stderr);
 
                /* pass label string on to tape writer */
-               syncpipe_put('L');
-               syncpipe_putint(filenum);
+               syncpipe_put('L', filenum);
                syncpipe_putstr(vol_label);             
 
                /* 
@@ -1060,18 +1553,38 @@ void read_file(fd, handle, hostname, diskname, datestamp, level, port_flag)
                        vol_date);
 
                /* pass date string on to tape writer */                
-               syncpipe_put('D');
-               syncpipe_putint(filenum);
+               syncpipe_put('D', filenum);
                syncpipe_putstr(vol_date);
 
 #endif /* HAVE_LIBVTBLC */
            }
-           return;
+           /* reset stuff that assumes we're on a new file */
+
+           if(nexting){
+               opening = 1;
+               nexting = 0;
+               closing = 0;
+               filesize = 0;
+               syncpipe_put('O', 0);
+               syncpipe_putstr(datestamp);
+               syncpipe_putstr(hostname);
+               syncpipe_putstr(diskname);
+               syncpipe_putint(level);
+               for(bp = buftable; bp < buftable + conf_tapebufs; bp++) {
+                   bp->status = EMPTY;
+               }
+               bp = buftable;
+               header_written = 0;
+               break;
+           }
+           else return 0;
 
        default:
            assert(0);
        }
     }
+
+    return 0;
 }
 
 int taper_fill_buffer(fd, bp, buflen)
@@ -1086,28 +1599,67 @@ int buflen;
     bp->size = 0;
     spaceleft = buflen;
 
-    do {
-       cnt = read(fd, curptr, spaceleft);
-       switch(cnt) {
-       case 0: /* eof */
-           if(interactive) fputs("r0", stderr);
-           return bp->size;
-       case -1:        /* error on read, punt */
-           if(interactive) fputs("rE", stderr);
-           return -1;
-       default:
-           spaceleft -= cnt;
-           curptr += cnt;
-           bp->size += cnt;
+    cnt = fullread(fd, curptr, spaceleft);
+    switch(cnt) {
+    case 0:    /* eof */
+       if(interactive) fputs("r0", stderr);
+       return bp->size;
+    case -1:   /* error on read, punt */
+       if(interactive) fputs("rE", stderr);
+       return -1;
+    default:
+       if(mode == MODE_PORT_WRITE && splitsize > 0){
+           memcpy(splitbuf_wr_ptr, curptr, (size_t)cnt);
+           splitbuf_wr_ptr += cnt;
        }
-
-    } while(spaceleft > 0);
+       spaceleft -= cnt;
+       curptr += cnt;
+       bp->size += cnt;
+    }
 
     if(interactive) fputs("R", stderr);
     return bp->size;
 }
 
+/* Given a dumpfile in holding, determine its size and figure out how many
+ * times we'd have to split it.
+ */
+int predict_splits(filename)
+char *filename;
+{
+    int splits = 0;
+    long total_kb = 0;
+    long adj_splitsize = splitsize - DISK_BLOCK_BYTES/1024;
+
+    if(splitsize <= 0) return(0);
 
+    if(adj_splitsize <= 0){
+      error("Split size must be > %ldk", DISK_BLOCK_BYTES/1024);
+    }
+
+    /* should only calculuate this once, not on retries etc */
+    if(expected_splits != 0) return(expected_splits);
+
+    total_kb = size_holding_files(filename, 1);
+    
+    if(total_kb <= 0){
+      fprintf(stderr, "taper: r: %ld kb holding file makes no sense, not precalculating splits\n", total_kb);
+      fflush(stderr);
+      return(0);
+    }
+
+    fprintf(stderr, "taper: r: Total dump size should be %ldkb, chunk size is %ldkb\n", total_kb, splitsize);
+    fflush(stderr);
+
+    splits = total_kb/adj_splitsize;
+    if(total_kb % adj_splitsize) splits++;
+
+
+    fprintf(stderr, "taper: r: Expecting to split into %d parts \n", splits);
+    fflush(stderr);
+
+    return(splits);
+}
 
 /*
  * ========================================================================
@@ -1132,6 +1684,7 @@ int getp, putp;
     char *diskname;
     char *datestamp;
     int level;
+    int tmpint;
 
 #ifdef HAVE_LIBVTBLC
     char *vol_label;
@@ -1146,7 +1699,7 @@ int getp, putp;
 
     while(1) {
        startclock();
-       tok = syncpipe_get();
+       tok = syncpipe_get(&tmpint);
        idlewait = timesadd(idlewait, stopclock());
        if(tok != 'S' && tok != 'Q' && !tape_started) {
            error("writer: token '%c' before start", tok);
@@ -1163,17 +1716,17 @@ int getp, putp;
                    tapefd_close(tape_fd);
                    tape_fd = -1;
                }
-               syncpipe_put('E');
+               syncpipe_put('E', 0);
                syncpipe_putstr(errstr);
                /* wait for reader to acknowledge error */
                do {
-                   tok = syncpipe_get();
+                   tok = syncpipe_get(&tmpint);
                    if(tok != 'e') {
                        error("writer: got '%c' unexpectedly after error", tok);
                    }
                } while(tok != 'e');
            } else {
-               syncpipe_put('S');
+               syncpipe_put('S', 0);
                tape_started = 1;
            }
            amfree(str);
@@ -1197,7 +1750,7 @@ int getp, putp;
 
 #ifdef HAVE_LIBVTBLC
        case 'L':               /* read vtbl label */
-           vtbl_no = syncpipe_getint();
+           vtbl_no = tmpint;
            vol_label = syncpipe_getstr();
            fprintf(stderr, "taper: read label string \"%s\" from pipe\n", 
                    vol_label);
@@ -1205,7 +1758,7 @@ int getp, putp;
            break;
 
        case 'D':               /* read vtbl date */
-           vtbl_no = syncpipe_getint();
+           vtbl_no = tmpint;
            vol_date = syncpipe_getstr();
            fprintf(stderr, "taper: read date string \"%s\" from pipe\n", 
                    vol_date);
@@ -1216,12 +1769,12 @@ int getp, putp;
        case 'Q':
            end_tape(0);        /* XXX check results of end tape ?? */
            clear_tapelist();
-           detach_buffers(buffers);
            amfree(taper_datestamp);
            amfree(label);
            amfree(errstr);
            amfree(changer_resultstr);
            amfree(tapedev);
+           amfree(conf_tapelist);
            amfree(config_dir);
            amfree(config_name);
 
@@ -1246,6 +1799,7 @@ void write_file()
     char tok;
     char number[NUM_STR_SIZE];
     char *rdwait_str, *wrwait_str, *fmwait_str;
+    int tmpint;
 
     rdwait = wrwait = times_zero;
     total_writes = 0;
@@ -1262,13 +1816,13 @@ void write_file()
     /*
      * Tell the reader that the tape is open, and give it all the buffers.
      */
-    syncpipe_put('O');
+    syncpipe_put('O', 0);
     for(i = 0; i < conf_tapebufs; i++) {
        if(bufdebug) {
            fprintf(stderr, "taper: w: put R%d\n", i);
            fflush(stderr);
        }
-       syncpipe_put('R'); syncpipe_putint(i);
+       syncpipe_put('R'i);
     }
 
     /*
@@ -1299,9 +1853,8 @@ void write_file()
        if(interactive) fputs("[WS]", stderr);
        startclock();
        while(full_buffers < conf_tapebufs - THRESHOLD) {
-           tok = syncpipe_get();
+           tok = syncpipe_get(&bufnum);
            if(tok != 'W') break;
-           bufnum = syncpipe_getint();
            if(bufdebug) {
                fprintf(stderr,"taper: w: got W%d\n",bufnum);
                fflush(stderr);
@@ -1343,9 +1896,8 @@ void write_file()
         */
 
        while(tok == 'W' && bp->status == FULL) {
-           tok = syncpipe_get();
+           tok = syncpipe_get(&bufnum);
            if(tok == 'W') {
-               bufnum = syncpipe_getint();
                if(bufdebug) {
                    fprintf(stderr,"taper: w: got W%d\n",bufnum);
                    fflush(stderr);
@@ -1355,7 +1907,7 @@ void write_file()
                            "taper: tape-writer: my buf %d reader buf %d\n",
                            (int)(bp-buftable), bufnum);
                    fflush(stderr);
-                   syncpipe_put('E');
+                   syncpipe_put('E', 0);
                    syncpipe_putstr("writer-side buffer mismatch");
                    goto error_ack;
                }
@@ -1381,15 +1933,15 @@ void write_file()
        goto reader_buffer_snafu;
 
     assert(tok == 'C');
-    syncpipe_put('C');
+    syncpipe_put('C', 0);
 
     /* tell reader the tape and file number */
 
     syncpipe_putstr(label);
-    ap_snprintf(number, sizeof(number), "%d", filenum);
+    snprintf(number, sizeof(number), "%d", filenum);
     syncpipe_putstr(number);
 
-    ap_snprintf(number, sizeof(number), "%ld", total_writes);
+    snprintf(number, sizeof(number), "%ld", total_writes);
     rdwait_str = stralloc(walltime_str(rdwait));
     wrwait_str = stralloc(walltime_str(wrwait));
     fmwait_str = stralloc(walltime_str(fmwait));
@@ -1412,23 +1964,21 @@ void write_file()
 
  tape_error:
     /* got tape error */
-    if(next_tape(1)) syncpipe_put('T');        /* next tape in place, try again */
-    else syncpipe_put('E');            /* no more tapes, fail */
+    if(next_tape(1)) syncpipe_put('T', 0);     /* next tape in place, try again */
+    else syncpipe_put('E', 0);         /* no more tapes, fail */
     syncpipe_putstr(errstr);
 
  error_ack:
     /* wait for reader to acknowledge error */
     do {
-       tok = syncpipe_get();
+       tok = syncpipe_get(&tmpint);
        if(tok != 'W' && tok != 'C' && tok != 'e')
            error("writer: got '%c' unexpectedly after error", tok);
-       if(tok == 'W')
-           syncpipe_getint();  /* eat buffer number */
     } while(tok != 'e');
     return;
 
  reader_buffer_snafu:
-    syncpipe_put('x');
+    syncpipe_put('x', 0);
     return;
 }
 
@@ -1437,10 +1987,7 @@ buffer_t *bp;
 {
     int rc;
 
-    if(bp->status != FULL) {
-       /* XXX buffer management snafu */
-       assert(0);
-    }
+    assert(bp->status == FULL);
 
     startclock();
     rc = tapefd_write(tape_fd, bp->buffer, bp->size);
@@ -1470,7 +2017,7 @@ buffer_t *bp;
            fprintf(stderr, "taper: w: put R%d\n", (int)(bp-buftable));
            fflush(stderr);
        }
-       syncpipe_put('R'); syncpipe_putint(bp-buftable);
+       syncpipe_put('R'bp-buftable);
        return 1;
     } else {
        errstr = newvstralloc(errstr,
@@ -1484,6 +2031,67 @@ buffer_t *bp;
 }
 
 
+static void 
+cleanup(void)
+{
+    REMOVE_SHARED_MEMORY(); 
+}
+
+
+/*
+ * Cleanup shared memory segments 
+ */
+static void 
+signal_handler(int signum)
+{
+    log_add(L_INFO, "Received signal %d", signum);
+
+    exit(1);
+}
+
+
+/*
+ * Installing signal handlers for signal whose default action is 
+ * process termination so that we can clean up shared memory
+ * segments
+ */
+static void
+install_signal_handlers(void) 
+{
+    struct sigaction act;
+
+    act.sa_handler = signal_handler;
+    act.sa_flags = 0;
+    sigemptyset(&act.sa_mask);
+
+    signal(SIGPIPE, SIG_IGN);
+
+    if (sigaction(SIGINT, &act, NULL) != 0) {
+       error("taper: couldn't install SIGINT handler [%s]", strerror(errno));
+    }
+
+    if (sigaction(SIGHUP, &act, NULL) != 0) {
+       error("taper: couldn't install SIGHUP handler [%s]", strerror(errno));
+    }
+   
+    if (sigaction(SIGTERM, &act, NULL) != 0) {
+       error("taper: couldn't install SIGTERM handler [%s]", strerror(errno));
+    }
+
+    if (sigaction(SIGUSR1, &act, NULL) != 0) {
+       error("taper: couldn't install SIGUSR1 handler [%s]", strerror(errno));
+    }
+
+    if (sigaction(SIGUSR2, &act, NULL) != 0) {
+       error("taper: couldn't install SIGUSR2 handler [%s]", strerror(errno));
+    }
+
+    if (sigaction(SIGALRM, &act, NULL) != 0) {
+       error("taper: couldn't install SIGALRM handler [%s]", strerror(errno));
+    }
+}
+
+
 /*
  * ========================================================================
  * SHARED-MEMORY BUFFER SUBSYSTEM
@@ -1521,7 +2129,8 @@ char *attach_buffers(size)
 void detach_buffers(bufp)
     char *bufp;
 {
-    if(shmdt((SHM_ARG_TYPE *)bufp) == -1) {
+    if ((bufp != NULL) &&
+        (shmdt((SHM_ARG_TYPE *)bufp) == -1)) {
        error("shmdt: %s", strerror(errno));
     }
 }
@@ -1580,11 +2189,13 @@ char *attach_buffers(size)
 void detach_buffers(bufp)
 char *bufp;
 {
-    if(munmap((void *)bufp, saved_size) == -1) {
+    if ((bufp != NULL) && 
+       (munmap((void *)bufp, saved_size) == -1)) {
        error("detach_buffers: munmap: %s", strerror(errno));
     }
 
-    aclose(shmfd);
+    if (shmfd != -1)
+       aclose(shmfd);
 }
 
 void destroy_buffers()
@@ -1592,7 +2203,7 @@ void destroy_buffers()
 }
 
 #else
-error: must define either HAVE_SYSVSHM or HAVE_MMAP!
+#error: must define either HAVE_SYSVSHM or HAVE_MMAP!
 #endif
 #endif
 
@@ -1613,111 +2224,95 @@ int rd, wr;
     putpipe = wr;
 }
 
-char syncpipe_get()
+char syncpipe_get(intp)
+int *intp;
 {
     int rc;
-    char buf[1];
+    char buf[sizeof(char) + sizeof(int)];
 
-    rc = read(getpipe, buf, sizeof(buf));
+    rc = fullread(getpipe, buf, sizeof(buf));
     if(rc == 0)                /* EOF */
        error("syncpipe_get: %c: unexpected EOF", *procname);
     else if(rc < 0)
        error("syncpipe_get: %c: %s", *procname, strerror(errno));
+    else if(rc != sizeof(buf))
+       error("syncpipe_get: %s", "short read");
 
     if(bufdebug && *buf != 'R' && *buf != 'W') {
        fprintf(stderr,"taper: %c: getc %c\n",*procname,*buf);
        fflush(stderr);
     }
 
+    memcpy(intp, &buf[1], sizeof(int));
     return buf[0];
 }
 
 int syncpipe_getint()
 {
-    int rc;
-    int i;
-    int len = sizeof(i);
-    char *p;
+    int rc, i;
 
-    for(p = (char *)&i; len > 0; len -= rc, p += rc) {
-       if ((rc = read(getpipe, p, len)) <= 0) {
-           error("syncpipe_getint: %s",
-                 rc < 0 ? strerror(errno) : "short read");
-       }
-    }
+    if ((rc = fullread(getpipe, &i, sizeof(i))) != sizeof(i))
+       error("syncpipe_getint: %s", rc < 0 ? strerror(errno) : "short read");
 
-    return i;
+    return (i);
 }
 
 
 char *syncpipe_getstr()
 {
-    int rc;
-    int len;
-    char *p;
+    int rc, len;
     char *str;
 
     if((len = syncpipe_getint()) <= 0) {
-       return NULL;
+       error("syncpipe_getstr: Protocol error - Invalid length (%d)", len);
+       /* NOTREACHED */
     }
 
     str = alloc(len);
 
-    for(p = str; len > 0; len -= rc, p += rc) {
-       if ((rc = read(getpipe, p, len)) <= 0) {
-           error("syncpipe_getstr: %s",
-                 rc < 0 ? strerror(errno) : "short read");
-       }
+    if ((rc = fullread(getpipe, str, len)) != len) {
+       error("syncpipe_getstr: %s", rc < 0 ? strerror(errno) : "short read");
+       /* NOTREACHED */
     }
 
-    return str;
+    return (str);
 }
 
 
-void syncpipe_put(chi)
+void syncpipe_put(chi, intval)
 int chi;
+int intval;
 {
-    int l, n, s;
-    char ch = chi;
-    char *item = &ch;
+    char buf[sizeof(char) + sizeof(int)];
 
-    if(bufdebug && chi != 'R' && chi != 'W') {
-       fprintf(stderr,"taper: %c: putc %c\n",*procname,chi);
+    buf[0] = (char)chi;
+    memcpy(&buf[1], &intval, sizeof(int));
+    if(bufdebug && buf[0] != 'R' && buf[0] != 'W') {
+       fprintf(stderr,"taper: %c: putc %c\n",*procname,buf[0]);
        fflush(stderr);
     }
 
-    for(l = 0, n = sizeof(ch); l < n; l += s) {
-       if((s = write(putpipe, item + l, n - l)) < 0) {
-           error("syncpipe_put: %s", strerror(errno));
-       }
-    }
+    if (fullwrite(putpipe, buf, sizeof(buf)) < 0)
+       error("syncpipe_put: %s", strerror(errno));
 }
 
 void syncpipe_putint(i)
 int i;
 {
-    int l, n, s;
-    char *item = (char *)&i;
 
-    for(l = 0, n = sizeof(i); l < n; l += s) {
-       if((s = write(putpipe, item + l, n - l)) < 0) {
-           error("syncpipe_putint: %s", strerror(errno));
-       }
-    }
+    if (fullwrite(putpipe, &i, sizeof(i)) < 0)
+       error("syncpipe_putint: %s", strerror(errno));
 }
 
-void syncpipe_putstr(item)
-char *item;
+void syncpipe_putstr(str)
+const char *str;
 {
-    int l, n, s;
+    int n;
 
-    n = strlen(item)+1;                                /* send '\0' as well */
+    n = strlen(str)+1;                         /* send '\0' as well */
     syncpipe_putint(n);
-    for(l = 0, n = strlen(item)+1; l < n; l += s) {
-       if((s = write(putpipe, item + l, n - l)) < 0) {
-           error("syncpipe_putstr: %s", strerror(errno));
-       }
-    }
+    if (fullwrite(putpipe, str, n) < 0)
+       error("syncpipe_putstr: %s", strerror(errno));
 }
 
 \f
@@ -1728,84 +2323,24 @@ char *item;
  */
 
 /* local functions */
-int scan_init P((int rc, int ns, int bk));
-int taperscan_slot P((int rc, char *slotstr, char *device));
-char *taper_scan P((void));
 int label_tape P((void));
 
 int label_tape()
-{
+{  
     char *conf_tapelist_old = NULL;
-    char *olddatestamp = NULL;
     char *result;
-    tape_t *tp;
     static int first_call = 1;
-
-    if(have_changer) {
-       amfree(tapedev);
-       if ((tapedev = taper_scan()) == NULL) {
-           errstr = newstralloc(errstr, changer_resultstr);
-           return 0;
-       }
-    }
-
-#ifdef HAVE_LINUX_ZFTAPE_H
-    if (is_zftape(tapedev) == 1){
-       if((tape_fd = tape_open(tapedev, O_RDONLY)) == -1) {
-           errstr = newstralloc2(errstr, "taper: ",
-                                 (errno == EACCES) ? "tape is write-protected"
-                                 : strerror(errno));
-           return 0;
-       }
-       if((result = tapefd_rdlabel(tape_fd, &olddatestamp, &label)) != NULL) {
-           amfree(olddatestamp);
-           errstr = newstralloc(errstr, result);
-           return 0;
-       }
-       if(tapefd_rewind(tape_fd) == -1) { 
-           return 0;
-       } 
-       tapefd_close(tape_fd);
-       tape_fd = -1;
-    }
-    else
-#endif /* !HAVE_LINUX_ZFTAPE_H */
-    if((result = tape_rdlabel(tapedev, &olddatestamp, &label)) != NULL) {
-       amfree(olddatestamp);
-       errstr = newstralloc(errstr, result);
+    char *timestamp;
+    char *error_msg;
+
+    if (taper_scan(NULL, &label, &timestamp, &error_msg, &tapedev) < 0) {
+        fprintf(stderr, "%s\n", error_msg);
+       errstr = newstralloc(errstr, error_msg);
+        amfree(error_msg);
+        amfree(timestamp);
        return 0;
     }
-
-    fprintf(stderr, "taper: read label `%s' date `%s'\n", label, olddatestamp);
-    fflush(stderr);
-    amfree(olddatestamp);
-
-    /* check against tape list */
-    if (strcmp(label, FAKE_LABEL) != 0) {
-       tp = lookup_tapelabel(label);
-       if(tp == NULL) {
-           errstr = newvstralloc(errstr,
-                                 "label ", label,
-               " match labelstr but it not listed in the tapelist file",
-                                 NULL);
-           return 0;
-       }
-       else if(tp != NULL && !reusable_tape(tp)) {
-           errstr = newvstralloc(errstr,
-                                 "cannot overwrite active tape ", label,
-                                 NULL);
-           return 0;
-       }
-
-       if(!match(labelstr, label)) {
-           errstr = newvstralloc(errstr,
-                                 "label ", label,
-                                 " doesn\'t match labelstr \"", labelstr, "\"",
-                                 NULL);
-           return 0;
-       }
-    }
-
+    
     if((tape_fd = tape_open(tapedev, O_WRONLY)) == -1) {
        if(errno == EACCES) {
            errstr = newstralloc(errstr,
@@ -1831,7 +2366,7 @@ int label_tape()
     fflush(stderr);
 
 #ifdef HAVE_LIBVTBLC
-    /* store time for the first volume entry */ 
+    /* store time for the first volume entry */
     time(&raw_time);
     tape_timep = localtime(&raw_time);
     strftime(start_datestr, 20, "%T %D", tape_timep);
@@ -1839,9 +2374,6 @@ int label_tape()
     fflush(stderr);
 #endif /* HAVE_LIBVTBLC */
 
-    /* write tape list */
-
-    /* XXX add cur_tape number to tape list structure */
     if (strcmp(label, FAKE_LABEL) != 0) {
 
        if(cur_tape == 0) {
@@ -1849,9 +2381,9 @@ int label_tape()
        } else {
            char cur_str[NUM_STR_SIZE];
 
-           ap_snprintf(cur_str, sizeof(cur_str), "%d", cur_tape - 1);
+           snprintf(cur_str, sizeof(cur_str), "%d", cur_tape - 1);
            conf_tapelist_old = vstralloc(conf_tapelist,
-                                       ".today.", cur_str, NULL);
+                                         ".today.", cur_str, NULL);
        }
        if(write_tapelist(conf_tapelist_old)) {
            error("could not write tapelist: %s", strerror(errno));
@@ -2090,167 +2622,3 @@ int write_filemark()
 }
 
 
-/*
- * ========================================================================
- * TAPE CHANGER SCAN
- *
- */
-int nslots, backwards, found, got_match, tapedays;
-char *first_match_label = NULL, *first_match = NULL, *found_device = NULL;
-char *searchlabel, *labelstr;
-tape_t *tp;
-
-int scan_init(rc, ns, bk)
-int rc, ns, bk;
-{
-    if(rc) {
-       fprintf(stderr, "%s: could not get changer info: %s\n",
-               get_pname(), changer_resultstr);
-       return rc;
-    }
-
-    nslots = ns;
-    backwards = bk;
-
-    return 0;
-}
-
-int taperscan_slot(rc, slotstr, device)
-     int rc;
-     char *slotstr;
-     char *device;
-{
-    char *t_errstr;
-    char *scan_datestamp = NULL;
-
-    if(rc == 2) {
-       fprintf(stderr, "%s: fatal slot %s: %s\n",
-               get_pname(), slotstr, changer_resultstr);
-       fflush(stderr);
-       return 1;
-    }
-    else if(rc == 1) {
-       fprintf(stderr, "%s: slot %s: %s\n", get_pname(),
-               slotstr, changer_resultstr);
-       fflush(stderr);
-       return 0;
-    }
-    else {
-       if((t_errstr = tape_rdlabel(device, &scan_datestamp, &label)) != NULL) {
-           amfree(scan_datestamp);
-           fprintf(stderr, "%s: slot %s: %s\n",
-                   get_pname(), slotstr, t_errstr);
-           fflush(stderr);
-       }
-       else {
-           /* got an amanda tape */
-           fprintf(stderr, "%s: slot %s: date %-8s label %s",
-                   get_pname(), slotstr, scan_datestamp, label);
-           fflush(stderr);
-           amfree(scan_datestamp);
-           if(searchlabel != NULL
-              && (strcmp(label, FAKE_LABEL) == 0
-                  || strcmp(label, searchlabel) == 0)) {
-               /* it's the one we are looking for, stop here */
-               fprintf(stderr, " (exact label match)\n");
-               fflush(stderr);
-               found_device = newstralloc(found_device, device);
-               found = 1;
-               return 1;
-           }
-           else if(!match(labelstr, label)) {
-               fprintf(stderr, " (no match)\n");
-               fflush(stderr);
-           }
-           else {
-               /* not an exact label match, but a labelstr match */
-               /* check against tape list */
-               tp = lookup_tapelabel(label);
-               if(tp == NULL) {
-                   fprintf(stderr, "(not in tapelist)\n");
-                   fflush(stderr);
-               }
-               else if(!reusable_tape(tp)) {
-                   fprintf(stderr, " (active tape)\n");
-                   fflush(stderr);
-               }
-               else if(got_match == 0 && tp->datestamp == 0) {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(stderr, " (new tape)\n");
-                   fflush(stderr);
-                   found = 3;
-                   found_device = newstralloc(found_device, device);
-                   return 1;
-               }
-               else if(got_match) {
-                   fprintf(stderr, " (labelstr match)\n");
-                   fflush(stderr);
-               }
-               else {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(stderr, " (first labelstr match)\n");
-                   fflush(stderr);
-                   if(!backwards || !searchlabel) {
-                       found = 2;
-                       found_device = newstralloc(found_device, device);
-                       return 1;
-                   }
-               }
-           }
-       }
-    }
-    return 0;
-}
-
-char *taper_scan()
-{
-    char *outslot = NULL;
-
-    if((tp = lookup_last_reusable_tape(0)) == NULL)
-       searchlabel = NULL;
-    else
-       searchlabel = tp->label;
-
-    found = 0;
-    got_match = 0;
-
-    if (searchlabel != NULL)
-      changer_find(scan_init, taperscan_slot, searchlabel);
-    else
-      changer_scan(scan_init, taperscan_slot);
-
-    if(found == 2 || found == 3)
-       searchlabel = first_match_label;
-    else if(!found && got_match) {
-       searchlabel = first_match_label;
-       amfree(found_device);
-       if(changer_loadslot(first_match, &outslot, &found_device) == 0) {
-           found = 1;
-       }
-       amfree(outslot);
-    }
-    else if(!found) {
-       if(searchlabel) {
-           changer_resultstr = newvstralloc(changer_resultstr,
-                                            "label ", searchlabel,
-                                            " or new tape not found in rack",
-                                            NULL);
-       } else {
-           changer_resultstr = newstralloc(changer_resultstr,
-                                           "new tape not found in rack");
-       }
-    }
-
-    if(found) {
-       outslot = found_device;
-       found_device = NULL;            /* forget about our copy */
-    } else {
-       outslot = NULL;
-       amfree(found_device);
-    }
-    return outslot;
-}
diff --git a/server-src/taperscan.c b/server-src/taperscan.c
new file mode 100644 (file)
index 0000000..3b5ba55
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2005 Zmanda Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ * 
+ * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
+ * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
+ */
+
+/*
+ * $Id: taperscan.c,v 1.9 2006/03/10 14:29:22 martinea Exp $
+ *
+ * This contains the implementation of the taper-scan algorithm, as it is
+ * used by taper, amcheck, and amtape. See the header file taperscan.h for
+ * interface information. */
+
+#include <amanda.h>
+#include <tapeio.h>
+#include <conffile.h>
+#include "changer.h"
+#include "tapefile.h"
+
+int scan_read_label P((char *dev, char *wantlabel,
+                       char** label, char** timestamp,
+                       char**error_message));
+int changer_taper_scan P((char *wantlabel, char** gotlabel, char**timestamp,
+                          char**error_message, char **tapedev));
+char *find_brand_new_tape_label();
+
+/* NO GLOBALS PLEASE! */
+
+/* How does the taper scan algorithm work? Like this:
+ * 1) If there is a barcode reader, and we have a recyclable tape, use the
+ *    reader to load the oldest tape.
+ * 2) Otherwise, search through the changer until we find a new tape
+ *    or the oldest recyclable tape.
+ * 3) If we couldn't find the oldest recyclable tape or a new tape,
+ *    but if in #2 we found *some* recyclable tape, use the oldest one we
+ *    found.
+ * 4) At this point, we give up.
+ */
+
+/* This function checks the label of a single tape, which may or may not
+ * have been loaded by the changer. With the addition of char *dev, it has
+ * the same interface as taper_scan. 
+ * Return value is the same as taper_scan.
+ */
+int scan_read_label(char *dev, char *desired_label,
+                    char** label, char** timestamp, char** error_message) {
+    char *result = NULL;
+    char *errstr = NULL;
+
+    *label = *timestamp = NULL;
+    result = tape_rdlabel(dev, timestamp, label);
+    if (result != NULL) {
+        if (CHECK_NOT_AMANDA_TAPE_MSG(result) &&
+            getconf_seen(CNF_LABEL_NEW_TAPES)) {
+            amfree(result);
+            
+            *label = find_brand_new_tape_label();
+            if (*label != NULL) {
+                *timestamp = stralloc("X");
+                vstrextend(error_message,
+                           "Found a non-amanda tape, will label it `",
+                           *label, "'.\n", NULL);
+                return 3;
+            }
+            vstrextend(error_message,
+                       "Found a non-amanda tape, but have no labels left.\n",
+                       NULL);
+            return -1;
+        }
+        amfree(*timestamp);
+        amfree(*label);
+        vstrextend(error_message, result, "\n", NULL);
+        amfree(result);
+        return -1;
+    }
+    
+    if ((*label == NULL) || (*timestamp == NULL)) {
+       error("Invalid return from tape_rdlabel");
+    }
+
+    vstrextend(error_message, "read label `", *label, "', date `",
+               *timestamp, "'\n", NULL);
+
+    if (desired_label != NULL && strcmp(*label, desired_label) == 0) {
+        /* Got desired label. */
+        return 1;
+    }
+
+    /* Is this actually an acceptable tape? */
+    if (strcmp(*label, FAKE_LABEL) != 0) {
+        char *labelstr;
+        labelstr = getconf_str(CNF_LABELSTR);
+       if(!match(labelstr, *label)) {
+            vstrextend(&errstr, "label ", *label,
+                       " doesn\'t match labelstr \"",
+                       labelstr, "\"\n", NULL);
+            return -1;
+       } else {
+            tape_t *tp;
+            if (strcmp(*timestamp, "X") == 0) {
+                /* new, labeled tape. */
+                return 1;
+            }
+
+            tp = lookup_tapelabel(*label);
+         
+            if(tp == NULL) {
+                vstrextend(&errstr, "label ", *label,
+                     " match labelstr but it not listed in the tapelist file.\n",
+                           NULL);
+                return -1;
+            } else if(tp != NULL && !reusable_tape(tp)) {
+                vstrextend(&errstr, "cannot overwrite active tape ", *label,
+                           "\n", NULL);
+                return -1;
+            }
+        }
+    }
+  
+    /* Yay! We got a good tape! */
+    return 2;
+}
+
+/* Interface is the same as taper_scan, with the addition of the tapedev
+ * output. */
+typedef struct {
+    char *wantlabel;
+    char **gotlabel;
+    char **timestamp;
+    char **error_message;
+    char **tapedev;
+    char *first_labelstr_slot;
+    int backwards;
+    int tape_status;
+} changertrack_t;
+
+int scan_slot(void *data, int rc, char *slotstr, char *device) {
+    int label_result;
+    changertrack_t *ct = ((changertrack_t*)data);
+
+    switch (rc) {
+    default:
+        newvstralloc(*(ct->error_message), *(ct->error_message),
+                     "fatal changer error ", slotstr, ": ",
+                     changer_resultstr, NULL);
+        return 1;
+    case 1:
+        newvstralloc(*(ct->error_message), *(ct->error_message),
+                     "changer error ", slotstr, ": ", changer_resultstr, NULL);
+        return 0;
+    case 0:
+       vstrextend(ct->error_message, "slot ", slotstr, ": ", NULL);
+        label_result = scan_read_label(device, ct->wantlabel, ct->gotlabel,
+                                       ct->timestamp, ct->error_message);
+        if (label_result == 1 || label_result == 3 ||
+            (label_result == 2 && !ct->backwards)) {
+            *(ct->tapedev) = stralloc(device);
+            ct->tape_status = label_result;
+            return 1;
+        } else if (label_result == 2) {
+            if (ct->first_labelstr_slot == NULL)
+                ct->first_labelstr_slot = stralloc(slotstr);
+            return 0;
+        } else {
+            return 0;
+        }
+    }
+    /* NOTREACHED */
+    return 1;
+}
+
+static int 
+scan_init(void *data, int rc, int nslots, int backwards, int searchable) {
+    changertrack_t *ct = ((changertrack_t*)data);
+    
+    if (rc) {
+        newvstralloc(*(ct->error_message), *(ct->error_message),
+                     "could not get changer info: ", changer_resultstr, NULL);
+    }
+
+    ct->backwards = backwards;
+    return 0;
+}
+
+int changer_taper_scan(char* wantlabel,
+                       char** gotlabel, char** timestamp,
+                       char** error_message, char **tapedev) {
+    changertrack_t local_data = {wantlabel, gotlabel, timestamp,
+                                 error_message, tapedev, NULL, 0, 0};
+
+    *gotlabel = *timestamp = *tapedev = NULL;
+    
+    changer_find(&local_data, scan_init, scan_slot, wantlabel);
+    
+    if (*(local_data.tapedev)) {
+        /* We got it, and it's loaded. */
+        return local_data.tape_status;
+    } else if (local_data.first_labelstr_slot) {
+        /* Use plan B. */
+        if (changer_loadslot(local_data.first_labelstr_slot,
+                             NULL, tapedev) == 0) {
+            return scan_read_label(*tapedev, NULL, gotlabel, timestamp,
+                                   error_message);
+        }
+    }
+
+    /* Didn't find a tape. :-( */
+    assert(local_data.tape_status <= 0);
+    return -1;
+}
+
+int taper_scan(char* wantlabel,
+               char** gotlabel, char** timestamp, char** error_message,
+               char** tapedev) {
+
+    *gotlabel = *timestamp = *error_message = NULL;
+    *tapedev = getconf_str(CNF_TAPEDEV);
+
+    if (wantlabel == NULL) {
+        tape_t *tmp;
+        tmp = lookup_last_reusable_tape(0);
+        if (tmp != NULL) {
+            wantlabel = tmp->label;
+        }
+    }
+
+    if (changer_init()) {
+        return changer_taper_scan(wantlabel, gotlabel, timestamp,
+                                    error_message, tapedev);
+    }
+
+    return scan_read_label(*tapedev, wantlabel,
+                           gotlabel, timestamp, error_message);
+}
+
+#define AUTO_LABEL_MAX_LEN 1024
+char* find_brand_new_tape_label() {
+    char *format;
+    char newlabel[AUTO_LABEL_MAX_LEN];
+    char tmpnum[12];
+    char tmpfmt[16];
+    char *auto_pos = NULL;
+    int i, format_len, label_len, auto_len;
+    tape_t *tp;
+
+    if (!getconf_seen(CNF_LABEL_NEW_TAPES)) {
+        return NULL;
+    }
+    format = getconf_str(CNF_LABEL_NEW_TAPES);
+    format_len = strlen(format);
+
+    memset(newlabel, 0, AUTO_LABEL_MAX_LEN);
+    label_len = 0;
+    auto_len = -1; /* Only find the first '%' */
+    while (*format != '\0') {
+        if (label_len + 4 > AUTO_LABEL_MAX_LEN) {
+            fprintf(stderr, "Auto label format is too long!\n");
+            return NULL;
+        }
+
+        if (*format == '\\') {
+            /* Copy the next character. */
+            newlabel[label_len++] = format[1];
+            format += 2;
+        } else if (*format == '%' && auto_len == -1) {
+            /* This is the format specifier. */
+            auto_pos = newlabel + label_len;
+            auto_len = 0;
+            while (*format == '%' && label_len < AUTO_LABEL_MAX_LEN) {
+                newlabel[label_len++] = '%';
+                auto_len ++;
+                format ++;
+            }
+        } else {
+            /* Just copy a character. */
+            newlabel[label_len++] = *(format++);
+        }     
+    }
+
+    /* Sometimes we copy the null, sometimes not. */
+    if (newlabel[label_len] != '\0') {
+        newlabel[label_len++] = '\0';
+    }
+
+    if (auto_pos == NULL) {
+        fprintf(stderr, "Auto label template contains no '%%'!\n");
+        return NULL;
+    }
+
+    sprintf(tmpfmt, "%%0%dd", auto_len);
+
+    for (i = 1; i < INT_MAX; i ++) {
+        sprintf(tmpnum, tmpfmt, i);
+        if (strlen(tmpnum) != auto_len) {
+            fprintf(stderr, "All possible auto-labels used.\n");
+            return NULL;
+        }
+
+        strncpy(auto_pos, tmpnum, auto_len);
+
+        tp = lookup_tapelabel(newlabel);
+        if (tp == NULL) {
+            /* Got it. Double-check that this is a labelstr match. */
+            if (!match(getconf_str(CNF_LABELSTR), newlabel)) {
+                fprintf(stderr, "New label %s does not match labelstr %s!\n",
+                        newlabel, getconf_str(CNF_LABELSTR));
+                return 0;
+            }
+            return stralloc(newlabel);
+        }
+    }
+
+    /* NOTREACHED. Unless you have over two billion tapes. */
+    fprintf(stderr, "Taper internal error in find_brand_new_tape_label.");
+    return 0;
+}
diff --git a/server-src/taperscan.h b/server-src/taperscan.h
new file mode 100644 (file)
index 0000000..39190fb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005 Zmanda Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ * 
+ * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
+ * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
+ */
+
+/*
+ * $Id: taperscan.h,v 1.1 2005/12/21 19:07:51 paddy_s Exp $
+ *
+ * This contains the interface to the tape-scan algorithm implementation.
+ * The interface is rather simple: Calling programs (taper, amcheck,
+ * amtape) call the function below with a desired tape label, and get back
+ * all the relevant label information, along with any other error messages.
+ */
+
+/* taper_scan(): Scans the changer to find a tape to use. Reads the tape
+ *               label, or invents a new one if label_new_tapes is in use.
+ *               Note that the returned label information should not be
+ *               re-read, because there may not actually exist a label
+ *               on-tape (for WORM or newly-labeled media).
+ *
+ * Inputs: wantlabel
+ * Outputs: Returns: -1 if an error occured or no tape was found.
+ *                    1 if the most desirable tape was found.
+ *                    2 if some other labeled tape was found.
+ *                    3 if a brand new tape was found, which we should
+ *                         label ASAP.
+ *          gotlabel: What label was actually retrieved or invented.
+ *         timestamp: What the timestamp string on-tape was. May be "X".
+ *     error_message: Debugging output.
+ *           tapedev: What device to use from now on.
+ *
+ * All returned strings are newly-allocated. */
+
+int taper_scan P((char* wantlabel,
+                  char** gotlabel, char** timestamp, char** error_message,
+                  char **tapedev));
index 6b78e0224fcaaff43052ba1c22faf87cd3449089..e2cfcf78f4daa89d66bb458ddb3135d19f7461ff 100644 (file)
@@ -1,6 +1,7 @@
 # Makefile for Amanda tape library.
 
-INCLUDES =             -I$(top_srcdir)/common-src
+INCLUDES =     -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src
 
 lib_LTLIBRARIES =      libamtape.la
 LIB_EXTENSION = la
index 017739ae6dfc6e0070c53380cd21823fafb39244..aa9f74ba748a30c17890e04f214434f2b43f4100 100644 (file)
@@ -161,7 +161,9 @@ DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
 DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DOC_BUILD_DATE = @DOC_BUILD_DATE@
 DUMP = @DUMP@
+DUMPER_DIR = @DUMPER_DIR@
 ECHO = @ECHO@
 ECHO_C = @ECHO_C@
 ECHO_N = @ECHO_N@
@@ -173,9 +175,12 @@ FFLAGS = @FFLAGS@
 GETCONF = @GETCONF@
 GNUPLOT = @GNUPLOT@
 GNUTAR = @GNUTAR@
+GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@
 GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
 GREP = @GREP@
 GZIP = @GZIP@
+HAVE_XSLTPROC_FALSE = @HAVE_XSLTPROC_FALSE@
+HAVE_XSLTPROC_TRUE = @HAVE_XSLTPROC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -188,6 +193,7 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LL_FMT = @LL_FMT@
 LN_S = @LN_S@
 LTALLOCA = @LTALLOCA@
 LTLIBOBJS = @LTLIBOBJS@
@@ -250,10 +256,13 @@ WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
 WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
 WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
 WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
+WANT_SSH_SECURITY_FALSE = @WANT_SSH_SECURITY_FALSE@
+WANT_SSH_SECURITY_TRUE = @WANT_SSH_SECURITY_TRUE@
 WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
 WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
 XFSDUMP = @XFSDUMP@
 XFSRESTORE = @XFSRESTORE@
+XSLTPROC = @XSLTPROC@
 YACC = @YACC@
 ac_c = @ac_c@
 ac_ct_AR = @ac_ct_AR@
@@ -304,7 +313,9 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-INCLUDES = -I$(top_srcdir)/common-src
+INCLUDES = -I$(top_builddir)/common-src \
+               -I$(top_srcdir)/common-src
+
 lib_LTLIBRARIES = libamtape.la
 LIB_EXTENSION = la
 libamtape_la_SOURCES = output-file.c \
index ca5e1c9e418dd0c34c79666fa489cd3d8ab65fdf..692b525eef8a0871b74e65890a9bdfe7536c7f63 100644 (file)
@@ -156,6 +156,9 @@ main(int argc, char **argv) {
     int save_errno;
     char *s;
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     if((pgm = strrchr(argv[0], '/')) != NULL) {
        pgm++;
     } else {
index bbffaa96ea41810c75af0ffdc8ab28686e1ac4cf..54517f1c4ecf392f8f7da3a18aabb42f05b9d2a3 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 /*
- * $Id: output-file.c,v 1.1.2.4.2.4 2003/05/29 20:13:53 martinea Exp $
+ * $Id: output-file.c,v 1.10 2006/01/14 04:37:20 paddy_s Exp $
  *
  * tapeio.c virtual tape interface for a file device.
  *
@@ -276,7 +276,7 @@ file_open(fd)
                host = tapefd_getinfo_host(fd);
                disk = tapefd_getinfo_disk(fd);
                level = tapefd_getinfo_level(fd);
-               ap_snprintf(number, sizeof(number), "%d", level);
+               snprintf(number, sizeof(number), "%d", level);
                if (host != NULL) {
                    f = stralloc(host);
                }
@@ -313,7 +313,7 @@ file_open(fd)
            }
        }
        if (datafilename == NULL) {
-           ap_snprintf(number, sizeof(number), "%05d", pos);
+           snprintf(number, sizeof(number), "%05d", pos);
            datafilename = vstralloc(volume_info[fd].basename,
                                     number,
                                     DATA_INDICATOR,
@@ -391,7 +391,7 @@ file_close(fd)
                  NULL);
     fi = &volume_info[fd].fi[pos];
     if (fi->ri_altered) {
-       ap_snprintf(number, sizeof(number), "%05d", pos);
+       snprintf(number, sizeof(number), "%05d", pos);
        filename = vstralloc(volume_info[fd].basename,
                             number,
                             RECORD_INDICATOR,
@@ -447,7 +447,7 @@ file_release(fd)
                      10,
                      NULL);
        if (volume_info[fd].fi[pos].name != NULL) {
-           ap_snprintf(number, sizeof(number), "%05d", pos);
+           snprintf(number, sizeof(number), "%05d", pos);
            filename = vstralloc(volume_info[fd].basename,
                                 number,
                                 DATA_INDICATOR,
@@ -816,7 +816,7 @@ file_tapefd_write(fd, buffer, count)
        volume_info[fd].at_bof = 0;
        volume_info[fd].at_eom = 1;
     }
-    result = write(file_fd, buffer, write_count);
+    result = fullwrite(file_fd, buffer, write_count);
     if (result >= 0) {
        volume_info[fd].last_operation_write = 1;
        pos = volume_info[fd].file_current;
@@ -893,8 +893,8 @@ file_tapefd_close(fd)
            errno = save_errno;
            return -1;
        }
-       ap_snprintf(number, sizeof(number),
-                   "%d", volume_info[fd].file_current);
+       snprintf(number, sizeof(number),
+                "%d", volume_info[fd].file_current);
        line = vstralloc("position ", number, "\n", NULL);
        len = strlen(line);
        result = write(fd, line, len);
index 727da962f991cf364eb097f1fbd6bbd7f0bceaad..a0dfd6064969de0ef7ae04ba3f57f435fa4151da 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 /*
- * $Id: output-file.h,v 1.1.2.2.2.2 2003/03/06 21:44:20 martinea Exp $
+ * $Id: output-file.h,v 1.5 2003/03/06 21:43:57 martinea Exp $
  *
  * tapeio.c virtual tape interface for a file device.
  */
index fb8a46edaca55e604f69eda60ce3a649687c647a..1a56faea732afa5c041b3e48bcf7b5d6a014e15e 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 /*
- * $Id: output-null.c,v 1.1.2.3.2.3 2003/03/06 21:44:20 martinea Exp $
+ * $Id: output-null.c,v 1.7 2003/03/06 21:43:57 martinea Exp $
  *
  * tapeio.c virtual tape interface for a null device.
  */
index 72c37a56c566cb91e1d24aa67e82fc5bb212872f..d092fa2eaed517be16c75ac58058c5560288b8f1 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 /*
- * $Id: output-null.h,v 1.1.2.2.2.2 2003/03/06 21:44:20 martinea Exp $
+ * $Id: output-null.h,v 1.5 2003/03/06 21:43:57 martinea Exp $
  *
  * tapeio.c virtual tape interface for a null device.
  */
index bd369651b527ef37911548491d94716de01c57df..c08aa03ab5e20c4070743ea1f1ac767d35f0b585 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 /*
- * $Id: output-tape.c,v 1.1.2.6.2.7 2003/03/06 21:44:21 martinea Exp $
+ * $Id: output-tape.c,v 1.14 2006/03/09 20:06:12 johnfranks Exp $
  *
  * tapeio.c virtual tape interface for normal tape drives.
  */
@@ -475,14 +475,14 @@ int tape_tape_open(filename, flags, mask)
 #ifdef HAVE_LINUX_ZFTAPE_H
     /*
      * switch the block size for the zftape driver (3.04d)
-     * (its default is 10kb and not TAPE_BLOCK_BYTES=32kb)
+     * (its default is 10kb and not 32kb)
      *        A. Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
      */
     if (ret >= 0 && is_zftape(filename) == 1) {
        struct mtop mt;
 
        mt.mt_op = MTSETBLK;
-       mt.mt_count = 32 * 1024;        /* wrong?  tape blocksize??? */
+       mt.mt_count = 32 * 1024;                /* should be blocksize ??? */
        ioctl(ret, MTIOCTOP, &mt);
     }
 #endif /* HAVE_LINUX_ZFTAPE_H */
@@ -615,11 +615,10 @@ tape_tapefd_status(fd, stat)
      * If we did not find any valid information, do a stat on the device
      * and if that returns successfully, assume it is at least online.
      */
-    if(!anything_valid && res == 0) {
+    if(!anything_valid) {
        struct stat sbuf;
 
        res = fstat(fd, &sbuf);
-       anything_valid = 1;
        stat->online_valid = 1;
        stat->online = (res == 0);
     }
index 1aa9fee84378ba30adbd235e3c68293361de4ef7..7c43169c41c6b7deb01f70f661d096c1b353e276 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 /*
- * $Id: output-tape.h,v 1.1.2.2.2.2 2003/03/06 21:44:21 martinea Exp $
+ * $Id: output-tape.h,v 1.5 2003/03/06 21:43:58 martinea Exp $
  *
  * tapeio.c virtual tape interface for normal tape drives.
  */
index 984dddcec9f33c5d0e2da5f008db255d09bf741a..54e2aa0c078520533357936641053686b4b1c5e2 100644 (file)
  */
 
 /*
- * $Id: tapeio.c,v 1.20.4.7.4.4.2.9 2003/11/28 12:34:52 martinea Exp $
+ * $Id: tapeio.c,v 1.53 2006/01/14 04:37:20 paddy_s Exp $
  *
  * implements generic tape I/O functions
  */
 
 #include "amanda.h"
+#include <stdarg.h>
 #include <errno.h>
 
 #include "tapeio.h"
@@ -49,7 +50,7 @@
 static struct virtualtape {
     char *prefix;
     int (*xxx_tape_access) P((char *, int));
-    int (*xxx_tape_open) ();
+    int (*xxx_tape_open) (char *, int, int);
     int (*xxx_tape_stat) P((char *, struct stat *));
     int (*xxx_tapefd_close) P((int));
     int (*xxx_tapefd_fsf) P((int, int));
@@ -528,14 +529,17 @@ tape_stat(filename, buf)
 }
 
 int
-tape_open(filename, mode, mask)
-    char *filename;
-    int mode;
-    int mask;
+tape_open(char *filename, int mode, ...)
 {
     char *tname;
     int vslot;
     int fd;
+    int mask;
+    va_list ap;
+
+    va_start(ap, mode);
+    mask = va_arg(ap, int);
+    va_end(ap);
 
     vslot = name2slot(filename, &tname);
     if((fd = vtable[vslot].xxx_tape_open(tname, mode, mask)) >= 0) {
@@ -797,7 +801,7 @@ tape_fsf(devname, count)
                                  strerror(errno),
                                  NULL);
     } else if(tapefd_fsf(fd, count) == -1) {
-       ap_snprintf(count_str, sizeof(count_str), "%d", count);
+       snprintf(count_str, sizeof(count_str), "%d", count);
        r = errstr = newvstralloc(errstr,
                                  "tape_fsf: fsf ",
                                  count_str,
@@ -812,6 +816,10 @@ tape_fsf(devname, count)
     return r;
 }
 
+/* Reads the tape label, like you expect. If failure, returns an error
+   string. If the tape might not be an Amanda tape, the returned
+   string will start with NOT_AMANDA_TAPE_MSG. */
+
 char *
 tapefd_rdlabel(fd, datestamp, label)
     int fd;
@@ -833,23 +841,26 @@ tapefd_rdlabel(fd, datestamp, label)
        *datestamp = stralloc("X");
        *label = stralloc(FAKE_LABEL);
     } else if(tapefd_rewind(fd) == -1) {
-       r = errstr = newstralloc2(errstr, "rewinding tape: ", strerror(errno));
+       r = stralloc2("rewinding tape: ", strerror(errno));
     } else if((rc = tapefd_read(fd, buffer, buflen)) == -1) {
-       r = errstr = newstralloc2(errstr, "reading label: ", strerror(errno));
+       r = vstralloc(NOT_AMANDA_TAPE_MSG, " (",
+                      strerror(errno), ")", NULL);
+    } else if (rc == 0) {
+        r = stralloc2(NOT_AMANDA_TAPE_MSG, " (Read 0 bytes)");
     } else {
-
        /* make sure buffer is null-terminated */
        buffer[rc] = '\0';
 
        parse_file_header(buffer, &file, rc);
        if(file.type != F_TAPESTART) {
-           r = errstr = newstralloc(errstr, "not an amanda tape");
+           r = stralloc(NOT_AMANDA_TAPE_MSG);
        } else {
            *datestamp = stralloc(file.datestamp);
            *label = stralloc(file.name);
        }
     }
     amfree(buffer);
+    errstr = newvstralloc(errstr, r, NULL);
     return r;
 }
 
@@ -863,18 +874,18 @@ tape_rdlabel(devname, datestamp, label)
     char *r = NULL;
 
     if((fd = tape_open(devname, O_RDONLY)) < 0) {
-       r = errstr = newvstralloc(errstr,
-                                 "tape_rdlabel: tape open: ",
-                                 devname,
-                                 ": ",
-                                 strerror(errno),
-                                 NULL);
-    } else if(tapefd_rdlabel(fd, datestamp, label) != NULL) {
-       r = errstr;
-    }
+       r = vstralloc("tape_rdlabel: tape open: ",
+                      devname,
+                      ": ",
+                      strerror(errno),
+                      NULL);
+    } else
+        r = tapefd_rdlabel(fd, datestamp, label);
+
     if(fd >= 0) {
-       tapefd_close(fd);
+        tapefd_close(fd);
     }
+    errstr = newvstralloc(errstr, r, NULL);
     return r;
 }
 
@@ -1373,6 +1384,9 @@ main(argc, argv)
     int j;
     time_t now;
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
     if((pgm = strrchr(argv[0], '/')) != NULL) {
        pgm++;
     } else {
index c3783192c568c2d8ccf33262081ea5f5b27a9a6d..564ab99d1cecc9554ff64afbf8e64a346f3aa778 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: tapeio.h,v 1.9.2.2.4.3.2.3 2003/03/07 20:55:37 martinea Exp $
+ * $Id: tapeio.h,v 1.20 2005/12/21 19:07:51 paddy_s Exp $
  *
  * interface for tapeio.c
  */
@@ -33,6 +33,7 @@
 #define TAPEIO_H
 
 #include "amanda.h"
+#include "util.h" /* For BSTRNCMP */
 
 /*
  * Tape drive status structure.  This abstracts the things we are
@@ -65,8 +66,9 @@ struct am_mt_status {
 };
 
 #define        FAKE_LABEL      "[fake-label]"
+#define NO_LABEL        "[no-label-yet]"
 
-int tape_open ();
+int tape_open (char *, int, ...);
 
 int tapefd_rewind P((int tapefd));
 int tapefd_unload P((int tapefd));
@@ -85,6 +87,10 @@ char *tapefd_wrlabel P((int tapefd,
                        char  *datestamp,
                        char  *label,
                        unsigned int s));
+
+char *auto_tapefd_label P((int tapefd, char **datestamp, char **label));
+char *auto_tape_label P((char *dev, char **datestamp, char **label));
+
 char *tapefd_wrendmark P((int tapefd, char *datestamp, unsigned int s));
 
 int tapefd_eof P((int tapefd));                /* just used in tapeio-test */
@@ -139,4 +145,7 @@ char *tapeio_next_devname P((char * dev_left,
                             char * dev_right,
                             char **dev_next));
 
+#define NOT_AMANDA_TAPE_MSG "not an amanda tape"
+#define CHECK_NOT_AMANDA_TAPE_MSG(x) (!BSTRNCMP(x, NOT_AMANDA_TAPE_MSG))
+
 #endif /* ! TAPEIO_H */
index 50340ad850c4882daaef000c3acd5894c79cb96c..dd4758187b91b398b3cb48265c3bc71dcefbe222 100644 (file)
@@ -25,7 +25,7 @@
  *                        University of Maryland at College Park
  */
 /*
- * $Id: tapetype.c,v 1.3.2.3.4.3.2.9.2.3 2005/10/02 13:48:42 martinea Exp $
+ * $Id: tapetype.c,v 1.24 2006/03/10 11:56:06 martinea Exp $
  *
  * tests a tape in a given tape unit and prints a tapetype entry for
  * it.  */
@@ -45,6 +45,7 @@ static int blockkb = 32;
 static int blocksize;
 
 static char *randombytes = (char *) NULL;
+static char *prandombytes = (char *) NULL;
 
 #if USE_RAND
 /* If the C library does not define random(), try to use rand() by
@@ -74,6 +75,7 @@ static void allocrandombytes() {
     } else {
       randombytes = p;                         /* alloc already on boundary */
     }
+    prandombytes = p;
   }
 }
 
@@ -322,6 +324,9 @@ int main(argc, argv)
     sProgName++;
   }
 
+  /* Don't die when child closes pipe */
+  signal(SIGPIPE, SIG_IGN);
+
   estsize = 1024 * 1024;                       /* assume 1 GByte for now */
   tapedev = getenv("TAPE");
   typename = "unknown-tapetype";
@@ -599,14 +604,17 @@ int main(argc, argv)
   if (tapefd_rewind(fd) == -1) {
     fprintf(stderr, "%s: could not rewind %s: %s\n",
            sProgName, tapedev, strerror(errno));
+    free(randombytes);
     return 1;
   }
 
   if (tapefd_close(fd) == -1) {
     fprintf(stderr, "%s: could not close %s: %s\n",
            sProgName, tapedev, strerror(errno));
+    free(randombytes);
     return 1;
   }
 
+  free(randombytes);
   return 0;
 }