summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBdale Garbee <bdale@gag.com>2009-02-15 18:17:54 +0100
committerBdale Garbee <bdale@gag.com>2009-02-15 18:17:54 +0100
commit1c3607e4d1f94869e7887568fb40d16bb0d2407d (patch)
treef7a37bbbea5791814281affed9da11b47fbd080b
Import mtx_1.3.12.orig.tar.gz
[dgit import orig mtx_1.3.12.orig.tar.gz]
-rw-r--r--CHANGES373
-rw-r--r--COMPATABILITY163
-rw-r--r--FAQ144
-rw-r--r--LICENSE280
-rw-r--r--LICENSE.html515
-rw-r--r--Makefile.in176
-rw-r--r--README38
-rw-r--r--README.win3245
-rw-r--r--TODO15
-rwxr-xr-xbuild.win3215
-rwxr-xr-xconfig.guess1500
-rw-r--r--config.h.in37
-rwxr-xr-xconfig.sub1616
-rwxr-xr-xconfigure6545
-rwxr-xr-xconfigure.in113
-rw-r--r--contrib/MTX.html209
-rw-r--r--contrib/README3
-rw-r--r--contrib/TapeChanger-MTX-0.71b.tar.gzbin0 -> 6179 bytes
-rwxr-xr-xcontrib/config_sgen_solaris.sh151
-rwxr-xr-xcontrib/mtx-changer431
-rw-r--r--contrib/mtx.py306
-rw-r--r--contrib/mtxctl-0.0.2.tar.gzbin0 -> 5688 bytes
-rw-r--r--contrib/qdback.tar.gzbin0 -> 11072 bytes
-rw-r--r--contrib/tapechanger.html209
-rw-r--r--contrib/tapeinfo.py55
-rw-r--r--contrib/tapeload.pl118
-rw-r--r--contrib/tapeunload.pl98
-rw-r--r--debian/bash_completion45
-rw-r--r--debian/changelog159
-rw-r--r--debian/compat1
-rw-r--r--debian/control16
-rw-r--r--debian/copyright15
-rw-r--r--debian/dirs2
-rwxr-xr-xdebian/rules69
-rw-r--r--du/defs.h25
-rw-r--r--du/scsi.c214
-rwxr-xr-xinstall-sh253
-rw-r--r--loaderinfo.190
-rw-r--r--loaderinfo.c510
-rwxr-xr-xmakedist19
-rw-r--r--mam2debug.c124
-rw-r--r--mam2debug2.c124
-rw-r--r--msvc/config.h37
-rw-r--r--msvc/loaderinfo/loaderinfo.vcproj205
-rw-r--r--msvc/mtx.sln50
-rw-r--r--msvc/mtx/Distributions.txt49
-rw-r--r--msvc/mtx/mtx.vcproj247
-rw-r--r--msvc/nsmhack/nsmhack.vcproj213
-rw-r--r--msvc/scsieject/scsieject.vcproj203
-rw-r--r--msvc/scsitape/scsitape.vcproj203
-rw-r--r--msvc/tapeinfo/tapeinfo.vcproj213
-rw-r--r--mtx.1257
-rw-r--r--mtx.c1075
-rw-r--r--mtx.doc209
-rw-r--r--mtx.h607
-rw-r--r--mtx.spec109
-rw-r--r--mtx.spec.in109
-rw-r--r--mtxl.README.html165
-rw-r--r--mtxl.c1907
-rw-r--r--mtxl.h109
-rw-r--r--nsmhack.c342
-rw-r--r--scsi_aix.c159
-rw-r--r--scsi_freebsd.c116
-rw-r--r--scsi_hpux.c134
-rw-r--r--scsi_linux.c491
-rw-r--r--scsi_sgi.c81
-rw-r--r--scsi_sun.c156
-rw-r--r--scsi_win32.c355
-rw-r--r--scsieject.1116
-rw-r--r--scsieject.c255
-rw-r--r--scsitape.1179
-rw-r--r--scsitape.c941
-rw-r--r--sg_err.c645
-rw-r--r--sg_err.h140
-rw-r--r--tapeinfo.172
-rw-r--r--tapeinfo.c969
-rw-r--r--vms/000readme175
-rw-r--r--vms/build.com34
-rw-r--r--vms/defs.h42
-rw-r--r--vms/descrip.mms77
-rw-r--r--vms/ldrset.c183
-rw-r--r--vms/ldrset.cld9
-rw-r--r--vms/ldrutil.mar104
-rw-r--r--vms/scsi.c400
84 files changed, 26963 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..aa5439c
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,373 @@
+CHANGES, mtx 1.3.12
+- Incorporate debian packaging
+- Remove strip of binaries
+- Remove unsupported nsmhack from list of binaries built by default
+- Add support for building outside of source tree
+- Update copyrights
+- Fix typo in mtx.1 man page
+- Clear outstanding UNIT ATTENTION state at start
+
+CHANGES, mtx 1.3.11
+- loaderinfo: Print RequestSense information if an operation fails.
+- loaderinfo: Print all information from the Device Configuration Page.
+- mtx: Fix problems with a lot of loaders determining the number of elements.
+- mtx: Implement Previous command.
+- mtx: Fix bugs in Last command.
+- scsieject: New tool that handles start/stop, load/unload.
+- tapeinfo: Fix inconsistencies in output.
+- Fix timeout handling on Linux.
+- Merge in fixes from the Debian and FreeBSD distributions.
+
+CHANGES, mtx 1.3.10
+- Add support for Microsoft Windows.
+- Add support for Sony VGP-XL1B(2) Media Changer.
+ Thanks to Will (nodenet at hotmail dot com)
+- Add build support for Microsoft Windows using MinGW native and Linux
+ cross-compile.
+- Add build support for Microsoft Windows using Microsoft Visual Studio 2005.
+- Add support for building on x86_64.
+- Add more debugging information.
+- Eliminate compiler warnings.
+
+CHANGES, mtx 1.3.9
+- Cleaned up scsi_linux.c a little to eliminate around 40 lines of code.
+- Change to using SG_IO ioctl rather than write-read interface. This
+ should make us a little safer, as well as (on 2.6.x) letting us issue SCSI
+ commands to regular block devices as well as to /dev/sgXX devices.
+ WARNING: Can cause the system to *CRASH* if the SCSI device is in use, due
+ to brokenness inside the Linux kernel! It's always preferable to use the
+ /dev/sgXX device, which has specialness in its buffer handling that bypasses
+ some of the brokenness elsewhere in the SCSI subsystem.
+- Check SG version before using SG_IO interface, so that if we're run on a
+ Linux 2.2 system and we were compiled on Linux 2.4 or above,
+- If a tape is in the drive, make tapeinfo print out its partition info. Seems
+ to work on my DAT drive, anyhow (shrug).
+- Minor cleanups in mtxl.c (other cleanups necessary in tapeinfo and etc.).
+
+CHANGES, mtx 1.3.8
+- Forgot about 8 bytes for header
+- Handle pedantic loader whose firmware writer spends too much time
+ parsing phrases in the SCSI spec and not enough time in the
+ real world.
+
+CHANGES, mtx 1.3.6
+- The You Gotta Be F'ing Kidding Release (see rant on mailing list)
+- Added AIX support with http://fz.eryx.net/aix/ GSC driver, courtesy
+ of Steve Heck.
+- Make __WEIRD_CHAR_SUPPRESS the default to stop barcode garbling
+- Fix core dump on invalid inputs in mtx.c
+- Add retry with bigger ALLOCATION_LENGTH if
+ BYTE_COUNT_OF_REPORT_AVAILABLE is > than our original estimate. (see rant
+ on mailing list).
+- Shut up the low-level SCSI sg_read and sg_write routines, which were poofting
+ all over the place on innocuous things like no EAAP.
+
+CHANGES, mtx 1.3.5
+- The I-Need-A-Job Release (see http://badtux.org) :-}
+- Change Makefile so that it works w/systems whose 'install' program
+ accepts only one argument. That's it.
+- Uncomment the Exabyte hack in the drive parsing code so that it works
+ with ATL loaders again.
+- Add hack for ATL stacked loaders to keep them from reporting ghost slots
+
+CHANGES, mtx 1.3.4
+- Forward-ported the ATL/Exabyte patches from mtx 1.2
+- Added progress indicator to 'tapeinfo' for DAT drives. (PLEASE TEST)
+- Purged a few more estinc.com out of the documentation, point to bru.com.
+
+CHANGES, mtx 1.3.3
+- Reversed James' long descriptor patch until can figure out what's wrong with
+ it.
+- Fixed some debug declarations, courtesy of Kevin Wang.
+- Point COMPATIBILITY file at mtx.sourceforge.net.
+
+CHANGES, mtx 1.3.2
+- Merged Makefile changes from mtx-1.2 code
+- Changes from James Dugal to get all info for newer loaders, fix debugging
+
+CHANGES, mtx 1.3.1
+- add an Exchange command
+
+CHANGES, mtx 1.3.0
+- New Linux SCSI subsystem interface for 2.4 kernels, ripped boldly
+ from sgtools by Doug Gilbert
+- mtx 'next' now skips blank slots, courtesy of Christopher McCrory
+- mtx 'unload' now prints an error message telling you that you need to
+ eject the tape in the drive prior to unloading it, under certain
+ conditions.
+- Started work on 'nsmhack' for controlling NSM jukeboxes.
+- copy_barcode was off by one.
+- 'position to element' command now added, courtesy of Mahlon Stacy
+
+CHANGES, mtx 1.2.15:
+- Some Solaris fixes, courtesy of Matt Ward
+- Fix URL in .spec file
+
+CHANGES, mtx 1.2.14:
+- Fix so it'll work if 0 is result of SCSI open (e.g., in cron jobs on Linux)
+- Move changelog to end of .spec file for easier reading
+- Added a bit of text to beginning of COMPATIBILITY file
+
+CHANGES, mtx 1.2.13:
+- Fixed some autoloader bugs w/autoloaders that don't report an arm.
+- Fixed barcode backoff.
+- Added "nobarcode" option
+- Increased timeout for 'mtx inventory' to 30 minutes
+ (note: may increase this even more if needed, please let me know!)
+- Shortened timeout for 'mtx inquiry' to 30 seconds
+- tapeinfo now prints SCSI ID/LUN info if available (only on Linux at the
+ moment, sigh).
+- update documentation w/new email addresses, updated compile directions,
+ various fixes.
+
+CHANGES, mtx 1.2.12:
+- Fix FreeBSD compile bugs
+- Fix SGI compile bugs
+- Add HP/UX port (I hope!), courtesy of William Smith.
+- Re-wrote ReadElementStatus to make work for %!@# brain dead firmware that
+ reports non-existent drives (I hope!). Also has side-effect of now working
+ with multiple-arm libraries (though it only sees first arm!).
+- Cleaned up all -Wall messages.
+- Cleaned up Linux Sparc, installs loaderinfo.1, courtesy of Matt Dainty.
+- tapeinfo now reports status of CheckUnitReady.
+- tapeinfo no longer puts out Block Position if CheckUnitReady says 'no'.
+- tapeinfo now puts out Density Code and Medium Type/Not Loaded (modification
+ of patches sent in by Bob Rahe)
+
+CHANGES, mtx 1.2.11:
+- Added a GNU autoconf Makefile.in (still provide a Makefile for your use)
+ *WARNING* autoconf is not yet working on all supported OS's! You may need
+ to do the old-fashioned 'edit Makefile' bit!
+- Changed mtx.h and mtxl.c to include and define various things based upon
+ what features autoconf detected (e.g., if 'camlib.h', use FreeBSD-style
+ 'cam', if 'scsi/sg.h' use Linux-style 'sg', etc.). If I ever port to a
+ Unix that has same SCSI interface as one of the existing ports, autoconf
+ will handle it without me having to add another set of #if's or #ifdefs.
+- Went ahead and tossed mtxctl into contrib.
+- In 'tapeinfo', skip \0 characters in serial numbers (some use \0
+ terminator, some do not, skip it if this one does).
+- in 'tapeinfo', dump out the block position and (if at BOP) the "BOP: Yes"
+ flag. Also dump out other info such as block limits.
+- Put file 'sparc-patch1' contributed by Chaskiel M Grundman, and applied
+ it (sigh)
+- Added tapeinfo.py to 'contrib' directory
+- Updated mtx.py in 'contrib' directory
+- Created 'loaderinfo' program to report some misc. info about loaders.
+- Created 'scsitape' program so that I don't have to keep messing with
+ #@$%@! tape ioctls on the various Unixes that I'm porting tape software
+ to. (But see the warnings!).
+- Applied the Solaris patch to the read_element_status command (sigh).
+- Added timeout adjustment to the SCSI subsystem.
+- WARNING: DIGITAL UNIX AND VMS ARE PROBABLY IRREPERABLY BROKEN, due to the
+ timeout changes to the SCSI subsystem. If anybody wishes to fix them,
+ feel free to send me patches.
+- added contrib program "mtx-changer" (an Amanda tape changer script for
+ ?Solaris? that uses mtx rather than stc)
+- Jiggered Linux SCSI module for smarter error conditions handling (there are
+ some error conditions that are normal for READ of tape drives).
+- Added contrib program "config_sgen_solaris.sh" which should ease
+ setting up the 'sgen' driver on Solaris 8 (still no easy Solaris 7 or
+ below config).
+
+CHANGES, mtx 1.2.10:
+- Added FAQ and COMPATIBILITY (feel free to send me patches to these files!)
+- Added LICENSE
+- Added serial number to 'tapeinfo' output.
+- Fixed stupid syntax error in mtx.c (compiled with gcc, not with others!)
+- Fixed spec file for building rpms (maybe).
+- Added an 'erase' command (undocumented) for use on Linux for doing
+ short erases on tapes (the Linux device driver defaults to a long erase).
+- Made mtx inventory return an error code if the inventory
+ fails, so that we can wait for inventory to be completed at system
+ startup for libraries that auto-inventory (sigh).
+
+CHANGES, mtx 1.2.9:
+- Added an 'eject' command that, if directed to a tape drive, will eject the
+ tape, and for some autoloaders, if directed to LUN 1, will eject the entire
+ magazine.
+- Fixed the 'transfer' command to be 1 based rather than 0 based (sigh)
+- Now properly reports bar code for the tape that's in the tape drive.
+- Added some miscellaneous Python and Perl scripts to 'contrib'. Thanks
+ to Frank Samuelson for the Perl scripts.
+
+CHANGES, mtx 1.2.8:
+- Spec file has been changed to use the "portable" patch supplied by Red
+ Hat so it should work on Linux Alpha and Linux SPARC too... maybe...
+- Now will accept 4-byte element status for most element types, despite fact
+ that these don't comply with SCSI standards :-(. This should make many
+ older changers work, including HP optical changers.
+- Fixed PeripheralDeviceType table, courtesy of Rob Turk.
+- Now looks for CHANGER environment variable if a device is not specified
+ on the command line. If can't find CHANGER, then tries TAPE environment
+ variable.
+- Properly sets TransportElementAddress in the CDB for the MOVE MEDIUM command
+ with what was discovered via the READ_ELEMENT_STATUS command, rather
+ than setting them to zero (SCSI spec says that zero should be the default
+ arm, but at least one changer out there didn't like it).
+- Added a '--version' command (sigh).
+- Added an 'inventory' command for Breece Hill libraries that don't
+ automatically do an inventory at powerup.
+
+CHANGES, mtx 1.2.7:
+- Fixed problem w/single drive Exabyte 220 reporting element status data for
+ both drives (sigh).
+- some general cleanup in the barcode fallback code (what a cruft!). Discovered
+ that ADIC DAT AUTOCHANGER does not work w/mtx because it produces
+ gibberish (will apparently only produce one element status page per request).
+- Fixed the RPM .spec file to have updated file locations, doc locations.
+- Fixed MoveMedium to say 'Output' for direction, to make it work with
+ Solaris 8
+- Some changes to the Solaris low-level module to report more errors (though
+ it still doesn't work as well as the Linux low-level module). Should now
+ work properly with Solaris 2.6/7/8. (Solaris changes courtesy of Richard
+ Fish of Enhanced Software Technologies).
+
+CHANGES, mtx 1.2.6:
+- Fixed 'eepos' stuff to use | rather than || (whoops!)
+- Accept a 4-byte element descriptor for the robot arm for certain older
+ autochangers.
+
+CHANGES, mtx 1.2.5:
+- Added 'noattach' command. If on command line prior to other commands, forces
+ them to use the regular SCSI changer API rather than the _ATTACHED API,
+ no matter what the _ATTACHED bit in the Inquiry page said.
+- Created 'tapeinfo' program.
+
+CHANGES, mtx 1.2.4:
+- Major overhaul of element guts to dynamically allocate the arrays
+ using the result of a MODE_SENSE on the Element Address Assignment
+ Page. If mtx 1.2.3 works for you and mtx 1.2.4 does NOT work for you,
+ please un-comment the '#define DEBUG_MODE_SENSE' in file 'mtxl.c' and
+ EMAIL me the results.
+
+CHANGES, mtx 1.2.3:
+- Fixed the source storage element number stuff (again, sigh)
+- Because of above fix, 'next' etc. ought to work right again.
+
+CHANGES, mtx 1.2.2:
+- Fixed that it was saying everything was an Import/Export element (oops!)
+- Properly update the Import/Export element count.
+
+CHANGES, mtx 1.2.1:
+- Now explicitly output that a Storage element is in fact an Import/Export
+ element.
+- Added 'transfer' command to transfer between two Storage elements (so that
+ you can get a tape to an Import/Export element.
+- Added 'eepos' command for controlling tray retraction on the Breecehill
+ import/export trays. (Works with "load" and "unload" commands too, though
+ that is not documented on "mtx -h").
+
+CHANGES, mtx 1.2.0:
+- Re-numbered now that Leonard has asked me to take over maintenance of the
+ 'mtx' program.
+- Temporarily treat Import/Export elements the same as Storage elements. Need
+ to fix this eventually so that the GUI knows what kind of element we're
+ talking about.
+- Removed quotes from the source element # to make it easier to parse
+ from Perl or Python (just do a split on spaces).
+- Added sample program, 'mam2debug', showing how to use mtxl library for
+ your own programs (this happens to dump the Exabyte Mammoth 2's internal
+ debug buffer to a file, using the Mammoth2-specific SCSI commands to do so).
+
+CHANGES, mtxl 1.4.8:
+- Whoops, report logical rather than physical when I have to scan for
+ open slots :-).
+
+CHANGES, mtxl 1.4.7:
+- Update comment to reflect mtxl 1.4.6 stuff :-).
+- Fix the part of the code that scans for open slots as sources for media.
+
+CHANGES, mtxl 1.4.6:
+- Don't use _ATTACHED interface if it reports itself as a Medium Changer!
+
+CHANGES, mtxl 1.4.5:
+- Changed "whoops" compile error on Linux (teach me to release w/o testing on
+ the most popular platform!)
+- Changed declarations to remove compile-time warnings.
+
+CHANGES, mtxl 1.4.4:
+- Added support for FreeBSD. (uses pass device, NOT native FreeBSD ch device).
+- Change all 'int' DeviceFD to DEVICE_TYPE DeviceFD. Note that SGI and FreeBSD
+ use a struct * to access the CAM SCSI layer, rather than a file fd.
+- Fixed goof where I'd hard-wired max # of elements to 127 for testing
+ purposes (it should be sum of MAX_STORAGE_ELEMENTS + MAX_TRANSFER_ELEMENTS
+ + MAX_TRANSPORT_ELEMENTS from mtx.h -- change those if you need more
+ elements, bearing in mind that the code for ReadElementStatus in
+ mtxl.c maxes out at 255 elements unless you fix that too).
+- Cleaned some cruft out of the MOVE_MEDIUM code.
+- Must have GNU Make to process Makefile. In reality, I don't know of
+ any machine where we voluntarily use the native 'make' command, because
+ a) there's a half dozen native 'make' all with their own perverted
+ syntaxes, and b) most of them are brain dead beyond belief.
+
+CHANGES, mtxl 1.4.3:
+- Do an INQUIRY prior to doing a MOVE_MEDIUM or READ_ELEMENT_STATUS so that I
+ can detect the MChanger bit and use MOVE_MEDIUM_ATTACHED or
+ READ_ELEMENT_STATUS_ATTACHED commands instead.
+- Successfully tested with dual drives!
+- first, next, last now working
+- Created a man page
+- Created a 'make install', edit Makefile to alter destinations.
+
+CHANGES, mtxl 1.4.2:
+- Found the problem with the DAT changer! It was burping on the
+ 'bar code' bit... so I intercept that sense key, re-issue w/out the
+ 'bar code' bit, and success!
+- Added a 'TODO' file...
+
+CHANGES, mtxl 1.4.1:
+- Added 'invert' qualifier to 'load' and 'unload' commands to invert
+ the media (for HP optical jukeboxes). Type './mtx' by itself to
+ see the syntax.
+- Figured out why my code wasn't properly detecting errors --
+ turns out the 'sg' device can return ok
+ status even when there is sense data to be reported!
+- Still to fix: *still* isn't working right with my Seagate
+ 6-tape DDS-4 DAT changer... also need to put the
+ second drive into the Exabyte 220 to make sure the dual-drive stuff
+ works properly (!).
+
+CHANGES, mtxl 1.4:
+- Have now tested the barcode (volume tag) stuff. It works! (Well, there was
+an index-by-one problem that I had to squash, but after that...)
+- Changed to use SCSI Generic device API on Linux rather than
+SCSI_IOCTL_SEND_COMMAND API, which cut things off at 4095 bytes on i386
+Linux.
+- Added a bunch of debugging output that needs to be ripped out :-(.
+Make sure you remove the -DDEBUG from the Makefile, and probably
+ -DLONG_PRINT_REQUEST_SENSE too (unless you LIKE sense results that make
+sense!)
+- Still have annoying bug on Linux of only reading 1st 16 bytes of sense
+data. Alas, this appears to be a problem in the Linux 2.2 kernel, not in
+anything that we're doing :-(. Hmm... cdrecord has the same problem, Mr.
+Schilling says he's been saying it's a problem since 1997. Sigh.
+- Still need to test the dual-drive stuff!
+
+CHANGES, mtxl 1.3:
+- Hacked in the barcode (volume tag) stuff. NEED SOMEONE TO TEST
+WHETHER IT WORKS!
+- started issuing redundant initial READ_ELEMENT_STATUS with Allocation Length
+of 8 in order to get a BYTE_COUNT_OF_REPORT_AVAILABLE in order to calculate a
+better Allocation Length for the "real" READ_ELEMENT_STATUS. Trying to send a
+query to a small 6-tape changer with an Allocation Length suited for a
+200-element tape library was resulting in some errors and lockups on the
+part of the tape changer device.
+- first, last, next, previous are STILL broken. Sorry :-(.
+
+CHANGES, mtxl 1.2:
+
+- Changed many output messages to make them more easily parsed by
+scripts written in awk/perl/python
+- Extracted out a library of SCSI tape library routines usable by "C"
+programs (must be GPL'ed). Extensive re-arranging of code.
+- Added support for multiple drives.
+- Started adding support for tape changers that use the "MCHangr"
+bit rather than a separate ID or LUN.
+- Increased limits so we could deal with LARGE tape libraries.
+- Started adding support for barcode readers in said tape libraries
+- broke first, last, next, previous. Sorry :-(.
+- Added ability to chain commands on command line. Thus could say 'mtx -f
+/dev/sg4 unload 4 0 load 7 0' to unload a tape from drive 0 and load the
+tape in slot 7 into drive 0.
+
+
diff --git a/COMPATABILITY b/COMPATABILITY
new file mode 100644
index 0000000..e8cde0d
--- /dev/null
+++ b/COMPATABILITY
@@ -0,0 +1,163 @@
+WARNING: THIS FILE IS OBSOLETE AND FOR HISTORICAL USE ONLY. Please
+see http://mtx.sourceforge.net for a more up-to-date compatibility list.
+
+Operating Systems:
+-----------------
+
+mtx 1.2 is currently known to work flawlessly under the following
+operating systems:
+
+Linux (2.2.5 kernel and above)
+FreeBSD (tested with versions 3.2 and above, but should work for all 3.x
+ and 4.x).
+
+Various people have reported that they have managed to make mtx work
+on various versions of Solaris. Please check the mtx list archives (
+http://mtx.sourceforge.net ) to see how they've done it.
+
+IRIX 6.5 apparently works flawlessly:
+
+(Richard.Lefebvre(@AROBAS)cerca(.POINT)umontreal(.POINT)ca):
+I just wanted to send you 1 or 2 comments on mtx. I just downloaded it
+last friday to use with and SGI Origin2000 and an 8 slot DLT autoloader.
+The whole thing compiled fine (under gcc).
+
+From Dan Wright (dtwright at uiuc dot uiuc.edu):
+ I just wanted to send an e-mail to let you know that mtx 1.2.9
+ works great for me on IRIX 6.5 with an ADIC FastStor DLT8000.
+ IRIX 6.5 has a generic scsi interface installed by default, so to
+ access the autoloader I use "mtx -f /dev/scsi/sc1d1l0" (bus 1 id 1
+ lun 0).
+
+----------------
+Changer Devices
+----------------
+The following has been directly tested:
+
+* Exabyte 220 with 1 drive (21 slots)
+* Exabyte 220 with 2 drives (21 slots)
+* Exabyte EZ-17 (7 slots)
+ Known quirks: Must eject tape using 'mt' or 'tapectl' prior to using
+ the 'unload' command.
+
+* Seagate DDS-4 DAT AutoLoader (1 drive, 6 slots)
+ Product ID: 'DAT 06241-XXX'
+ Known quirks: Uses LUN 1 for robot. On Linux, must compile kernel with
+ "Scan SCSI LUNs" or add the following line to your /etc/lilo.conf (and
+ re-run /sbin/lilo):
+ append="max_scsi_luns=2"
+
+* DISC D-40 optical library (2 drives, 40 slots, 1 import/export): Yes,
+ it really does report that it's a Maxoptix!
+ Product Type: Medium Changer
+ Vendor ID: 'Maxoptix'
+ Product ID: 'MAXLYB '
+ Revision: '3.04'
+ Attached Changer: No
+
+The following have been tested by others, and information may be
+incomplete or in error even.
+
+* Compaq DLT Library 20/40, 1 drive 15 slots (antony at elizatravel dot com)
+ Vendor: HP Model: C5173-4000
+
+* Vendor ID: 'ADIC ' (boris dot klug at ibs dash ag dot de)
+ Product ID: 'VLS DLT ' 7 slot 1 import/export 1 drive.
+
+* Unknown Overland changer (phreno at pacbell dot net):
+> > > Vendor ID: 'OVERLAND'
+> > > Product ID: 'LXB '
+
+* "old Exabyte 10e tape loaders" (drew at pctc dot com)
+
+* Unknown HP DLT changer: (eric at collab dot net)
+> > Storage Changer /dev/sgd:1 Drives, 15 Slots ( 0 Import/Export )
+> > Vendor ID: 'HP '
+> > Product ID: 'C5173-4000 '
+
+* "Lago Sys LS-380L/StorageTek 9704/Imation ITL-2225 (mine's a
+ StorageTek labeled)" 25-slot, 2-drive, 1-arm, 1-import/export
+ (eswan at lips dot net)
+
+* HP SureStore Optical 80fx. (mmarchione at nyhomes dot org )
+ Vendor: HP Model: C1160F Rev: 0.40
+ Type: Medium Changer ANSI SCSI revision: 02
+
+* Breece Hill tape library (unknown configuration, unknown reporter):
+ Vendor ID: 'BHTI'
+ Product ID: 'Q2 '
+ Oddities: Must either turn on auto-inventory, or run 'mtx inventory'
+ prior to running any other mtx command. Reads bar codes by yanking
+ tapes out of slots and waving them in front of bar code reader, so
+ inventory of tapes with no bar code is VERY slow (bar code your tapes!).
+
+
+* Seagate Scorpion DDS-3 4-tape autochanger
+ (jsled at normandy dot smarttouch dot com):
+ Vendor ID: 'ARCHIVE '
+ Product ID: 'Python 04377-XXX'
+
+* Overland 15 tape 1 drive DLT changer: (asmith at umdgrb dot umd dot edu)
+ Vendor ID: 'OVERLAND'
+ Product ID: 'LXB '
+
+* ADIC DAT AutoChanger -- 1 drive, 12 slots, 1 import-export:
+ Vendor ID: 'ADIC ' (andrew_gray at irobotics dot com)
+ Product ID: 'DAT AutoChanger '
+ Quirks: firmware version 0357 does not appear to work w/mtx (request
+ from ADIC that they upgrade your firmeware to 0361, which does
+ seem to work), firmware version revision `0462` does work. Use
+ 'mtx inquiry' to detirmine which firmware you have.
+
+* HP 1/20 DLT loader: "We have a HP 1/20, but I think it's all the
+ same hardware. mtx works fine with it." (jo2y at midnightlinux dot com)
+
+* Exabyte 120 (116 slots, 4 tape drives): (wsb at paralleldata dot com)
+ Quirks: This loader does not properly support the loader slot assignment
+ page used to allocate element structures, so the #defines must be
+ changed in mtx.h for MAX_STORAGE_ELEMENTS, MAX_TRANSFER_ELEMENTS, and
+ MAX_TRANSPORT_ELEMENTS. May also need to increase the SCSI timeout to
+ do inventories. Takes a LONG time to do inventories if you don't have
+ bar codes!
+
+* Exabyte 210 (wsb at paralleldata dot com)
+
+
+* Adic FastStor DLT4000 (7-Slot 1 drive):
+ Vendor ID: 'ADIC '
+ Product ID: 'FastStor DLT '
+
+* Ecrix AutoPak VXA (15-slot 1 drive) in configuration mode 0 (mark
+ at commerceengine dot com):
+ "This drive can be configured to emulate several types, but I've
+ only tested it in this one mode."
+ Vendor ID: 'SPECTRA '
+ Product ID: '215 '
+ Revision: '1008'
+ Attached Changer: No
+ SerialNumber: '023201'
+
+* ATL P1000 2 drive, 31 slot, 1 import/output: (dna plus mtx at clas.ufl.edu)
+ # ./mtx -f /dev/scsi/changer/c2t0d0 inquiry
+ Product Type: Medium Changer
+ Vendor ID: 'ATL '
+ Product ID: 'P1000 6220070'
+ Revision: '2.01'
+ Attached Changer: No
+
+* NSM DVD Jukebox:
+ Storage Changer /dev/sg4:4 Drives, 561 Slots ( 1 Import/Export )
+Product Type: Medium Changer
+ Vendor ID: 'NSM '
+ Product ID: 'NSM6000 '
+ Revision: '1120'
+ Attached Changer: No
+
+* Spectralogic Treefrog/Bullfrog:
+ Storage Changer /dev/sg0:2 Drives, 15 Slots ( 0 Import/Export )
+Product Type: Medium Changer
+Vendor ID: 'SPECTRA '
+Product ID: '10000 '
+Revision: 'X010'
+Attached Changer: No
+
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..186242f
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,144 @@
+Frequently Asked Questions List, v 1.0.1
+
+Index:
+ I. Compiling
+ II. Finding the correct device
+ III. Operational Issues
+
+Part I: Compiling.
+
+Q: Where is the Makefile in the tarball?
+A: MTX now uses GNU Autoconf to generate the Makefile. Type "./configure"
+ while in the extracted mtx directory.
+
+Q: Typing 'make' gives me a bunch of errors in the Makefile. Why can't
+ you provide a Makefile that works?
+A: Note that you need the GNU 'make'. The BSD 'make' won't work, and
+ Solaris 'make' probably won't work either. If you want a better
+ configuration and makefile system, write one, then EMAIL me the results --
+ mtx is Open Source software and needs your code contributions to grow.
+
+Q: How do I compile for operating systems other than Linux?
+A: MTX no longer needs you to edit the Makefile to compile for operating
+ systems other than Linux. Just type ./configure and go with it.
+
+Q: How do I port it to OS's other than the supported ones?
+A: Create a new scsi_ module using one of the existing modules as an
+ example (scsi_freebsd.c might be a good model). Decide what symbol
+ you want #ifdef'ed in order to include that scsi_ module. Edit
+ mtxl.c to #include your scsi_ module. Edit the Makefile to add the
+ new target, including the -D needed to #include your new scsi_ module.
+
+*********************************************************************
+Part II: Finding the correct device.
+
+Q: Why does this command not work??
+ [root@Scotty mtxl-1.4.8]# ./mtx -f /dev/st0 inquiry
+ In /var/log/messages I see:
+ st0: Write not multiple of tape block size.
+A: Note that mtx 1.2 and above use the SCSI GENERIC interface on Linux,
+ FreeBSD, and Solaris (at least). They do NOT use the tape device node.
+
+Q: When I do 'mtx -f /dev/sga inquiry' it shows
+ Product Type: Tape Drive
+ Vendor Id: HP
+ Product ID: C1553A
+ But when I do a 'mtx -f /dev/sga status' it fails. Why?!
+A: You're trying to send a robotics command to a tape drive. You need
+ to send robotics commands to robotics devices, not to tape drives. Look in
+ /proc/scsi/scsi (Linux) or camcontrol (FreeBSD) to find out what the
+ robotics device is. It will be reported as a 'Medium Changer', not a
+ 'Sequential Access' or 'Tape Drive'.
+
+Q: When I do 'cat /proc/scsi/scsi' it shows only one device, the tape device!
+A: You are using a DAT autochanger that has one SCSI ID but two LUN's, LUN 0
+ and LUN 1. You need to compile a new kernel with SCAN SCSI LUNS enabled
+ or add this line to your /etc/lilo.conf (then run /sbin/lilo and reboot):
+ append="max_scsi_luns=2"
+
+Q: I'm tired of typing '-f /dev/sgc' all the time. How do I set a default
+ device that 'mtx' looks at?
+A: Set the CHANGER environment variable. For example, with 'bash':
+ export CHANGER=/dev/sgc
+
+Q: I get "modprobe: can't locate module char-major-21"
+ syslog messages being squirreled away into a file on our syslog host,
+ and mtx doesn't work. What's the problem?
+A: You need to compile SCSI generic support into your kernel (or as a module).
+
+Q: When I installed mtx, a message showed
+ up on the console stating that a scsi changer was found at
+ dev sgr. However, I have no device /dev/sgr.
+A: On Linux, do 'mknod /dev/sgr c 21 19' to create a device node. By default
+ only 16 SCSI generic nodes are created, which might not be enough if
+ you have multiple SCSI controllers with lots of devices.
+
+******************************************************
+III. Operational issues:
+
+Q: I'm using Red Hat 7.0 and mtx works fine when I type ./mtx from the
+ command line, but when I use it from scripts I get the following:
+ mtx: Request Sense: Error Code=70 (Current)
+ mtx: Request Sense: Sense Key=Aborted Command
+ mtx: Request Sense: Additional Sense Code = 4E
+ mtx: Request Sense: Additional Sense Qualifier = 00
+ What's happening?
+A: Do "rpm -e mtx". Red Hat 7.0 includes a busted version of mtx. Your
+ script is apparently picking up the busted mtx in your path. Get rid
+ of the busted mtx, make sure that /usr/local/bin (or wherever you
+ put the "good" mtx) is in the path, and all should be well.
+
+Q: I get
+ # /usr/local/bin/mtx -f /dev/sgr status
+ mtx: Request Sense: Error Code=70 (Current)
+ mtx: Request Sense: Sense Key=Not Ready
+ mtx: Request Sense: Additional Sense Code = 04
+ mtx: Request Sense: Additional Sense Qualifier = 8E
+ mtx: READ ELEMENT STATUS Command Failed
+ What gives?
+A: Make sure your loader is in random mode, not sequential mode.
+ Most "real" loaders (as vs. DAT autoloaders) will not properly report
+ status information unless they are in "random" mode.
+
+
+Q: I issue 'mtx load 5' and it loads tape 5. But when I try to put the tape
+ back in the magazine, we hit problems:
+ mtx: MOVE MEDIUM from Element Address 82 to 5 Failed
+ What gives?
+A: Many loaders require you to first eject the tape (using 'mt' or 'tapectl')
+ before you issue an 'unload' command via 'mtx'.
+
+Q: My Breece Hill loader does not properly report its slots.
+A: Either set the "auto-inventory" feature in the loader's control panel,
+ or run 'mtx inventory' prior to running 'mtx status'.
+
+Q: My Breece Hill loader takes a long time to do an inventory. mtx times
+ out and spits all over the place. Help!
+A: Many loaders that support barcodes will perform poorly if you place tapes
+ into them without bar codes. Place bar codes on all your tapes and you
+ should be able to run 'mtx inventory' without that failure.
+
+Q: How do I eject the magazine of my autoloader?
+A: Many low-end DAT autoloaders support the removable media 'EJECT' command
+ sent to the robotics device, even though it's not documented (or required)
+ in the SCSI standards. If the loader is at /dev/sgb, simply do
+ 'mtx -f /dev/sgb eject' and see what happens. (If nothing happens,
+ your autoloader doesn't support 'eject'). Some high-end libraries have
+ their own proprietary way for ejecting magazine trays, generally
+ involving abuse of the 'transfer' command and 'eepos' addendums,
+ but this is totally non-standard and undocumented.
+
+Q: Is there a standard for cleaning tape bar codes?
+A: Many libraries, and many backup programs, expect cleaning tape bar
+ codes to start with "CLN".
+
+Q: How do I report a bug?
+A: First, read this FAQ. Next, check the mtx list archives at
+ http://mtx.sourceforge.net to make sure that it's not already addressed
+ by somebody else. If your problem is still not solved, send
+ (to the mtx list) the following information:
+ Result of 'mtx inquiry' on the loader,
+ Result of 'mtx status' on the loader (minus a bunch of tapes if
+ it's a 50+ tape loader!),
+ Results of the operation that isn't working correctly.
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c7aea18
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/LICENSE.html b/LICENSE.html
new file mode 100644
index 0000000..40bc73d
--- /dev/null
+++ b/LICENSE.html
@@ -0,0 +1,515 @@
+<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<HTML>
+<HEAD>
+<TITLE>GNU General Public License - GNU Project - Free Software Foundation (FSF)</TITLE>
+<LINK REV="made" HREF="mailto:webmasters@www.gnu.org">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#1F00FF" ALINK="#FF0000" VLINK="#9900DD">
+<H1>GNU General Public License</H1>
+
+<P>
+<HR>
+
+<P>
+
+<H2>Table of Contents</H2>
+<UL>
+
+ <LI><A NAME="TOC1" HREF="gpl.html#SEC1">GNU GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A NAME="TOC2" HREF="gpl.html#SEC2">Preamble</A>
+<LI><A NAME="TOC3" HREF="gpl.html#SEC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A>
+<LI><A NAME="TOC4" HREF="gpl.html#SEC4">How to Apply These Terms to Your New Programs</A>
+
+</UL>
+</UL>
+
+<P>
+
+<HR>
+
+<P>
+
+
+
+<H2><A NAME="SEC1" HREF="gpl.html#TOC1">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>
+Version 2, June 1991
+
+</P>
+
+<PRE>
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+</PRE>
+
+
+
+<H2><A NAME="SEC2" HREF="gpl.html#TOC2">Preamble</A></H2>
+
+<P>
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+</P>
+<P>
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+</P>
+<P>
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+</P>
+<P>
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+</P>
+<P>
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+</P>
+<P>
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+</P>
+<P>
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+</P>
+<P>
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+</P>
+
+
+<H2><A NAME="SEC3" HREF="gpl.html#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A></H2>
+
+
+<P>
+
+<STRONG>0.</STRONG>
+ This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+<P>
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+<P>
+
+<STRONG>1.</STRONG>
+ You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+<P>
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+<P>
+
+<STRONG>2.</STRONG>
+ You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+<P>
+
+<UL>
+
+<LI><STRONG>a)</STRONG>
+ You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+<P>
+<LI><STRONG>b)</STRONG>
+ You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+<P>
+<LI><STRONG>c)</STRONG>
+ If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+</UL>
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+<P>
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+<P>
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+<P>
+
+<STRONG>3.</STRONG>
+ You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+
+<!-- we use this doubled UL to get the sub-sections indented, -->
+<!-- while making the bullets as unobvious as possible. -->
+<UL>
+
+<LI><STRONG>a)</STRONG>
+ Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+<P>
+<LI><STRONG>b)</STRONG>
+ Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+<P>
+<LI><STRONG>c)</STRONG>
+ Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+</UL>
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+<P>
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+<P>
+
+<STRONG>4.</STRONG>
+ You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+<P>
+
+<STRONG>5.</STRONG>
+ You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+<P>
+
+<STRONG>6.</STRONG>
+ Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+<P>
+
+<STRONG>7.</STRONG>
+ If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+<P>
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+<P>
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+<P>
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+<P>
+
+<STRONG>8.</STRONG>
+ If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+<P>
+
+<STRONG>9.</STRONG>
+ The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+<P>
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+<P>
+
+
+<STRONG>10.</STRONG>
+ If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+
+
+<P><STRONG>NO WARRANTY</STRONG></P>
+
+<P>
+
+<STRONG>11.</STRONG>
+ BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+<P>
+
+<STRONG>12.</STRONG>
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+<P>
+
+
+<H2>END OF TERMS AND CONDITIONS</H2>
+
+
+
+<H2><A NAME="SEC4" HREF="gpl.html#TOC4">How to Apply These Terms to Your New Programs</A></H2>
+
+<P>
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+</P>
+<P>
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+</P>
+
+<PRE>
+<VAR>one line to give the program's name and an idea of what it does.</VAR>
+Copyright (C) <VAR>yyyy</VAR> <VAR>name of author</VAR>
+
+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.
+</PRE>
+
+<P>
+Also add information on how to contact you by electronic and paper mail.
+
+</P>
+<P>
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+</P>
+
+<PRE>
+Gnomovision version 69, Copyright (C) <VAR>year</VAR> <VAR>name of author</VAR>
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
+type `show w'. This is free software, and you are welcome
+to redistribute it under certain conditions; type `show c'
+for details.
+</PRE>
+
+<P>
+The hypothetical commands <SAMP>`show w'</SAMP> and <SAMP>`show c'</SAMP> should show
+the appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than <SAMP>`show w'</SAMP> and
+<SAMP>`show c'</SAMP>; they could even be mouse-clicks or menu items--whatever
+suits your program.
+
+</P>
+<P>
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+</P>
+
+<PRE>
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written
+by James Hacker.
+
+<VAR>signature of Ty Coon</VAR>, 1 April 1989
+Ty Coon, President of Vice
+</PRE>
+
+<P>
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+<HR>
+
+<P>
+FSF &amp; GNU inquiries &amp; questions to
+<A HREF="mailto:gnu@gnu.org"><EM>gnu@gnu.org</EM></A>.
+send other questions to
+<A HREF="mailto:gnu@gnu.org"><EM>gnu@gnu.org</EM></A>.
+<P>
+Copyright notice above.<BR>
+Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111, USA
+<P>
+<HR>
+</BODY>
+</HTML>
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..6b967cf
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,176 @@
+# WARNING -- THIS HAS BEEN RE-WRITTEN TO USE GNU MAKE. DO NOT
+# TRY TO PROCESS THIS WITH A NORMAL MAKE! (FREEBSD GUYS, THIS MEANS
+# USE GMAKE, NOT REGULAR BSD MAKE!)
+#
+# Valid targets:
+# linux86 freebsd86 solarissparc sgi dec vms
+#
+# Makefile changes by Lars Kellogg-Stedman for better integration with
+# GNU Autoconf.
+
+# Version # for 'make dist'...
+VERSION=1.3.12
+
+BINS = mtx@EXEEXT@ tapeinfo@EXEEXT@ loaderinfo@EXEEXT@ scsitape@EXEEXT@ scsieject@EXEEXT@
+EXTRA_BINS = nsmhack@EXEEXT@
+DBGS := $(BINS:%@EXEEXT@=%.dbg)
+MAN = mtx.1 tapeinfo.1 loaderinfo.1 scsitape.1 scsieject.1
+MAN_HTML := $(MAN:%.1=%.html)
+MAN_TXT := $(MAN:%.1=%.txt)
+
+TARGET = @TARGET@
+CPU = @CPU@
+CC = @CC@
+INSTALL = @INSTALL@
+
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@ -DVERSION="\"$(VERSION)\"" -I$(srcdir) -I.
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+USE_OBJCOPY = @USE_OBJCOPY@
+
+INSTALL_DOC = $(INSTALL) -m 644
+INSTALL_BIN = $(INSTALL) -m 755
+INSTALL_DIR = $(INSTALL) -m 755 -d
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+sbindir = @sbindir@
+mandir = @mandir@
+srcdir = @srcdir@
+
+VPATH = $(srcdir)
+
+#
+# Linux on x86...
+#
+ifeq ($(TARGET),linux)
+CFLAGS += -Wall
+CPPFLAGS += -DLONG_PRINT_REQUEST_SENSE=1
+endif
+
+ifeq ($(TARGET),mingw)
+CFLAGS += -Wall
+CPPFLAGS += -DLONG_PRINT_REQUEST_SENSE=1
+endif
+
+#
+# FreeBSD
+#
+ifeq ($(TARGET),freebsd86)
+CPPFLAGS += -DLONG_PRINT_REQUEST_SENSE=1
+LIBS += -lcam
+endif
+
+ifeq ($(TARGET),hpux)
+CFLAGS += -O -D_HPUX_SOURCE -D __hpux__
+endif
+
+#
+# Solaris/SPARC
+#
+ifeq ($(TARGET),solarissparc)
+CFLAGS += -O6
+endif
+
+#
+# SGI IRIX
+#
+ifeq ($(TARGET),sgi)
+CFLAGS += -O6
+LIBS += -lds
+endif
+
+#
+# Digital Unix
+#
+ifeq ($(TARGET),dec)
+CFLAGS += -O
+endif
+
+#
+# OpenVMS (see vms/000readme)
+#
+ifeq ($(TARGET),vms)
+See vms/000readme for information.
+endif
+
+%.dbg : %@EXEEXT@
+ifeq ($(USE_OBJCOPY),yes)
+ objcopy --only-keep-debug $< $@
+ objcopy --strip-debug $<
+ objcopy --add-gnu-debuglink=$@ $<
+else
+ strip $< -o $@
+endif
+
+all: $(BINS)
+
+dbgs: $(DBGS)
+
+install: $(BINS)
+ $(INSTALL_DIR) $(sbindir)
+ for file in $(BINS); do \
+ $(INSTALL_BIN) "$$file" $(sbindir) ; \
+ done
+ $(INSTALL_DIR) $(mandir) $(mandir)/man1
+ for file in mtx.1 tapeinfo.1 scsitape.1 scsieject.1 loaderinfo.1 ; do \
+ $(INSTALL_DOC) "$$file" $(mandir)/man1 ; \
+ done
+
+clean:
+ rm -f *.o *~ mtx-*.zip
+ rm -f $(BINS)
+ rm -f $(DBGS)
+ rm -f $(MAN_HTML)
+ rm -f $(MAN_TXT)
+ rm -f mam2debug@EXEEXT@ mam2debug2@EXEEXT@
+ rm -rf autom4te.cache
+
+distclean: clean
+ rm -f Makefile config.h config.log config.cache config.status
+
+dist: distclean
+ ./makedist $(VERSION)
+
+loaderinfo@EXEEXT@: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o loaderinfo@EXEEXT@ loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
+
+nsmhack@EXEEXT@: nsmhack.o mtxl.o $(EXTRA)
+ $(CC) $(LDFLAGS) -o nsmhack@EXEEXT@ nsmhack.o mtxl.o $(EXTRA) $(LIBS)
+
+mtx@EXEEXT@: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o mtx@EXEEXT@ mtx.o mtxl.o $(EXTRA) $(LIBS)
+
+mam2debug@EXEEXT@: mtxl.o mam2debug.o mtx.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o mam2debug@EXEEXT@ mtxl.o mam2debug.o $(EXTRA) $(LIBS)
+
+tapeinfo@EXEEXT@: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o tapeinfo@EXEEXT@ tapeinfo.o mtxl.o $(EXTRA) $(LIBS)
+
+mam2debug2@EXEEXT@: mtxl.o mam2debug2.o mtx.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o mam2debug2@EXEEXT@ mtxl.o mam2debug2.o $(EXTRA) $(LIBS)
+
+scsitape@EXEEXT@: scsitape.o mtxl.o mtxl.h mtx.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o scsitape@EXEEXT@ scsitape.o mtxl.o $(EXTRA) $(LIBS)
+
+scsitape.o: scsitape.c mtx.h mtxl.h
+
+scsieject@EXEEXT@: scsieject.o mtxl.o mtxl.h mtx.h $(EXTRA)
+ $(CC) $(LDFLAGS) -o scsieject@EXEEXT@ scsieject.o mtxl.o $(EXTRA) $(LIBS)
+
+scsieject.o: scsieject.c mtx.h mtxl.h
+
+loaderinfo.o: loaderinfo.c mtx.h mtxl.h
+
+tapeinfo.o: tapeinfo.c mtx.h mtxl.h
+
+mam2debug.o: mam2debug.c mtx.h mtxl.h
+
+mam2debug2.o: mam2debug2.c mtx.h mtxl.h
+
+mtx.o: mtx.c mtx.h mtxl.h
+
+mtxl.o: mtxl.c mtx.h mtxl.h scsi_linux.c scsi_win32.c
+
+nsmhack.o: nsmhack.c mtxl.h mtx.h
diff --git a/README b/README
new file mode 100644
index 0000000..f81f6ca
--- /dev/null
+++ b/README
@@ -0,0 +1,38 @@
+MTX
+
+Programs:
+ mtx is the media changer control program
+ tapeinfo dumps some interesting stuff out of tape drives' mode pages and
+sense pages.
+ loaderinfo dumps some interesting stuff out of loaders' mode pages and
+sense pages.
+ scsitape sends raw SCSI commands to tape drives. Do not use this unless
+you know exactly what you're doing, because you can easily get into a feud
+with the system's own tape driver and end up locking up the whole system.
+
+INSTALLATION:
+
+WARNING: MUST HAVE GNU 'make' TO DO THIS! (e.g. use 'gmake' on freebsd, not
+BSD 'make'!).
+
+Type ./configure to create a Makefile. Type 'make', then 'make
+install'. Type 'man mtx' for info about mtx, and 'man tapeinfo' for
+info about tapeinfo. Enjoy.
+
+Credits:
+
+The original 'mtx' program is copyright 1996-1997 by Leonard Zubkoff
+<lnz@dandelion.com>. This version was modified for multi-drive,
+optical changer, and tape library support by Eric Lee Green
+<eric@badtux.org>. Also added FreeBSD support. Please see the man page
+for current info, and the file 'mtx.doc' for historical info.
+
+My thanks to Doug Bonnell of Breece Hill for suggestions on
+dynamically allocating element info, Tien That Ton of Tandberg for
+being the original tester of the Import/Export Element stuff, Ken
+Porter for RPM's, William D. Smith for the HP/UX port, Kai Makisara
+for the barcode backoff fix, and to all the other people out there who
+have used it, found problems with it, and let me know about it (you
+know who you are).
+
+ -- Eric Lee Green <eric@badtux.org>
diff --git a/README.win32 b/README.win32
new file mode 100644
index 0000000..cf8c39d
--- /dev/null
+++ b/README.win32
@@ -0,0 +1,45 @@
+BUILDING FOR MICROSOFT WINDOWS
+==============================
+
+You can perform the build using either MinGW or Microsoft Visual Studio 2005.
+
+ Microsoft Visual Studio 2005
+ ----------------------------
+
+ Open the solution in msvc/mtx.sln.
+
+ Select the Build / Build Solution menu item.
+
+
+ MinGW with GCC
+ --------------
+
+ You must be using at least version 2.16.91 of binutils.
+
+ To generate the initial configure script, this only needs to be
+ done once.
+
+ ./configure --host=mingw32
+ make
+
+CHANGES FROM UNIX
+=================
+
+The only difference is in the naming of devices. On Linux the changer is
+accessed using /dev/sg<N>, on Windows you use Changer<N>.
+
+On Linux the tape drive is referenced using /dev/nst<N>, on Windows you use Tape<N>.
+
+There is one exception, in the case where there isn't a driver loaded for the device.
+This is usually only the case on Windows 2000 or if the Windows XP or Windows Server
+2003 system supplied driver has been disabled.
+
+In the case where there is no driver loaded you can access the device directly
+through the SCSI driver using the following notation:
+
+ <port>:<bus>:<target>:<lun>
+
+ Port is the adapter number
+ Bus is the SCSI bus number relative to the adapter
+ Target is the SCSI device's target ID
+ LUN is the SCSI device's logical unit number
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..4a7c757
--- /dev/null
+++ b/TODO
@@ -0,0 +1,15 @@
+1 Fix the big element descriptor overflow problem by adding a retry/reallocate
+ if things overflow.
+1 Add a 'timeout' command to adjust the timeout (timeout will be in seconds!).
+1 Add IES command (sets CDB[5] to something in routine Inventory() ).
+1 Fix 'scsitape' READ and WRITE so that block counts work.
+1 Add EXCHANGE command so that we can exchange media between slots in
+ NSM/DISC optical jukeboxes.
+1 If moving media to/from import/export slot, try to do it even if the slot
+ reports that it's empty or full, this will let us stick our tongue out
+ on NSM/DISC optical jukeboxes for importing media.
+2 Fix ports to other Unixes/VMS.
+2 Add a range to 'mtx status' so that we request status only of
+ the elements we're interested in, rather than of all of them.
+ (nice for the very big loaders!).
+3 Better Import/Export port support?
diff --git a/build.win32 b/build.win32
new file mode 100755
index 0000000..5c2c00a
--- /dev/null
+++ b/build.win32
@@ -0,0 +1,15 @@
+manpages="mtx.1 tapeinfo.1 loaderinfo.1 scsitape.1 scsieject.1"
+txtpages="mtx.txt tapeinfo.txt loaderinfo.txt scsitape.txt scsieject.txt"
+htmlpages="mtx.html tapeinfo.html loaderinfo.html scsitape.html scsieject.html"
+
+./configure --host=mingw32
+make
+make dbgs
+
+for i in $manpages
+do
+ groff -et -Thtml -mandoc $i | col -b > `basename $i .1`.html
+ groff -et -Tascii -mandoc $i | col -b > `basename $i .1`.txt
+done
+
+zip mtx-$1.zip README.win32 *.exe $htmlpages $txtpages
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..396482d
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2006-07-02'
+
+# 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
+# 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+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 "$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 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-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
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[3456]*)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T:Interix*:[3456]*)
+ 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
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ 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:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ 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:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ 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 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ 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
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ 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
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..7282e46
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,37 @@
+/* Copyright 2001 Enhanced Software Technologies Inc.
+ * Released under GNU General Public License V2 or Above
+ * See http://www.gnu.org for more information about the terms of
+ * the GNU General Public License.
+ * $Date: 2007-02-13 08:45:31 -0800 (Tue, 13 Feb 2007) $
+ * $Revision: 144 $
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H 1
+
+/* autoconf changes these. */
+#define HAVE_STRING_H 0
+#define HAVE_UNISTD_H 0
+#define HAVE_STDLIB_H 0
+#define HAVE_STDARG_H 0
+#define HAVE_SYS_PARAM_H 0
+#define HAVE_SCSI_SCSI_H 0
+#define HAVE_SCSI_SCSI_IOCTL_H 0
+#define HAVE_SCSI_SG_H 0
+#define HAVE_SYS_GSCDDS_H 0
+#define HAVE_CAMLIB_H 0
+#define HAVE_SYS_SCSI_IMPL_USCSI_H 0
+#define HAVE_SYS_SCSI_CTL_H 0
+#define HAVE_DSLIB_H 0
+#define HAVE_DU_DEFS_H 0
+#define HAVE_SYS_STAT_H 0
+#define HAVE_SYS_TYPES_H 0
+#define HAVE_FCNTL_H 0
+#define HAVE_SYS_IOCTL_H 0
+#define HAVE_SYS_MTIO_H 0
+#define HAVE_DDK_NTDDSCSI_H 0
+
+#define WORDS_BIGENDIAN 0
+
+#endif
+
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..fab0aa3
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1616 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2006-09-20'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# 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
+# 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# 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-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/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -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/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # 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/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ 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
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ 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
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -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-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* | -rdos* | -toppers*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..2e4bd13
--- /dev/null
+++ b/configure
@@ -0,0 +1,6545 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="mtx.c"
+ac_default_prefix=/usr/local
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# 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
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+TARGET
+CPU
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+USE_OBJCOPY
+CPP
+GREP
+EGREP
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+case "$host_os" in
+ *linux*) cat >>confdefs.h <<\_ACEOF
+#define LINUX 1
+_ACEOF
+
+ TARGET=linux
+ ;;
+ *solaris*) cat >>confdefs.h <<\_ACEOF
+#define SOLARIS 1
+_ACEOF
+
+ TARGET=solarissparc
+ ;;
+ *sunos*) TARGET=solarissparc
+ ;;
+ *freebsd*) TARGET=freebsd86
+ ;;
+ *aix*) TARGET=aix
+ ;;
+ *irix*) TARGET=sgi
+ ;;
+ *hp*) TARGET=hpux
+ ;;
+ *HP*) TARGET=hpux
+ ;;
+ *sequent*) cat >>confdefs.h <<\_ACEOF
+#define SEQUENT 1
+_ACEOF
+
+ ;;
+ *MINGW*) TARGET=mingw
+ ;;
+ *MinGW*) TARGET=mingw
+ ;;
+ *mingw*) TARGET=mingw
+ ;;
+ *) TARGET=$host_os
+ ;;
+esac
+
+case "$host_cpu" in
+ # force us down to '386 if we're on some other machine.
+ *?86*) host_cpu='i386'
+ CPU=386
+ ;;
+ *) CPU=$host_cpu;
+ ;;
+esac
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; 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_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; 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_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; 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_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; 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_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$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_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+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_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+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. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+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. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; 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_prog_USE_OBJCOPY+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$USE_OBJCOPY"; then
+ ac_cv_prog_USE_OBJCOPY="$USE_OBJCOPY" # Let the user override the test.
+else
+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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_USE_OBJCOPY="yes"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_USE_OBJCOPY" && ac_cv_prog_USE_OBJCOPY="no"
+fi
+fi
+USE_OBJCOPY=$ac_cv_prog_USE_OBJCOPY
+if test -n "$USE_OBJCOPY"; then
+ { echo "$as_me:$LINENO: result: $USE_OBJCOPY" >&5
+echo "${ECHO_T}$USE_OBJCOPY" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 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); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 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); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 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); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 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); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+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. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+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 )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_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. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in \
+ unistd.h \
+ stdlib.h \
+ errno.h \
+ fcntl.h \
+ stdarg.h \
+ string.h \
+ scsi/scsi.h \
+ scsi/scsi_ioctl.h \
+ scsi/sg.h \
+ sys/gscdds.h \
+ camlib.h \
+ cam/cam_ccb.h \
+ cam/scsi/scsi_message.h \
+ sys/fsid.h \
+ sys/fstyp.h \
+ sys/stat.h \
+ sys/types.h \
+ sys/mnttab.h \
+ sys/param.h \
+ sys/time.h \
+ sys/scsi/impl/uscsi.h \
+ sys/scsi.h \
+ sys/scsi_ctl.h \
+ sys/ioctl.h \
+ sys/mtio.h \
+ sys/param.h \
+ dslib.h \
+ du/defs.h \
+ ddk/ntddscsi.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+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
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 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); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+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. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset cs;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_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
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_size_t=no
+fi
+
+rm -f core 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
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_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
+typedef pid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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 whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
+if test "${ac_cv_header_time+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. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; }
+if test "${ac_cv_struct_tm+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. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_struct_tm=time.h
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_struct_tm=sys/time.h
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ 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
+typedef int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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; }
+
+# The cast to long int 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.
+{ 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 "$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
+ typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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
+ typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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
+ typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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
+ typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core 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
+ typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') if test "$ac_cv_type_int" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+ else
+ ac_cv_sizeof_int=0
+ fi ;;
+esac
+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
+ typedef int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+ {
+ long int i = longval ();
+ if (i != ((long int) (sizeof (ac__type_sizeof_))))
+ return 1;
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ((long int) (sizeof (ac__type_sizeof_))))
+ return 1;
+ fprintf (f, "%lu\n", i);
+ }
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 )
+if test "$ac_cv_type_int" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+ else
+ ac_cv_sizeof_int=0
+ fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+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
+typedef long ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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; }
+
+# The cast to long int 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.
+{ 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 "$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
+ typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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
+ typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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
+ typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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
+ typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core 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
+ typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') if test "$ac_cv_type_long" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+ else
+ ac_cv_sizeof_long=0
+ fi ;;
+esac
+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
+ typedef long ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+ {
+ long int i = longval ();
+ if (i != ((long int) (sizeof (ac__type_sizeof_))))
+ return 1;
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ((long int) (sizeof (ac__type_sizeof_))))
+ return 1;
+ fprintf (f, "%lu\n", i);
+ }
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 )
+if test "$ac_cv_type_long" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+ else
+ ac_cv_sizeof_long=0
+ fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+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 whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+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>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+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>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+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 ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+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 )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; }
+if test "${ac_cv_type_signal+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. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_signal=int
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_signal=void
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+for ac_func in vprintf
+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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+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
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+{ echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; }
+if test "${ac_cv_func__doprnt+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 _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt (); 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 _doprnt
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _doprnt ();
+/* 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__doprnt || defined __stub____doprnt
+choke me
+#endif
+
+int
+main ()
+{
+return _doprnt ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func__doprnt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func__doprnt=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6; }
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+TARGET!$TARGET$ac_delim
+CPU!$CPU$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+USE_OBJCOPY!$USE_OBJCOPY$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 67; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/configure.in b/configure.in
new file mode 100755
index 0000000..10aa09d
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,113 @@
+dnl Copyright 2001 Enhanced Software Technologies Inc.
+dnl Written Jan. 2001 Eric Lee Green
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(mtx.c)
+AC_CONFIG_HEADER(config.h)
+
+dnl Check system.
+AC_CANONICAL_SYSTEM
+AC_PREFIX_DEFAULT(/usr/local)
+
+case "$host_os" in
+ *linux*) AC_DEFINE(LINUX)
+ TARGET=linux
+ ;;
+ *solaris*) AC_DEFINE(SOLARIS)
+ TARGET=solarissparc
+ ;;
+ *sunos*) TARGET=solarissparc
+ ;;
+ *freebsd*) TARGET=freebsd86
+ ;;
+ *aix*) TARGET=aix
+ ;;
+ *irix*) TARGET=sgi
+ ;;
+ *hp*) TARGET=hpux
+ ;;
+ *HP*) TARGET=hpux
+ ;;
+ *sequent*) AC_DEFINE(SEQUENT)
+ ;;
+ *MINGW*) TARGET=mingw
+ ;;
+ *MinGW*) TARGET=mingw
+ ;;
+ *mingw*) TARGET=mingw
+ ;;
+ *) TARGET=$host_os
+ ;;
+esac
+AC_SUBST(TARGET)
+case "$host_cpu" in
+ # force us down to '386 if we're on some other machine.
+ *?86*) host_cpu='i386'
+ CPU=386
+ ;;
+ *) CPU=$host_cpu;
+ ;;
+esac
+
+AC_SUBST(CPU)
+
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_CHECK_PROG(USE_OBJCOPY, objcopy, yes, no)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(\
+ unistd.h \
+ stdlib.h \
+ errno.h \
+ fcntl.h \
+ stdarg.h \
+ string.h \
+ scsi/scsi.h \
+ scsi/scsi_ioctl.h \
+ scsi/sg.h \
+ sys/gscdds.h \
+ camlib.h \
+ cam/cam_ccb.h \
+ cam/scsi/scsi_message.h \
+ sys/fsid.h \
+ sys/fstyp.h \
+ sys/stat.h \
+ sys/types.h \
+ sys/mnttab.h \
+ sys/param.h \
+ sys/time.h \
+ sys/scsi/impl/uscsi.h \
+ sys/scsi.h \
+ sys/scsi_ctl.h \
+ sys/ioctl.h \
+ sys/mtio.h \
+ sys/param.h \
+ dslib.h \
+ du/defs.h \
+ ddk/ntddscsi.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_TYPE_PID_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_C_BIGENDIAN
+
+
+
+dnl Checks for library functions.
+dnl AC_FUNC_ALLOCA
+
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+
+dnl Check for files
+
+AC_OUTPUT(Makefile)
diff --git a/contrib/MTX.html b/contrib/MTX.html
new file mode 100644
index 0000000..8ea9fce
--- /dev/null
+++ b/contrib/MTX.html
@@ -0,0 +1,209 @@
+<HTML>
+<HEAD>
+<TITLE>TapeChanger::MTX - use 'mtx' to manipulate a tape library</TITLE>
+<LINK REV="made" HREF="mailto:none">
+</HEAD>
+
+<BODY>
+
+<A NAME="__index__"></A>
+<!-- INDEX BEGIN -->
+
+<UL>
+
+ <LI><A HREF="#name">NAME</A></LI>
+ <LI><A HREF="#synopsis">SYNOPSIS</A></LI>
+ <LI><A HREF="#description">DESCRIPTION</A></LI>
+ <LI><A HREF="#variables">VARIABLES</A></LI>
+ <LI><A HREF="#usage">USAGE</A></LI>
+ <LI><A HREF="#notes">NOTES</A></LI>
+ <LI><A HREF="#requirements">REQUIREMENTS</A></LI>
+ <LI><A HREF="#todo">TODO</A></LI>
+ <LI><A HREF="#see also">SEE ALSO</A></LI>
+ <LI><A HREF="#author">AUTHOR</A></LI>
+ <LI><A HREF="#copyright">COPYRIGHT</A></LI>
+</UL>
+<!-- INDEX END -->
+
+<HR>
+<P>
+<H1><A NAME="name">NAME</A></H1>
+<P>TapeChanger::MTX - use 'mtx' to manipulate a tape library</P>
+<P>
+<HR>
+<H1><A NAME="synopsis">SYNOPSIS</A></H1>
+<PRE>
+ use TapeChanger::MTX;</PRE>
+<PRE>
+ my $loaded = TapeChanger::MTX-&gt;loadedtape;
+ print &quot;Currently loaded: $loaded\n&quot; if ($loaded);</PRE>
+<PRE>
+ TapeChanger::MTX-&gt;loadtape('next');
+ my $nowloaded = TapeChanger::MTX-&gt;loadedtape;
+ print &quot;Currently loaded: $nowloaded\n&quot; if ($nowloaded);
+</PRE>
+<PRE>
+
+See below for more available functions.</PRE>
+<P>
+<HR>
+<H1><A NAME="description">DESCRIPTION</A></H1>
+<P>TapeChanger::MTX is a module to manipulate a tape library using the 'mtx'
+tape library program. It is meant to work with a simple shell/perl script
+to load and unload tapes as appropriate, and to provide a interface for
+more complicated programs to do the same. The below functions and
+variables should do as good a job as explaining this as anything.</P>
+<P>
+<HR>
+<H1><A NAME="variables">VARIABLES</A></H1>
+<DL>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3AMT_%3Ditem_%24TapeCha">$TapeChanger::MTX::MT
+=item $TapeChanger::MTX::MTX</A></STRONG><BR>
+<DD>
+What is the location of the 'mt' and 'mtx' binaries? Can be set with
+'$MT' and '$MTX' in ~/.mtxrc, or defaults to '/usr/sbin/mt' and
+'/usr/local/sbin/mtx'.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3ADRIVE">$TapeChanger::MTX::DRIVE</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3ACONTROL">$TapeChanger::MTX::CONTROL</A></STRONG><BR>
+<DD>
+What are the names of the tape (DRIVE) and changer (CONTROL) device
+nodes? Can be set with $DRIVE or $CONTROL in ~/.mtxrc, or default to
+'/dev/rmt/0' and '/dev/changer' respectively.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3AEJECT">$TapeChanger::MTX::EJECT</A></STRONG><BR>
+<DD>
+Does the tape drive have to eject the tape before the changer retrieves
+it? It's okay to say 'yes' if it's not necessary, in most cases. Can be
+set with $EJECT in ~/.mtxrc, or defaults to '1'.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3AREADY_TIME">$TapeChanger::MTX::READY_TIME</A></STRONG><BR>
+<DD>
+How long should we wait to see if the drive is ready, in seconds, after
+mounting a volume? Can be set with $READY_TIME in ~/.mtxrc, or defaults
+to 60.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3ADEBUG">$TapeChanger::MTX::DEBUG</A></STRONG><BR>
+<DD>
+Print debugging information? Set to '0' for normal verbosity, '1' for
+debugging information, or '-1' for 'quiet mode' (be as quiet as possible).
+<P></P></DL>
+<P>
+<HR>
+<H1><A NAME="usage">USAGE</A></H1>
+<P>This module uses the following functions:</P>
+<DL>
+<DT><STRONG><A NAME="item_tape_cmd">tape_cmd ( COMMAND )</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_mt_cmd">mt_cmd ( COMMAND )</A></STRONG><BR>
+<DD>
+Runs 'mtx' and 'mt' as appropriate. <CODE>COMMAND</CODE> is the command you're
+trying to send to them. Uses 'warn()' to print the commands to the screen
+if $TapeChanger::MTX::DEBUG is set.
+<P></P>
+<DT><STRONG><A NAME="item_numdrives">numdrives ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_numslots">numslots ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadedtape">loadedtape ()</A></STRONG><BR>
+<DD>
+Returns the number of drives, number of slots, and currently loaded tape
+values, respectively, by parsing <STRONG>tape_cmd('status')</STRONG>.
+<P></P>
+<DT><STRONG><A NAME="item_loadtape">loadtape ( SLOT [, DRIVE] )</A></STRONG><BR>
+<DD>
+Loads a tape into the tape changer, and waits until the drive is again
+ready to be written to. <CODE>SLOT</CODE> can be any of the following (with the
+relevant function indicated):
+<PRE>
+ current C&lt;loadedtape()&gt;
+ prev C&lt;loadprevtape()&gt;
+ next C&lt;loadnexttape()&gt;
+ first C&lt;loadfirsttape()&gt;
+ last C&lt;loadlasttape()&gt;
+ 0 C&lt;_ejectdrive()&gt;
+ 1..99 Loads the specified tape number, ejecting whatever is
+ currently in the drive.</PRE>
+<P><CODE>DRIVE</CODE> is the drive to load, and defaults to 0. Returns 0 if
+successful, an error string otherwise.</P>
+<P></P>
+<DT><STRONG><A NAME="item_loadnexttape">loadnexttape ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadprevtape">loadprevtape ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadfirsttape">loadfirsttape ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadlasttape">loadlasttape ()</A></STRONG><BR>
+<DD>
+Loads the next, previous, first, and last tapes in the changer
+respectively. Use <STRONG>tape_cmd('next')</STRONG>, <STRONG>tape_cmd('previous')</STRONG>,
+<STRONG>tape_cmd('first')</STRONG>, and <STRONG>tape_cmd('last')</STRONG>, respectively.
+<P></P>
+<DT><STRONG><A NAME="item_ejecttape">ejecttape ()</A></STRONG><BR>
+<DD>
+Ejects the tape, by first ejecting the tape from the drive
+(<STRONG>mt_cmd(rewind)</STRONG> then <STRONG>mt_cmd(offline)</STRONG>) and then returning it to its
+slot (<STRONG>tape_cmd(unload)</STRONG>). Returns 1 if successful, 0 otherwise.
+<P></P>
+<DT><STRONG><A NAME="item_resetchanger">resetchanger ()</A></STRONG><BR>
+<DD>
+Resets the changer, ejecting the tape and loading the first one from the
+changer.
+<P></P>
+<DT><STRONG><A NAME="item_checkdrive">checkdrive ()</A></STRONG><BR>
+<DD>
+Checks to see if the drive is ready or not, by waiting for up to
+$TapeChanger::MTX::READY_TIME seconds to see if it can get status
+information using <STRONG>mt_cmd(status)</STRONG>. Returns 1 if so, 0 otherwise.
+<P></P>
+<DT><STRONG><A NAME="item_reportstatus">reportstatus</A></STRONG><BR>
+<DD>
+Returns a string containing the loaded tape and the drive that it's
+mounted on.
+<P></P>
+<DT><STRONG><A NAME="item_cannot_run">cannot_run ()</A></STRONG><BR>
+<DD>
+Does some quick checks to see if you're actually capable of using this
+module, based on your user permissions. Returns a list of problems if
+there are any, 0 otherwise.
+<P></P></DL>
+<P>
+<HR>
+<H1><A NAME="notes">NOTES</A></H1>
+<P>~/.mtxrc is automatically loaded when this module is used, if it exists,
+using do(). This could cause security problems if you're trying to use
+this with <CODE>setuid()</CODE> programs - so just don't do that. If you want someone
+to have permission to mess with the tape drive and/or changer, let them
+have that permission directly.</P>
+<P>
+<HR>
+<H1><A NAME="requirements">REQUIREMENTS</A></H1>
+<P>Perl 5.6.0 or better, an installed 'mtx' binary, and a tape changer and
+reader connected to the system.</P>
+<P>
+<HR>
+<H1><A NAME="todo">TODO</A></H1>
+<P>Support for Input/Export slots is not included, though it may be later.
+Possibly works for multiple drives per changer, but I haven't tested it,
+so I probably missed something. 'load previous' doesn't actually work,
+because mtx doesn't support it (though the help says it does).</P>
+<P>
+<HR>
+<H1><A NAME="see also">SEE ALSO</A></H1>
+<P><STRONG>mtx</STRONG>, <STRONG>mt</STRONG>, <STRONG>tapechanger</STRONG>. Inspired by <STRONG>stc-changer</STRONG>, which comes
+with the AMANDA tape backup package (http://www.amanda.org), and MTX,
+available at <A HREF="http://mtx.sourceforge.net.">http://mtx.sourceforge.net.</A></P>
+<P>
+<HR>
+<H1><A NAME="author">AUTHOR</A></H1>
+<P>Tim Skirvin &lt;<A HREF="mailto:tskirvin@uiuc.edu">tskirvin@uiuc.edu</A>&gt;</P>
+<P>
+<HR>
+<H1><A NAME="copyright">COPYRIGHT</A></H1>
+<P>Copyright 2001-2002 by the University of Illinois Board of Trustees and
+Tim Skirvin &lt;<A HREF="mailto:tskirvin@ks.uiuc.edu">tskirvin@ks.uiuc.edu</A>&gt;.</P>
+
+</BODY>
+
+</HTML>
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..832ee0a
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,3 @@
+Everything in here is copyrighted by its original copyright holder.
+The contents of this directory are not maintained as part of the 'mtx'
+project, they are maintained by their original copyright holders.
diff --git a/contrib/TapeChanger-MTX-0.71b.tar.gz b/contrib/TapeChanger-MTX-0.71b.tar.gz
new file mode 100644
index 0000000..a42a2e0
--- /dev/null
+++ b/contrib/TapeChanger-MTX-0.71b.tar.gz
Binary files differ
diff --git a/contrib/config_sgen_solaris.sh b/contrib/config_sgen_solaris.sh
new file mode 100755
index 0000000..080c127
--- /dev/null
+++ b/contrib/config_sgen_solaris.sh
@@ -0,0 +1,151 @@
+#!/bin/sh
+# Copyright 2001 Enhanced Software Technologies Inc.
+# All Rights Reserved
+#
+# This software is licensed under the terms of the Free Software Foundation's
+# General Public License, version 2. See http://www.fsf.org for more
+# inforation on the General Public License. It is released for public use in
+# the hope that others will find it useful. Please contact eric@estinc.com
+# if you have problems. Also check out our backup products at
+# http://www.estinc.com (grin).
+#
+# usage: config_sgen_solaris.sh check|[un]install
+#
+# This configures sgen under Solaris (we hope! :-). Note that this
+# *CAN* do a reboot of the system. Do NOT call this function unless
+# you are willing to let it do a reboot of the system! Also note that
+# this *must* be run as user 'root', since it does highly grokety things.
+
+
+mode="$1"
+cvs upd
+SGEN="/kernel/drv/sgen"
+SGEN_CONF="/kernel/drv/sgen.conf"
+
+do_check() {
+ if test ! -f $SGEN_CONF; then
+ # sgen.conf not installed...
+ return 1
+ fi
+
+ changer_type_count=`grep "changer" $SGEN_CONF | grep -v "^#" | wc -l`
+ target_count=`grep "target=" $SGEN_CONF | grep -v "^#" | wc -l`
+
+ if test $changer_type_count = 0 -o $target_count = 0; then
+ # sgen.conf not configured
+ return 1
+ fi
+
+ # sgen.conf installed, and configured
+ return 0
+}
+
+do_install() {
+
+ # see if already installed
+ do_check
+ if test $? = 0; then
+ echo "sgen already configured, skipping"
+ return 0 # successfully installed (?)
+ fi
+
+ if test ! -f $SGEN; then
+ echo "sgen driver not installed, aborting"
+ return 1
+ fi
+
+ echo "configuring sgen driver..."
+
+ echo 'device-type-config-list="changer"; # BRU-PRO' >>$SGEN_CONF
+ target=0
+ while test $target -le 15; do
+ echo "name=\"sgen\" class=\"scsi\" target=$target lun=0; # BRU-PRO" >>$SGEN_CONF
+ target=`expr $target + 1`
+ done
+
+ echo "Attempting to reload driver..."
+ rem_drv sgen >/dev/null 2>&1
+ add_drv sgen
+ if test "$?" != "0"; then
+ # failed
+ touch /reconfigure
+ echo "Driver was successfully configured, but could not be re-loaded."
+ echo "The system must be rebooted for the driver changes to take effect."
+
+ ans=""
+ while test "$ans" = ""; do
+ printf "Do you want to reboot now (shutdown -g 1 -y -i 6)? [Y/n] "
+ read ans
+
+ if test "$ans" = "Y"; then
+ ans="y"
+ fi
+
+ if test "$ans" = "N"; then
+ ans="n"
+ fi
+
+ if test "$ans" != "y" -a "$ans" != "n"; then
+ echo "Please enter 'y' or 'n'"
+ ans=""
+ fi
+ done
+
+ if test "$ans" = "y"; then
+ shutdown -g 1 -y -i 6
+ # will be killed by reboot...
+ while true; do
+ echo "Waiting for reboot..."
+ sleep 300
+ done
+ fi
+
+ # not rebooted, exit with error
+ return 2
+ fi
+
+ # successful
+ return 0
+}
+
+do_uninstall() {
+ do_check
+ if test $? = 1; then
+ echo "sgen not configured, skipping"
+ return 0 # successfully uninstalled (?)
+ fi
+
+ printf "removing BRU-PRO configuration from $SGEN_CONF..."
+ grep -v "# BRU-PRO" $SGEN_CONF > ${SGEN_CONF}.$$ || return 1
+ cat ${SGEN_CONF}.$$ >${SGEN_CONF} || return 1
+ rm -f ${SGEN_CONF}.$$ >/dev/null || return 1
+ printf "done\n"
+
+ touch /reconfigure
+ printf "Devices will be reconfigured at next reboot.\n"
+ return 0
+}
+
+uname | grep SunOS >/dev/null 2>&1
+if test $? != 0; then
+ echo "$0: not on Solaris, ABORT!"
+ exit 99
+fi
+
+case "$mode" in
+ check)
+ do_check
+ ;;
+ install)
+ do_install
+ ;;
+ uninstall)
+ do_uninstall
+ ;;
+ *)
+ echo "usage: $0 check|[un]install"
+ exit 1
+ ;;
+esac
+
+exit $? \ No newline at end of file
diff --git a/contrib/mtx-changer b/contrib/mtx-changer
new file mode 100755
index 0000000..cf68ddd
--- /dev/null
+++ b/contrib/mtx-changer
@@ -0,0 +1,431 @@
+#! /bin/sh
+###############################################################################
+# AMANDA Tape Changer script for use with the MTX tape changer program
+# Version 1.0 - Tue Feb 20 13:59:39 CST 2001
+#
+# Based on 'stc-changer' by Eric Berggren (eric@ee.pdx.edu)
+# Updated by Tim Skirvin (tskirvin@ks.uiuc.edu)
+#
+# Given that there's no license...let's make this the Perl Artistic License.
+# Just make sure you give me and Eric credit if you modify this.
+###############################################################################
+
+### USER CONFIGURATION
+# Name of the tape drive (takes place of "tapedev" option in amanda.conf)
+# and default driver number in library (usu 0) that DRIVE_NAME points to
+DRIVE_NAME="/dev/rmt/0n"
+DRIVE_NUM=0
+
+# Location of "STC" command and control device
+MTX_CMD="/usr/local/sbin/mtx";
+MTX_CONTROL="/dev/scsi/changer/c4t1d0";
+
+# Whether tape drive must eject tape before changer retrieves
+# (ie, EXB-2x0). Usually okay if set while not necessary, bad if
+# required but not set.
+DRIVE_MUST_EJECT=1
+
+# How long to check drive readiness (in seconds) after mounting (or
+# ejecting) a volume (on some libraries, the motion or eject command may
+# complete before the drive has the volume fully mounted and online,
+# or ready for retrieval, resulting in "Drive not ready"/"Media not
+# ready" errors). Do an "mt status" command every 5 seconds upto this
+# time.
+DRIVE_READY_TIME_MAX=120
+
+# tape "mt" command location...
+MT_CMD="/usr/bin/mt" # called via "MT_CMD -f DRIVE_NAME rewind" &
+ # "MT_CMD -f DRIVE_NAME offline" to eject
+ # and "MT_CMD -f DRIVE_NAME status" to get ready info
+
+##############################################################################
+#
+NumDrives=-1
+NumSlots=-1
+LastSlot=-1
+LoadedTape=-1
+
+#
+# Usage information
+#
+usage()
+{
+ echo
+ echo "Usage: $Progname <command> [arg...]"
+ echo " -info reports capability and loaded tape"
+ echo " -slot <slot> loads specified tape into drive"
+ echo " current reports current mounted tape"
+ echo " next loads logically next tape (loops to top)"
+ echo " prev loads logically previous tape (loops to bot)"
+ echo " first loads first tape"
+ echo " last loads last tape"
+ echo " 0..99 loads tape from specified slot#"
+ echo " -eject uloads current mounted tape"
+ echo " -reset resets changer (and drive); loads first tape"
+ echo
+ exit 5
+}
+
+#
+# Perform "stc" changer command (& handle the "fatal" errors)
+# else, set 'CommandResStr' and 'CommandRawResStr' to the result string
+# and 'CommandResCode' to the exit code
+#
+dotapecmd()
+{
+ cmd=$1
+ arg=$2
+
+ CommandResStr=`$MTX_CMD $MTX_CONTROL $cmd $arg 2>&1`
+ CommandRawResStr=$CommandResStr
+ CommandResCode=$?
+
+ CommandResStr=`echo $CommandResStr | head -1 | sed 's/^[^:]*: //'`
+ if [ $CommandResCode -gt 1 ]; then
+ echo "0 $Progname: returned $CommandResStr"
+ exit 2
+ fi
+}
+
+#
+# Unload tape from drive (a drive command; "ejecttape" is a changer command
+# to actually retrieve the tape). Needed by some changers (controlled by
+# setting "DRIVE_MUST_EJECT")
+#
+ejectdrive()
+{
+ # Tell drive to eject tape before changer retrieves; req'd by some
+ # drives (ie, EXB-2x0). Not needed by QDLT-4x00. Do a "rewind"
+ # command first, then "offline" to eject (instead of "rewoffl")
+ #
+ if [ "$DRIVE_MUST_EJECT" -ne 0 ]; then
+ mtresstr=`$MT_CMD -f $DRIVE_NAME rewind 2>&1`
+ mtrescode=$?
+
+ if [ $mtrescode -ne 0 ]; then
+ if echo "$mtresstr" | egrep -s 'no tape'; then
+ :; # no tape mounted; assume okay...
+ else
+ # can't eject tape, bad; output: <tape#> reason
+ echo "0 $mtresstr"
+ exit 1
+ fi
+ else
+ mtresstr=`$MT_CMD -f $DRIVE_NAME offline 2>&1`
+ mtrescode=$?
+
+ checkdrive 1
+ fi
+ fi
+}
+
+#
+# Check drive readiness after (un)mounting a volume (which may take a while
+# after the volume change command completes)
+#
+checkdrive()
+{
+ unmounting=$1
+
+ if [ "$DRIVE_READY_TIME_MAX" -gt 0 ]; then
+
+ # sleep time between checks
+ pausetime=5
+
+ # number of interations to check
+ numchecks=`expr $DRIVE_READY_TIME_MAX / $pausetime`
+ if [ "$numchecks" -eq 0 ]; then
+ numchecks=1
+ fi
+
+ # check until success, or out of attempts...
+ while [ "$numchecks" -gt 0 ]; do
+ mtresstr=`$MT_CMD -f $DRIVE_NAME status 2>&1`
+ mtrescode=$?
+
+ if [ $mtrescode -eq 0 ]; then
+ # Success ?
+ return 0
+ else
+ # pause, before trying again....
+ if [ "$numchecks" -gt 1 ]; then
+ sleep $pausetime
+
+ # if unmounting a volume, check for 'mt' command
+ # failure; (sleep first for additional comfort)
+ if [ "$unmounting" -ne 0 ]; then
+ return 0
+ fi
+ fi
+ fi
+ numchecks=`expr $numchecks - 1`
+ done
+
+ # failed; output: -1 reason
+ echo "-1 drive won't report ready"
+ exit 1
+ fi
+}
+
+#
+# Get changer parameters
+#
+getchangerparms()
+{
+ dotapecmd status
+ if [ $CommandResCode -eq 0 ] && \
+ echo "$CommandResStr" | egrep -s '^Storage Changer'; then
+
+ NumDrives=`echo $dspec | wc -l`
+ NumDrives=`echo "$CommandRawResStr" | \
+ grep 'Data Transfer Element' | wc -l`
+ if [ "$NumDrives" -le "$DRIVE_NUM" ]; then
+ echo "$Program: Invalid drive # specified ($DRIVE_NUM > $NumDrives)"
+ exit 3
+ fi
+ # grep 'Data Transfer Element $DRIVE_NUM' | \
+ LoadedTape=`echo "$CommandRawResStr" | \
+ grep 'Data Transfer Element' | \
+ grep 'Storage Element [0-9]' | \
+ awk '{ print $7 }' `
+ if [ -z "$LoadedTape" -o "$LoadedTape" = "e" ]; then
+ LoadedTape=-1
+ fi
+ NumSlots=`echo "$CommandRawResStr" | \
+ grep 'Storage Element [0-9]\{1,\}:' | \
+ grep -v 'Data Element' | \
+ wc -l | sed -e 's/ //g' `
+ LastSlot=`expr $NumSlots - 1`
+ else
+ echo \
+ "$Progname: Can't get changer parameters; Result was $CommandResStr"
+ exit 3
+ fi
+}
+
+#
+# Display changer info
+#
+changerinfo()
+{
+ getchangerparms
+
+ # output status string: currenttape numslots randomaccess?
+ echo "$LoadedTape $NumSlots 1"
+ exit 0
+}
+
+#
+# Eject current mounted tape
+#
+ejecttape()
+{
+ getchangerparms
+ ct=$LoadedTape
+
+ # If no tape reported mounted, assume success (could be bad if changer
+ # lost track of tape)
+ #
+ if [ $ct -lt 0 ]; then
+ CommandResCode=0
+ else
+ ejectdrive
+ dotapecmd unload
+ fi
+
+ if [ $CommandResCode -ne 0 ]; then
+ # failed; output: <tape#> reason
+ echo "$ct $CommandResStr"
+ exit 1
+ else
+ # success; output: <tape#> drive
+ echo "$ct $DRIVE_NAME"
+ exit 0
+ fi
+}
+
+#
+# Move specified tape into drive (operation level)
+#
+doloadtape()
+{
+ slot=$1
+ if [ "$slot" -eq "$LoadedTape" ]; then
+ return 0
+ fi
+ ejectdrive
+ dotapecmd load $slot
+ return $CommandResCode
+}
+
+#
+# Load next available tape into drive
+#
+loadnexttape()
+{
+ curslot=$1
+ direction=$2
+
+ startslot=$curslot
+ while true; do
+ if doloadtape $curslot; then
+ return 0
+ else
+ if echo $CommandResStr | egrep -s 'Slot.*reported empty'; then
+
+ if [ "$direction" -lt 0 ]; then
+ curslot=`expr $curslot - 1`
+ if [ "$curslot" -lt 0 ]; then
+ curslot=$LastSlot
+ fi
+ else
+ curslot=`expr $curslot + 1`
+ if [ "$curslot" -gt "$LastSlot" ]; then
+ curslot=0
+ fi
+ fi
+
+ # Check if we're back to where we started...
+ if [ "$curslot" = "$startslot" ]; then
+ if [ "$direction" -lt 0 ]; then
+ CommandResStr="No previous volume available"
+ else
+ CommandResStr="No subsequent volume available"
+ fi
+ return 1
+ fi
+ else
+ return 1
+ fi
+ fi
+ done
+}
+
+#
+# Report loadtape() status
+#
+reportstatus()
+{
+ if [ $CommandResCode -eq 0 ]; then
+ # success; output currenttape drivename
+ echo "$LoadedTape $DRIVE_NAME"
+ exit 0
+ else
+ # failed (empty slot?); output currenttape reason
+ echo "$LoadedTape $CommandResStr"
+ exit 1
+ fi
+}
+
+
+#
+# Move specified tape into drive (command level)
+#
+loadtape()
+{
+ slot=$1
+
+ getchangerparms
+
+ case "$slot" in
+ current)
+ if [ $LoadedTape -lt 0 ]; then
+ CommandResStr="Can't determine current tape; drive empty ?"
+ CommandResCode=1
+ fi
+ ;;
+ prev)
+ if [ $LoadedTape -le 0 ]; then
+ loadnexttape $LastSlot -1
+ else
+ loadnexttape `expr $LoadedTape - 1` -1
+ fi
+ ;;
+ next)
+ if [ $LoadedTape -ge $LastSlot -o $LoadedTape -lt 0 ]; then
+ loadnexttape 0 1
+ else
+ loadnexttape `expr $LoadedTape + 1` 1
+ fi
+ ;;
+ first)
+ loadnexttape 0 1
+ ;;
+ last)
+ loadnexttape $LastSlot -1
+ ;;
+ [0-9]*)
+ doloadtape $slot
+ ;;
+ *)
+ # error; no valid slot specified
+ echo "$Progname: No valid slot specified"
+ exit 1
+ ;;
+ esac
+
+ if [ $CommandResCode -eq 0 ]; then
+ getchangerparms
+ checkdrive
+ fi
+ reportstatus
+}
+
+#
+# Reset changer to known state
+#
+resetchanger()
+{
+ ejectdrive
+ dotapecmd reset
+ if [ $CommandResCode -ne 0 ]; then
+ # failed; output: failed? reason
+ echo "-1 $CommandResStr"
+ exit 2;
+ else
+ loadtape first
+ fi
+}
+
+#############################################################################
+#
+# MAIN
+#
+Progname=`basename $0`
+
+if [ ! -x "$MTX_CMD" ]; then
+ echo "-1 $Progname: cannot run STC command ($MTX_CMD)"
+ exit 2
+fi
+if [ -n "$MTX_CONTROL" ]; then
+ if echo "$MTX_CONTROL" | egrep -s '^-f'; then
+ :;
+ else
+ MTX_CONTROL="-f $MTX_CONTROL"
+ fi
+fi
+if [ -n "$DRIVE_NUM" ]; then
+ DRIVE_NUM=0
+fi
+
+if [ $# -ge 1 ]; then command=$1; else command="-usage"; fi
+
+case "$command" in
+ -info)
+ changerinfo
+ ;;
+ -slot)
+ loadtape $2
+ ;;
+ -eject)
+ ejecttape
+ ;;
+ -reset)
+ resetchanger
+ ;;
+ *)
+ usage
+ ;;
+esac
+
+exit 0
diff --git a/contrib/mtx.py b/contrib/mtx.py
new file mode 100644
index 0000000..1e60c15
--- /dev/null
+++ b/contrib/mtx.py
@@ -0,0 +1,306 @@
+# Copyright 2000 Enhanced Software Technologies Inc.
+# Released under Free Software Foundation's General Public License,
+# Version 2 or above
+#
+# This is an example of how to parse the 'mtx' output from a scripting
+# language.
+#
+# Routine to call 'mtx' and read status, or
+# whatever.
+#
+# We do this here rather than creating a Python "C" module because:
+# 1) Reduces complexity of compile environment
+# 2) Easier debugging.
+# 3) More in keeping with the Unix philosophy of things.
+# 4) Easier to add new functionality.
+#
+#
+
+import string
+import os
+import time # we can do some waiting here...
+
+def readpipe(command):
+ result=""
+
+ infile=os.popen(command,"r")
+
+ try:
+ s=infile.read()
+ except:
+ s=""
+ pass
+ if not s:
+ return None # didn't get anything :-(.
+ result=result+s
+ return result
+
+
+
+
+# these are returned by the mtx.status routine:
+class slotstatus:
+ def __init__(self,slotnum,middle,barcode=None):
+ middle=string.strip(middle)
+ try:
+ left,right=string.split(middle," ")
+ except:
+ left=middle
+ right=None
+ pass
+ # Note: We will not be able to test this at the moment since the
+ # 220 has no import/export port!
+ if right=="IMPORT/EXPORT":
+ self.importexport=1
+ else:
+ self.importexport=0
+ pass
+ self.slotnum=int(slotnum) # make sure it's an integer...
+ if left=="Full":
+ self.full=1
+ else:
+ self.full=None
+ pass
+ if not barcode:
+ self.voltag=None
+ else:
+ l=string.split(barcode,"=",1)
+ self.voltag=l[1]
+ pass
+ return
+ pass
+
+# Drive status lines have this format:
+#Data Transfer Element 0:Full (Storage Element 10 Loaded):VolumeTag = B0000009H
+#Data Transfer Element 1:Empty
+
+class drivestatus:
+ def __init__(self,slotnum,middle,barcode=None):
+ self.slotnum=slotnum
+ if middle=="Empty":
+ self.full=None
+ self.origin=None
+ self.voltag=None
+ return
+ else:
+ self.full=1
+ pass
+
+ # okay, we know we have a tape in the drive.
+ # split and find out our origin: we will always have
+ # an origin, even if the #$@% mtx program had to dig one
+ # out of the air:
+
+ l=string.split(middle," ")
+ self.origin=int(l[3])
+
+ if not barcode:
+ self.voltag=None # barcode of this element.
+ else:
+ l=string.split(barcode," ")
+ self.voltag=string.strip(l[2])
+ pass
+ return
+ pass
+
+# This is the return value for mtx.status.
+class mtxstatus:
+ def __init__(self):
+ self.numdrives=None
+ self.numslots=None
+ self.numexport=None
+ self.drives=[] # a list of drivestatus instances.
+ self.slots=[] # a list of slotstatus instances
+ self.export=[] # another list of slotstatus instances
+ return
+ pass
+
+# call 'mtx' and get barcode info, if possible:
+# okay, we now have a string that consists of a number of lines.
+# we want to explode this string into its component parts.
+# Example format:
+# Storage Changer /dev/sgd:2 Drives, 21 Slots
+# Data Transfer Element 0:Full (Storage Element '5' Loaded)
+# Data Transfer Element 1:Empty
+# Storage Element 1:Full :VolumeTag=CLNA0001
+# Storage Element 2:Full :VolumeTag=B0000009
+# Storage Element 3:Full :VolumeTag=B0000010
+# ....
+# What we want to do, then, is:
+# 1) Turn it into lines by doing a string.split on newline.
+# 2) Split the 1st line on ":" to get left and right.
+# 3) Split the right half on space to get #drives "Drives," #slots
+# 4) process the drives (Full,Empty, etc.)
+# 5) For each of the remaining lines: Split on ':'
+# 6) Full/Empty status is in 2)
+#
+configdir="/opt/brupro/bin" # sigh.
+
+def status(device):
+ retval=mtxstatus()
+ command="%s/mtx -f %s status" % (configdir,device)
+ result=readpipe(command)
+ if not result:
+ return None # sorry!
+ # now to parse:
+
+ try:
+ lines=string.split(result,"\n")
+ except:
+ return None # sorry, no status!
+
+ # print "DEBUG:lines=",lines
+
+ try:
+ l=string.split(lines[0],":")
+ except:
+ return None # sorry, no status!
+
+ # print "DEBUG:l=",l
+ leftside=l[0]
+ rightside=l[1]
+ if len(l) > 2:
+ barcode=l[3]
+ else:
+ barcode=None
+ pass
+ t=string.split(rightside)
+ retval.numdrives=int(t[0])
+ retval.numslots=int(t[2])
+
+ for s in lines[1:]:
+ if not s:
+ continue # skip blank lines!
+ #print "DEBUG:s=",s
+ parts=string.split(s,":")
+ leftpart=string.split(parts[0])
+ rightpart=parts[1]
+ try:
+ barcode=parts[2]
+ except:
+ barcode=None
+ pass
+ #print "DEBUG:leftpart=",leftpart
+ if leftpart[0]=="Data" and leftpart[1]=="Transfer":
+ retval.drives.append(drivestatus(leftpart[3],rightpart,barcode))
+ pass
+ if leftpart[0]=="Storage" and leftpart[1]=="Element":
+ element=slotstatus(leftpart[2],rightpart,barcode)
+ if element.importexport:
+ retval.export.append(element)
+ else:
+ retval.slots.append(element)
+ pass
+ pass
+ continue
+
+ return retval
+
+# Output of a mtx inquiry looks like:
+#
+#Product Type: Medium Changer
+#Vendor ID: 'EXABYTE '
+#Product ID: 'Exabyte EZ17 '
+#Revision: '1.07'
+#Attached Changer: No
+#
+# We simply return a hash table with these values { left:right } format.
+
+def mtxinquiry(device):
+ command="%s/mtx -f %s inquiry" % (configdir,device)
+ str=readpipe(command) # calls the command, returns all its data.
+
+ str=string.strip(str)
+ lines=string.split(str,"\n")
+ retval={}
+ for l in lines:
+ # DEBUG #
+ l=string.strip(l)
+ print "splitting line: '",l,"'"
+ idx,val=string.split(l,':',1)
+ val=string.strip(val)
+ if val[0]=="'":
+ val=val[1:-1] # strip off single quotes, sigh.
+ pass
+ retval[idx]=val
+ continue
+ return retval
+
+# Now for the easy part:
+
+def load(device,slot,drive=0):
+ command="%s/mtx -f %s load %s %s >/dev/null " % (configdir,device,slot,drive)
+ status=os.system(command)
+ return status
+
+def unload(device,slot,drive=0):
+ command="%s/mtx -f %s unload %s %s >/dev/null " % (configdir,device,slot,drive)
+ return os.system(command)
+
+def inventory(device):
+ command="%s/mtx -f %s inventory >/dev/null " % (configdir,device)
+ return os.system(command)
+
+def wait_for_inventory(device):
+ # loop while we have an error return...
+ errcount=0
+ while inventory(device):
+ if errcount==0:
+ print "Waiting for loader '%s'" % device
+ pass
+ time.sleep(1)
+ try:
+ s=status(device)
+ except:
+ s=None
+ pass
+ if s:
+ return 0 # well, whatever we're doing, we're inventoried :-(
+ errcount=errcount+1
+ if errcount==600: # we've been waiting for 10 minutes :-(
+ return 1 # sorry!
+ continue
+ return 0 # we succeeded!
+
+# RCS REVISION LOG:
+# $Log$
+# Revision 1.1 2001/06/05 17:10:51 elgreen
+# Initial revision
+#
+# Revision 1.2 2000/12/22 14:17:19 eric
+# mtx 1.2.11pre1
+#
+# Revision 1.14 2000/11/12 20:35:29 eric
+# do string.strip on the voltag
+#
+# Revision 1.13 2000/11/04 00:33:38 eric
+# if we can get an inventory on the loader after we send it 'mtx inventory',
+# then obviously we managed to do SOMETHING.
+#
+# Revision 1.12 2000/10/28 00:04:34 eric
+# added wait_for_inventory command
+#
+# Revision 1.11 2000/10/27 23:27:58 eric
+# Added inventory command...
+#
+# Revision 1.10 2000/10/01 01:06:29 eric
+# evening checkin
+#
+# Revision 1.9 2000/09/29 02:49:29 eric
+# evening checkin
+#
+# Revision 1.8 2000/09/02 01:05:33 eric
+# Evening Checkin
+#
+# Revision 1.7 2000/09/01 00:08:11 eric
+# strip lines in mtxinquiry
+#
+# Revision 1.6 2000/09/01 00:05:33 eric
+# debugging
+#
+# Revision 1.5 2000/08/31 23:46:01 eric
+# fix def:
+#
+# Revision 1.4 2000/08/31 23:44:06 eric
+# =->==
+#
diff --git a/contrib/mtxctl-0.0.2.tar.gz b/contrib/mtxctl-0.0.2.tar.gz
new file mode 100644
index 0000000..de41b7d
--- /dev/null
+++ b/contrib/mtxctl-0.0.2.tar.gz
Binary files differ
diff --git a/contrib/qdback.tar.gz b/contrib/qdback.tar.gz
new file mode 100644
index 0000000..761a216
--- /dev/null
+++ b/contrib/qdback.tar.gz
Binary files differ
diff --git a/contrib/tapechanger.html b/contrib/tapechanger.html
new file mode 100644
index 0000000..8ea9fce
--- /dev/null
+++ b/contrib/tapechanger.html
@@ -0,0 +1,209 @@
+<HTML>
+<HEAD>
+<TITLE>TapeChanger::MTX - use 'mtx' to manipulate a tape library</TITLE>
+<LINK REV="made" HREF="mailto:none">
+</HEAD>
+
+<BODY>
+
+<A NAME="__index__"></A>
+<!-- INDEX BEGIN -->
+
+<UL>
+
+ <LI><A HREF="#name">NAME</A></LI>
+ <LI><A HREF="#synopsis">SYNOPSIS</A></LI>
+ <LI><A HREF="#description">DESCRIPTION</A></LI>
+ <LI><A HREF="#variables">VARIABLES</A></LI>
+ <LI><A HREF="#usage">USAGE</A></LI>
+ <LI><A HREF="#notes">NOTES</A></LI>
+ <LI><A HREF="#requirements">REQUIREMENTS</A></LI>
+ <LI><A HREF="#todo">TODO</A></LI>
+ <LI><A HREF="#see also">SEE ALSO</A></LI>
+ <LI><A HREF="#author">AUTHOR</A></LI>
+ <LI><A HREF="#copyright">COPYRIGHT</A></LI>
+</UL>
+<!-- INDEX END -->
+
+<HR>
+<P>
+<H1><A NAME="name">NAME</A></H1>
+<P>TapeChanger::MTX - use 'mtx' to manipulate a tape library</P>
+<P>
+<HR>
+<H1><A NAME="synopsis">SYNOPSIS</A></H1>
+<PRE>
+ use TapeChanger::MTX;</PRE>
+<PRE>
+ my $loaded = TapeChanger::MTX-&gt;loadedtape;
+ print &quot;Currently loaded: $loaded\n&quot; if ($loaded);</PRE>
+<PRE>
+ TapeChanger::MTX-&gt;loadtape('next');
+ my $nowloaded = TapeChanger::MTX-&gt;loadedtape;
+ print &quot;Currently loaded: $nowloaded\n&quot; if ($nowloaded);
+</PRE>
+<PRE>
+
+See below for more available functions.</PRE>
+<P>
+<HR>
+<H1><A NAME="description">DESCRIPTION</A></H1>
+<P>TapeChanger::MTX is a module to manipulate a tape library using the 'mtx'
+tape library program. It is meant to work with a simple shell/perl script
+to load and unload tapes as appropriate, and to provide a interface for
+more complicated programs to do the same. The below functions and
+variables should do as good a job as explaining this as anything.</P>
+<P>
+<HR>
+<H1><A NAME="variables">VARIABLES</A></H1>
+<DL>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3AMT_%3Ditem_%24TapeCha">$TapeChanger::MTX::MT
+=item $TapeChanger::MTX::MTX</A></STRONG><BR>
+<DD>
+What is the location of the 'mt' and 'mtx' binaries? Can be set with
+'$MT' and '$MTX' in ~/.mtxrc, or defaults to '/usr/sbin/mt' and
+'/usr/local/sbin/mtx'.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3ADRIVE">$TapeChanger::MTX::DRIVE</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3ACONTROL">$TapeChanger::MTX::CONTROL</A></STRONG><BR>
+<DD>
+What are the names of the tape (DRIVE) and changer (CONTROL) device
+nodes? Can be set with $DRIVE or $CONTROL in ~/.mtxrc, or default to
+'/dev/rmt/0' and '/dev/changer' respectively.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3AEJECT">$TapeChanger::MTX::EJECT</A></STRONG><BR>
+<DD>
+Does the tape drive have to eject the tape before the changer retrieves
+it? It's okay to say 'yes' if it's not necessary, in most cases. Can be
+set with $EJECT in ~/.mtxrc, or defaults to '1'.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3AREADY_TIME">$TapeChanger::MTX::READY_TIME</A></STRONG><BR>
+<DD>
+How long should we wait to see if the drive is ready, in seconds, after
+mounting a volume? Can be set with $READY_TIME in ~/.mtxrc, or defaults
+to 60.
+<P></P>
+<DT><STRONG><A NAME="item_%24TapeChanger%3A%3AMTX%3A%3ADEBUG">$TapeChanger::MTX::DEBUG</A></STRONG><BR>
+<DD>
+Print debugging information? Set to '0' for normal verbosity, '1' for
+debugging information, or '-1' for 'quiet mode' (be as quiet as possible).
+<P></P></DL>
+<P>
+<HR>
+<H1><A NAME="usage">USAGE</A></H1>
+<P>This module uses the following functions:</P>
+<DL>
+<DT><STRONG><A NAME="item_tape_cmd">tape_cmd ( COMMAND )</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_mt_cmd">mt_cmd ( COMMAND )</A></STRONG><BR>
+<DD>
+Runs 'mtx' and 'mt' as appropriate. <CODE>COMMAND</CODE> is the command you're
+trying to send to them. Uses 'warn()' to print the commands to the screen
+if $TapeChanger::MTX::DEBUG is set.
+<P></P>
+<DT><STRONG><A NAME="item_numdrives">numdrives ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_numslots">numslots ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadedtape">loadedtape ()</A></STRONG><BR>
+<DD>
+Returns the number of drives, number of slots, and currently loaded tape
+values, respectively, by parsing <STRONG>tape_cmd('status')</STRONG>.
+<P></P>
+<DT><STRONG><A NAME="item_loadtape">loadtape ( SLOT [, DRIVE] )</A></STRONG><BR>
+<DD>
+Loads a tape into the tape changer, and waits until the drive is again
+ready to be written to. <CODE>SLOT</CODE> can be any of the following (with the
+relevant function indicated):
+<PRE>
+ current C&lt;loadedtape()&gt;
+ prev C&lt;loadprevtape()&gt;
+ next C&lt;loadnexttape()&gt;
+ first C&lt;loadfirsttape()&gt;
+ last C&lt;loadlasttape()&gt;
+ 0 C&lt;_ejectdrive()&gt;
+ 1..99 Loads the specified tape number, ejecting whatever is
+ currently in the drive.</PRE>
+<P><CODE>DRIVE</CODE> is the drive to load, and defaults to 0. Returns 0 if
+successful, an error string otherwise.</P>
+<P></P>
+<DT><STRONG><A NAME="item_loadnexttape">loadnexttape ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadprevtape">loadprevtape ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadfirsttape">loadfirsttape ()</A></STRONG><BR>
+<DD>
+<DT><STRONG><A NAME="item_loadlasttape">loadlasttape ()</A></STRONG><BR>
+<DD>
+Loads the next, previous, first, and last tapes in the changer
+respectively. Use <STRONG>tape_cmd('next')</STRONG>, <STRONG>tape_cmd('previous')</STRONG>,
+<STRONG>tape_cmd('first')</STRONG>, and <STRONG>tape_cmd('last')</STRONG>, respectively.
+<P></P>
+<DT><STRONG><A NAME="item_ejecttape">ejecttape ()</A></STRONG><BR>
+<DD>
+Ejects the tape, by first ejecting the tape from the drive
+(<STRONG>mt_cmd(rewind)</STRONG> then <STRONG>mt_cmd(offline)</STRONG>) and then returning it to its
+slot (<STRONG>tape_cmd(unload)</STRONG>). Returns 1 if successful, 0 otherwise.
+<P></P>
+<DT><STRONG><A NAME="item_resetchanger">resetchanger ()</A></STRONG><BR>
+<DD>
+Resets the changer, ejecting the tape and loading the first one from the
+changer.
+<P></P>
+<DT><STRONG><A NAME="item_checkdrive">checkdrive ()</A></STRONG><BR>
+<DD>
+Checks to see if the drive is ready or not, by waiting for up to
+$TapeChanger::MTX::READY_TIME seconds to see if it can get status
+information using <STRONG>mt_cmd(status)</STRONG>. Returns 1 if so, 0 otherwise.
+<P></P>
+<DT><STRONG><A NAME="item_reportstatus">reportstatus</A></STRONG><BR>
+<DD>
+Returns a string containing the loaded tape and the drive that it's
+mounted on.
+<P></P>
+<DT><STRONG><A NAME="item_cannot_run">cannot_run ()</A></STRONG><BR>
+<DD>
+Does some quick checks to see if you're actually capable of using this
+module, based on your user permissions. Returns a list of problems if
+there are any, 0 otherwise.
+<P></P></DL>
+<P>
+<HR>
+<H1><A NAME="notes">NOTES</A></H1>
+<P>~/.mtxrc is automatically loaded when this module is used, if it exists,
+using do(). This could cause security problems if you're trying to use
+this with <CODE>setuid()</CODE> programs - so just don't do that. If you want someone
+to have permission to mess with the tape drive and/or changer, let them
+have that permission directly.</P>
+<P>
+<HR>
+<H1><A NAME="requirements">REQUIREMENTS</A></H1>
+<P>Perl 5.6.0 or better, an installed 'mtx' binary, and a tape changer and
+reader connected to the system.</P>
+<P>
+<HR>
+<H1><A NAME="todo">TODO</A></H1>
+<P>Support for Input/Export slots is not included, though it may be later.
+Possibly works for multiple drives per changer, but I haven't tested it,
+so I probably missed something. 'load previous' doesn't actually work,
+because mtx doesn't support it (though the help says it does).</P>
+<P>
+<HR>
+<H1><A NAME="see also">SEE ALSO</A></H1>
+<P><STRONG>mtx</STRONG>, <STRONG>mt</STRONG>, <STRONG>tapechanger</STRONG>. Inspired by <STRONG>stc-changer</STRONG>, which comes
+with the AMANDA tape backup package (http://www.amanda.org), and MTX,
+available at <A HREF="http://mtx.sourceforge.net.">http://mtx.sourceforge.net.</A></P>
+<P>
+<HR>
+<H1><A NAME="author">AUTHOR</A></H1>
+<P>Tim Skirvin &lt;<A HREF="mailto:tskirvin@uiuc.edu">tskirvin@uiuc.edu</A>&gt;</P>
+<P>
+<HR>
+<H1><A NAME="copyright">COPYRIGHT</A></H1>
+<P>Copyright 2001-2002 by the University of Illinois Board of Trustees and
+Tim Skirvin &lt;<A HREF="mailto:tskirvin@ks.uiuc.edu">tskirvin@ks.uiuc.edu</A>&gt;.</P>
+
+</BODY>
+
+</HTML>
diff --git a/contrib/tapeinfo.py b/contrib/tapeinfo.py
new file mode 100644
index 0000000..d5df136
--- /dev/null
+++ b/contrib/tapeinfo.py
@@ -0,0 +1,55 @@
+# Copyright 2000 Enhanced Software Technologies Inc.
+# All Rights Reserved
+# Released under Free Software Foundation's General Public License,
+# Version 2 or above
+
+# Routine to call 'tapeinfo' and read status for a node. This is an
+# example of how to parse the 'tapeinfo' output from a scripting language.
+#
+
+import os
+import string
+import sys
+
+
+configdir="/opt/brupro/bin" # sigh.
+
+def inquiry(device):
+ retval={}
+
+ # okay, now do the thing:
+
+ command="%s/tapeinfo -f %s" % (configdir,device)
+
+ # Now to read:
+
+ infile=os.popen(command,"r")
+
+ try:
+ s=infile.readline()
+ except:
+ s=""
+ pass
+ if not s:
+ return None # did not get anything.
+ while s:
+ s=string.strip(s)
+ idx,val=string.split(s,':',1)
+ val=string.strip(val)
+ if val[0]=="'":
+ val=val[1:-1] # strip off single quotes, sigh.
+ val=string.strip(val)
+ pass
+ while "\0" in val:
+ # zapo!
+ val=string.replace(val,"\0","")
+ pass
+ retval[idx]=val
+ try:
+ s=infile.readline()
+ except:
+ s=""
+ pass
+ continue # to top of loop!
+ return retval
+
diff --git a/contrib/tapeload.pl b/contrib/tapeload.pl
new file mode 100644
index 0000000..de1f221
--- /dev/null
+++ b/contrib/tapeload.pl
@@ -0,0 +1,118 @@
+!/usr/bin/perl
+########################## tapeload ###########################
+# This script uses mtx 1.2.9pre2 to load a tape based
+# on its volume tag. You can
+# specify a tape drive by number, but if you don`t, it puts the
+# tape in the first available drive and returns the number of that drive,
+# both from the standard output and as the exit value.
+# A negative exit value indicates an error.
+# If volume tags are missing from any full slot, bar codes are rescanned
+# automatically.
+#
+# usage:
+# tapeload TAPE_LABEL_1 # Loads tape with label TAPE_LABEL_1 into a drive
+# or
+# tapeload TAPE_LABEL_1 1 # Loads tape with label TAPE_LABEL_1 into drive #1
+#
+
+# Set this variable to your mtx binary and proper scsi library device.
+$MTXBIN="/usr/local/bin/mtx -f /dev/sga" ;
+
+# Additions and corrections are welcome.
+# This software comes with absolutely no warranty and every other imaginable
+# disclaimer.
+# -- Frank Samuelson sam@milagro.lanl.gov
+##################################################################
+
+@wt= &mdo("status"); #slurp in the list of slots
+
+# Check to be certain that every full slot has a volume tag
+for ($i=0; $i< $#wt; $i++) { # look through every line
+ if ( $wt[$i] =~ /Full/ && $wt[$i] !~ /VolumeTag/ ) {
+ # if the element is full, but there is no volume tag, do inventory
+ @wt= &mdo("inventory status");
+ break;
+ }
+}
+
+#try to find our tape
+$slot=-1;
+for ($i=0; $i< $#wt; $i++) { # look through every line
+ if ($wt[$i] =~ / *Storage Element (d*):Full :VolumeTag=(.*)/ ) {
+ if ($ARGV[0] eq $2) { # We found the tape
+ $slot=$1; # set the slot number
+ break; # stop reading the rest of the file.
+ }
+ }
+}
+
+if ( $slot>0) { # we found the tape you wanted.
+
+ $drivefound=-1; # set flag to bad value
+ for ($i=0; $i< $#wt; $i++) { # look through every line
+ # if this is a tape drive
+ if ($wt[$i] =~ / *Data Transfer Element (d*):(.*)/ ) { #parse the line
+ $drive=$1;
+ $state=$2;
+# print STDERR "$wt[$i] $drive $state";
+ if ($state =~ /Full/) { # This drive is full.
+ # if we are looking for a particular drive and this is it
+ if ( $#ARGV==1 && $drive == $ARGV[1]) {
+ print STDERR " ERROR: Specified drive $ARGV[1] is full.";
+ print STDERR @wt;
+ exit(-6);
+ }
+ } elsif ($state =~ /Empty/) { #This is a tape drive and it`s empty.
+ if ( $#ARGV==1 ) { # If we want a particular drive
+ if ($drive == $ARGV[1]) { # and this is it,
+ $drivefound=$drive; # mark it so.
+ break;
+ }
+ } else { # If any old drive will do
+ $drivefound=$drive; # Mark it.
+ break;
+ }
+ } else { # This is a tape drive, but what the heck is it?
+ print STDERR " Cannot assess drive status in line";
+ print STDERR $wt[$i];
+ exit(-7);
+ }
+ }
+ }
+
+ if ( $drivefound < 0 ) { # specified drive was not found
+ print STDERR "Error: Specified drive $ARGV[1] was not found";
+ print STDERR @wt;
+ exit(-8);
+ }
+ # Now we actually load the tape.
+ @dump=&mdo(" load $slot $drivefound ");
+ print "$drivefound";
+ exit($drivefound);
+ # The end.
+
+
+} else {
+ print STDERR " Ug. Tape $ARGV[0] is not in the library.";
+ print STDERR @wt;
+ exit(-4);
+}
+
+
+sub mdo # a subroutine to call mtx ;
+{
+# print STDERR "$_[0]";
+ if (!open(FD,"$MTXBIN $_[0] |")) { #call mtx function
+ print STDERR " ERRKK. Could not start mtx ";
+ exit (-9);
+ }
+
+ @twt= <FD>; # slurp in the output
+
+ if (! close(FD)) { # if mtx exited with a nonzero value...
+ print STDERR " Mtx gave an error. Tapeload is exiting... ";
+ exit (-10);
+ }
+
+ @twt;
+}
diff --git a/contrib/tapeunload.pl b/contrib/tapeunload.pl
new file mode 100644
index 0000000..e52a4ef
--- /dev/null
+++ b/contrib/tapeunload.pl
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+########################## tapeunload ###########################
+# This script uses mtx 1.2.9pre2 to unload a tape
+# based on its volume tag. You can
+# specify a slot into which the tape should go, but if you don`t, it puts the
+# tape into the slot from which it was taken. This slot number
+# is returned
+# both from the standard output and as the exit value.
+# A negative exit value indicates an error.
+# If volume tags are missing from any full slot or drive,
+# bar codes are rescanned automatically.
+# Note: This script assumes that the tape is ready to be removed from
+# the drive. That means you may have to unload the tape from the drive
+# with "mt offline" before the tape can be moved to a storage slot.
+#
+
+# usage:
+# tapeunload TAPE_LABEL_1
+# Removes tape with label TAPE_LABEL_1 from a drive and puts it
+# back into its storage slot. Or,
+# tapeunload TAPE_LABEL_1 40
+# Removes tape with label TAPE_LABEL_1 from a drive and puts it
+# into its storage slot 40.
+#
+
+# Set this variable to your mtx binary and proper scsi library device.
+$MTXBIN="/usr/local/bin/mtx -f /dev/sga" ;
+
+# Additions and corrections are welcome.
+# This software comes with absolutely no warranty and every other imaginable
+# disclaimer.
+# -- Frank Samuelson sam@milagro.lanl.gov
+
+##################################################################
+
+@wt= &mdo("status"); #slurp in the list of slots
+
+# Check to be certain that every full slot has a volume tag
+# Rescanning probably will not help. I haven`t seen any bar code
+# readers that read tapes that are in the drives. But you never know...
+for ($i=0; $i< $#wt; $i++) { # look through every line
+ if ( $wt[$i] =~ /Full/ && $wt[$i] !~ /VolumeTag/ ) {
+ # if the element is full, but there is no volume tag, do inventory
+ @wt= &mdo("inventory status");
+ break;
+ }
+}
+
+#try to find our tape
+$drivein=-1;
+for ($i=0; $i< $#wt; $i++) { # look through every line
+ # for a full tape drive
+ if ($wt[$i] =~ / *Data Transfer Element (d*):Full (Storage Element
+(d*) Loaded):VolumeTag = (.*)/ ){
+ if ($ARGV[0] eq $3) { # We found our tape
+ $drivein=$1; # set the drive number
+ $slottogo=$2; # set the slot number
+ break; # stop reading the rest of the file.
+ }
+ }
+}
+
+if ( $drivein>=0) { # we found the tape you wanted.
+ if ($#ARGV==1) { #If an alternative slot was requested, set it.
+ $slottogo=$ARGV[1]; # and let mtx handle the errors.
+ }
+
+ # Now we unload the tape.
+ @dump=&mdo(" unload $slottogo $drivein ");
+ print "$slottogo";
+ exit($slottogo);
+ # The end.
+
+
+} else {
+ print STDERR " Ug. Tape $ARGV[0] is not in a tape drive.";
+ print STDERR @wt;
+ exit(-4);
+}
+
+
+sub mdo # a subroutine to call mtx ;
+{
+# print STDERR "$_[0]";
+ if (!open(FD,"$MTXBIN $_[0] |")) { #call mtx function
+ print STDERR " ERRKK. Could not start mtx ";
+ exit (-9);
+ }
+
+ @twt= <FD>; # slurp in the output
+
+ if (! close(FD)) { # if mtx exited with a nonzero value...
+ print STDERR " Mtx gave an error. Tapeload is exiting... ";
+ exit (-10);
+ }
+
+ @twt;
+}
diff --git a/debian/bash_completion b/debian/bash_completion
new file mode 100644
index 0000000..71852c0
--- /dev/null
+++ b/debian/bash_completion
@@ -0,0 +1,45 @@
+# mtx completion by Jon Middleton <jjm@ixtab.org.uk>
+#
+# $Id: bash_completion,v 1.1 2004-02-15 05:43:25 bdale Exp $
+
+_mtx()
+{
+ local cur prev options tapes drives
+
+ COMPREPLY=()
+ cur=${COMP_WORDS[COMP_CWORD]}
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ options="-f nobarcode invert noattach --version inquiry noattach \
+ inventory status load unload eepos first last next"
+
+ tapes=$(mtx status | \
+ awk '/Storage Element [0-9]+:Full/ { printf "%s ", $3 }')
+ tapes=${tapes//:Full}
+
+ drives=$(mtx status | \
+ awk '/Data Transfer Element [0-9]+:(Full|Empty)/ { printf "%s ", $4 }')
+ drives=${drives//:Full}
+ drives=${drives//:Empty}
+
+ if [ $COMP_CWORD -gt 1 ]; then
+ case $prev in
+ load)
+ COMPREPLY=( $( compgen -W "$tapes" -- $cur ) )
+ ;;
+ unload|first|last|next)
+ COMPREPLY=( $( compgen -W "$drives" -- $cur ) )
+ ;;
+ -f)
+ true
+ ;;
+ *)
+ true
+ ;;
+ esac
+ else
+ COMPREPLY=( $( compgen -W "$options" -- $cur ) )
+ fi
+ return 0
+}
+complete -F _mtx mtx
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..860dd53
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,159 @@
+mtx (1.3.12-1) unstable; urgency=low
+
+ * Incorporate debian packaging into upsteam version
+ * Remove strip of binaries
+ * Remove unsupported nsmhack from list of binaries built by default
+ * Add support for building outside of source tree
+ * Update copyrights
+ * Fix typo in mtx.1 man page
+ * Clear outstanding UNIT ATTENTION state at start
+
+ -- Robert Nelson <robertn@the-nelsons.org> Tue, 19 Aug 2008 09:04:00 +0000
+
+mtx (1.3.11-1) unstable; urgency=low
+
+ * new upstream version, closes: #425687, #425688
+ * don't let Makefile.in strip binaries, let dh_strip do it, closes: #437589
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 15 Apr 2008 14:34:32 -0600
+
+mtx (1.2.17rel-2) unstable; urgency=low
+
+ * update config.sub and config.guess in rules clean target using the
+ autotools-dev package, closes: #367467
+
+ -- Bdale Garbee <bdale@gag.com> Sat, 19 Aug 2006 18:44:54 -0600
+
+mtx (1.2.17rel-1) unstable; urgency=low
+
+ * new upstream version
+
+ -- Bdale Garbee <bdale@gag.com> Wed, 28 Jun 2006 23:57:44 -0400
+
+mtx (1.2.16rel-5) unstable; urgency=low
+
+ * add build-deps needed for GNU/kFreeBSD, closes: #367467
+ * update debhelper build dependency
+
+ -- Bdale Garbee <bdale@gag.com> Wed, 28 Jun 2006 23:42:00 -0400
+
+mtx (1.2.16rel-4) unstable; urgency=medium
+
+ * revert SG_SCSI_DEFAULT_TIMEOUT to 5 minutes since at least the Sony
+ TLS-9000 takes more than a minute to load sometimes, closes: #229169
+ * remove 'previous' from command summary, since it's not actually
+ implemented in the program, closes: #230041
+ * include bash_completion file from Jon Middleton, closes: #227456
+
+ -- Bdale Garbee <bdale@gag.com> Sat, 14 Feb 2004 22:36:23 -0700
+
+mtx (1.2.16rel-3) unstable; urgency=low
+
+ * apply patch from Torsten Werner <twerner@debian.org> that elminates
+ hard-coding of the value of HZ, closes: #224147
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 16 Dec 2003 10:04:26 -0700
+
+mtx (1.2.16rel-2) unstable; urgency=low
+
+ * apply patch from R.A.Owen <rao3@leicester.ac.uk> that fixes the "staggered"
+ output from the status command on some changers, closes: #129910
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 9 Apr 2002 19:30:06 -0600
+
+mtx (1.2.16rel-1) unstable; urgency=low
+
+ * new upstream version, bug-fixing release, reportedly fixes timeout
+ problem with some drives, closes: #113947
+
+ -- Bdale Garbee <bdale@gag.com> Mon, 4 Mar 2002 01:27:48 -0700
+
+mtx (1.2.15-1) unstable; urgency=low
+
+ * new upstream source
+ * update standards version, rebuild rules file
+ * man pages all included now, mtx-changer and other pieces from contrib
+ provided as examples, though chg-mtx in the amanda package is probably
+ a better choice for use with amanda, closes: #113728
+ * apply diffs to correct "spelling errors" (actually hyphenation) in the
+ descriptions in the control file, closes: #125160
+
+ -- Bdale Garbee <bdale@gag.com> Sun, 30 Dec 2001 21:28:46 -0700
+
+mtx (1.2.10-1) unstable; urgency=low
+
+ * new upstream source
+
+ -- Bdale Garbee <bdale@gag.com> Mon, 11 Dec 2000 17:34:13 -0700
+
+mtx (1.0-10) frozen unstable; urgency=low
+
+ * deliver mtx.doc, lost when the package was made FHS compliant,
+ closes: #56276 Target frozen since including the documentation
+ is worthwhile for potato, and there is no added risk.
+
+ -- Bdale Garbee <bdale@gag.com> Wed, 9 Feb 2000 12:27:58 -0700
+
+mtx (1.0-9) unstable; urgency=low
+
+ * fix postinst/postrm scripts to be executable again
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 11 Jan 2000 23:00:17 -0700
+
+mtx (1.0-8) unstable; urgency=low
+
+ * update to latest standards revision, add Build-Depends
+ * fix all the lintian errors that aren't intentional, override the two
+ permissions warnings since they're precisely what is needed
+
+ -- Bdale Garbee <bdale@gag.com> Fri, 7 Jan 2000 02:47:08 -0700
+
+mtx (1.0-7) unstable; urgency=low
+
+ * grab a local copy of scsi_ioctl.h from the 2.2.10 kernel source tree. This
+ doesn't change often in any way we care about, and this is much simpler
+ than having to reference a live kernel tree somewhere...
+ * move to debhelper and CVS
+
+ -- Bdale Garbee <bdale@gag.com> Sun, 20 Jun 1999 10:42:39 -0600
+
+mtx (1.0-6) unstable; urgency=low
+
+ * put mtx in group backup, setuid root, perms set so that only members of
+ group backup can run mtx. This makes mtx compatible with amanda.
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 27 Jan 1998 15:06:13 -0700
+
+mtx (1.0-5) unstable; urgency=low
+
+ * explicit include path to find <scsi/scsi_ioctl.h> in the
+ /usr/src/linux/include tree. closes bug 16877
+
+ -- Bdale Garbee <bdale@gag.com> Sun, 25 Jan 1998 23:02:46 -0700
+
+mtx (1.0-4) unstable; urgency=low
+
+ * actually install the mtx.doc file that's referenced in the man page /o\
+
+ -- Bdale Garbee <bdale@gag.com> Sun, 21 Sep 1997 02:38:50 -0600
+
+mtx (1.0-3) unstable; urgency=low
+
+ * libc6
+
+ -- Bdale Garbee <bdale@gag.com> Thu, 4 Sep 1997 02:56:39 -0600
+
+mtx (1.0-2) unstable; urgency=low
+
+ * Add an 'mtx-changer' wrapper script from the amanda-users mailing list
+ to make this more useful with Amanda.
+ * Hack mtx-changer to report 6 slots instead of 4, since I have an HP
+ SureStore 12000e. Should make it configurable, someday.
+
+ -- Bdale Garbee <bdale@gag.com> Sun, 10 Aug 1997 03:50:42 -0600
+
+mtx (1.0-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Bdale Garbee <bdale@gag.com> Sun, 10 Aug 1997 03:05:18 -0600
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+4
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..fa6c9d0
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,16 @@
+Source: mtx
+Section: admin
+Priority: extra
+Maintainer: Robert Nelson <robertn@the-nelsons.org>
+Build-Depends: debhelper (>= 4), libcam-dev [kfreebsd-i386 kfreebsd-amd64], autotools-dev
+Standards-Version: 3.7.3
+
+Package: mtx
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: controls tape autochangers
+ MTX can be used to manipulate tape auto-changers, also known as "jukeboxes",
+ such that backup software can make use of the multiple tape capabilities of
+ the auto-changer. In particular, this is necessary glue for using a backup
+ system like Amanda with a DDS auto-changer like the HP Surestore 12000e.
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..28fd2e0
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,15 @@
+This package was debianized by Bdale Garbee bdale@gag.com on
+Sun, 10 Aug 1997 03:05:18 -0600.
+
+mtx was downloaded from http://mtx.sourceforge.net/
+
+Copyright:
+
+ Copyright 1997, 1998 Leonard Zubkoff <lnz@dandelion.com>
+ Changes copyright 2000, 2001 Eric Green <eric@badtux.org>
+ Changes copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+ GPL, version 2
+
+On Debian GNU/Linux systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..ce5d4fb
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+etc/bash_completion.d
+usr/sbin
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..79c0cb2
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,69 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+
+export DH_VERBOSE=1
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ ./configure --prefix=/usr
+ touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp
+ dh_testdir
+ $(MAKE)
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+ [ ! -f Makefile ] || $(MAKE) distclean
+
+ -test -r /usr/share/misc/config.sub && \
+ cp -f /usr/share/misc/config.sub config.sub
+ -test -r /usr/share/misc/config.guess && \
+ cp -f /usr/share/misc/config.guess config.guess
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ make install bindir=`pwd`/debian/mtx/bin prefix=`pwd`/debian/mtx/usr \
+ mandir=`pwd`/debian/mtx/usr/share/man
+ install -o root -g root -m 0644 debian/bash_completion \
+ debian/mtx/etc/bash_completion.d/mtx
+
+# Build architecture-independent files here.
+binary-indep: build install
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs
+ dh_installexamples contrib/*
+ dh_installmenu
+ dh_installcron
+# dh_installman
+ dh_installinfo
+ dh_installchangelogs CHANGES
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/du/defs.h b/du/defs.h
new file mode 100644
index 0000000..2da35e7
--- /dev/null
+++ b/du/defs.h
@@ -0,0 +1,25 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef int DEVICE_TYPE;
+
+#ifdef __osf__
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <io/common/iotypes.h>
+#else /* must be ultrix */
+#include <sys/devio.h>
+#endif
+#include <io/cam/cam.h>
+#include <io/cam/uagt.h>
+#include <io/cam/dec_cam.h>
+#include <io/cam/scsi_all.h>
+#define DEV_CAM "/dev/cam" /* CAM device path */
+
+
+#define DIGITAL_UNIX
diff --git a/du/scsi.c b/du/scsi.c
new file mode 100644
index 0000000..8f11e16
--- /dev/null
+++ b/du/scsi.c
@@ -0,0 +1,214 @@
+/* SCSI.C - Digital Unix-specific SCSI routines.
+**
+** TECSys Development, Inc., April 1998
+**
+** This module began life as a part of XMCD, an X-windows CD player
+** program for many platforms. No real functionality from the original XMCD
+** is present in this module, but in the interest of making certain that
+** proper credit is given where it may be due, the copyrights and inclusions
+** from the XMCD module OS_DEC.C are included below.
+**
+** The portions of coding in this module ascribable to TECSys Development
+** are hereby also released under the terms and conditions of version 2
+** of the GNU General Public License as described below....
+*/
+
+/*
+ * libdi - scsipt SCSI Device Interface Library
+ *
+ * Copyright (C) 1993-1997 Ti Kan
+ * E-mail: ti@amb.org
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Digital UNIX (OSF/1) and Ultrix support
+ *
+ * Contributing author: Matt Thomas
+ * E-Mail: thomas@lkg.dec.com
+ *
+ * This software fragment contains code that interfaces the
+ * application to the Digital UNIX and Ultrix operating systems.
+ * The term Digital, Ultrix and OSF/1 are used here for identification
+ * purposes only.
+ */
+
+static int bus = -1,
+ target = -1,
+ lun = -1;
+
+static int SCSI_OpenDevice(char *DeviceName)
+{
+ int fd;
+ struct stat stbuf;
+ int saverr;
+
+ /* Check for validity of device node */
+ if (stat(DeviceName, &stbuf) < 0)
+ {
+ FatalError("cannot stat SCSI device '%s' - %m\n", DeviceName);
+ }
+ if (!S_ISCHR(stbuf.st_mode))
+ {
+ FatalError("device '%s': not appropriate device type - %m\n", DeviceName);
+ }
+
+ if ((fd = open(DeviceName, O_RDONLY | O_NDELAY, 0)) >= 0)
+ {
+ struct devget devget;
+
+ if (ioctl(fd, DEVIOCGET, &devget) >= 0)
+ {
+#ifdef __osf__
+ lun = devget.slave_num % 8;
+ devget.slave_num /= 8;
+#else
+ lun = 0;
+#endif
+ target = devget.slave_num % 8;
+ devget.slave_num /= 8;
+ bus = devget.slave_num % 8;
+ (void) close(fd);
+
+ if ((fd = open(DEV_CAM, O_RDWR, 0)) >= 0 ||
+ (fd = open(DEV_CAM, O_RDONLY, 0)) >= 0)
+ {
+ return (fd);
+ }
+ fd = bus = target = lun = -1;
+ FatalError("error %d opening SCSI device '%s' - %m\n",
+ errno, DEV_CAM);
+ }
+ else
+ {
+ (void) close(fd);
+ fd = bus = target = lun = -1;
+ FatalError("error %d on DEVIOCGET ioctl for '%s' - %m\n",
+ errno, DeviceName);
+ }
+ }
+ else
+ {
+ saverr = errno;
+ fd = bus = target = lun = -1;
+ FatalError("cannot open SCSI device '%s', error %d - %m\n",
+ DeviceName, saverr);
+ }
+
+ fd = bus = target = lun = -1;
+ return -1;
+}
+
+
+static void SCSI_CloseDevice(char *DeviceName, int DeviceFD)
+{
+ (void) close(DeviceFD);
+ bus = target = lun = -1;
+}
+
+
+static int SCSI_ExecuteCommand(int DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ UAGT_CAM_CCB uagt;
+ CCB_SCSIIO ccb;
+
+ if (DeviceFD < 0)
+ return -1;
+
+ (void) memset(&uagt, 0, sizeof(uagt));
+ (void) memset(&ccb, 0, sizeof(ccb));
+
+ /* Setup the user agent ccb */
+ uagt.uagt_ccb = (CCB_HEADER *) &ccb;
+ uagt.uagt_ccblen = sizeof(CCB_SCSIIO);
+
+ /* Setup the scsi ccb */
+ (void) memcpy((unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes,
+ CDB, CDB_Length);
+ ccb.cam_cdb_len = CDB_Length;
+ ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
+ ccb.cam_ch.cam_ccb_len = sizeof(CCB_SCSIIO);
+ ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
+
+ if (DataBuffer != NULL && DataBufferLength > 0)
+ {
+ ccb.cam_ch.cam_flags |= (Direction == Input) ?
+ CAM_DIR_IN : CAM_DIR_OUT;
+ uagt.uagt_buffer = (u_char *) DataBuffer;
+ uagt.uagt_buflen = DataBufferLength;
+ }
+ else
+ ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
+
+ ccb.cam_ch.cam_flags |= CAM_DIS_AUTOSENSE;
+ ccb.cam_data_ptr = uagt.uagt_buffer;
+ ccb.cam_dxfer_len = uagt.uagt_buflen;
+ ccb.cam_timeout = 300; /* Timeout set to 5 minutes */
+
+ ccb.cam_sense_ptr = (u_char *) RequestSense;
+ ccb.cam_sense_len = sizeof(RequestSense_T);
+
+ ccb.cam_ch.cam_path_id = bus;
+ ccb.cam_ch.cam_target_id = target;
+ ccb.cam_ch.cam_target_lun = lun;
+
+ if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
+ {
+ return -1;
+ }
+
+ /* Check return status */
+ if ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ {
+ if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN)
+ {
+ (void) memset(&ccb, 0, sizeof(ccb));
+ (void) memset(&uagt, 0, sizeof(uagt));
+
+ /* Setup the user agent ccb */
+ uagt.uagt_ccb = (CCB_HEADER *) &ccb;
+ uagt.uagt_ccblen = sizeof(CCB_RELSIM);
+
+ /* Setup the scsi ccb */
+ ccb.cam_ch.my_addr = (struct ccb_header *) &ccb;
+ ccb.cam_ch.cam_ccb_len = sizeof(CCB_RELSIM);
+ ccb.cam_ch.cam_func_code = XPT_REL_SIMQ;
+
+ ccb.cam_ch.cam_path_id = bus;
+ ccb.cam_ch.cam_target_id = target;
+ ccb.cam_ch.cam_target_lun = lun;
+
+ if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
+ return -1;
+ }
+
+ printf( "mtx: %s:\n%s=0x%x %s=0x%x\n",
+ "SCSI command fault",
+ "Opcode",
+ CDB[0],
+ "Status",
+ ccb.cam_scsi_status);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..b66097a
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,253 @@
+#!/bin/sh
+# $Date: 2001-06-05 10:10:15 -0700 (Tue, 05 Jun 2001) $
+# $Revision: 2 $
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# 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 M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/loaderinfo.1 b/loaderinfo.1
new file mode 100644
index 0000000..ea6da04
--- /dev/null
+++ b/loaderinfo.1
@@ -0,0 +1,90 @@
+.\" tapeinfo.1 Document copyright 2000 Eric Lee Green
+.\" Program Copyright 2000 Eric Lee Green <eric@badtux.org>
+.\" Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+.\"
+.\" This is free documentation; 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.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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 manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH LOADERINFO 1 LOADERINFO1.0
+.SH NAME
+loaderinfo \- report SCSI tape device info
+.SH SYNOPSIS
+loaderinfo -f <scsi-generic-device>
+.SH DESCRIPTION
+The
+.B loaderinfo
+command reads various information from SCSI tape loaders. Its intended
+use is for high-level programs that are trying to decide what the
+capabilities of a device are.
+.P
+The following are printed:
+.TP 10
+.B Element Address Assignment Page:
+This tells how many elements are in the loader, and what their raw
+hardware addresses are.
+
+.TP 10
+.B Transport Geometry Descriptor Page:
+Will display whether media is invertible or not (usable with some
+optical jukeboxes for detirmining whether to "flip" media after writing
+to the first side).
+
+.TP 10
+.B Device Capabilities Page
+Currently will only display whether we can transfer between slots (i.e.
+whether 'mtx transfer' works).
+
+.TP 10
+.B Inquiry Page
+Aside from the normal inquiry info, will also print out whether we have
+a bar code reader (for loaders that support the Exabyte extension for
+reporting presense of said reader).
+
+
+.SH OPTIONS
+The first argument, given following
+.B -f
+, is the SCSI generic device corresponding to your tape loader.
+Consult your operating system's documentation for more information (for
+example, under Linux these are generally start at /dev/sg0
+under FreeBSD these start at /dev/pass0).
+.P
+Under FreeBSD, 'camcontrol devlist' will tell you what SCSI devices you
+have, along with which 'pass' device controls them. Under Linux,
+"cat /proc/scsi/scsi" will tell you what SCSI devices you have. Under
+Solaris 8,
+.B find /devices -name '*changer*'
+will display the device names for your attached changers. Make sure
+to configure your 'sgen' driver first.
+
+.SH BUGS AND LIMITATIONS
+.P
+This program has only been tested on Linux with a limited number of
+loaders (Ecrix Autopack, Exabyte 220).
+.P
+.SH AVAILABILITY
+.B loaderinfo
+is currently being maintained by Robert Nelson <robertnelson@users.sourceforge.net>
+as part of the 'mtx' suite of programs. The 'mtx' home page is
+http://mtx.sourceforge.net and the actual code is currently available there and via
+SVN from http://sourceforge.net/projects/mtx.
+
+.SH SEE ALSO
+.BR mt (1), tapeinfo (1), mtx (1)
diff --git a/loaderinfo.c b/loaderinfo.c
new file mode 100644
index 0000000..b23867e
--- /dev/null
+++ b/loaderinfo.c
@@ -0,0 +1,510 @@
+/* Copyright 2000 Enhanced Software Technologies Inc.
+ * Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+ * Released under terms of the GNU General Public License as
+ * required by the license on 'mtxl.c'.
+ */
+
+/*
+* $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+* $Revision: 193 $
+*/
+
+/* What this does: Basically dumps out contents of:
+ * Mode Sense: Element Address Assignment Page (0x1d)
+ * 1Eh (Transport Geometry Parameters) has a bit which indicates is
+ * a robot is capable of rotating the media. It`s the
+ * `Rotate` bit, byte 2, bit 1.
+ * Device Capabilities page (0x1f)
+ * Inquiry -- prints full inquiry info.
+ * DeviceType:
+ * Manufacturer:
+ * ProdID:
+ * ProdRevision:
+ * If there is a byte 55, we use the Exabyte extension to
+ * print out whether we have a bar code reader or not. This is
+ * bit 0 of byte 55.
+ *
+ * Next, we request element status on the drives. We do not
+ * request volume tags though. If Exabyte
+ * extensions are supported, we report the following information for
+ * each drive:
+ *
+ * Drive number
+ * EXCEPT (with ASC and ASCQ), if there is a problem.
+ * SCSI address and LUN
+ * Tape drive Serial number
+ *
+ */
+
+#include <stdio.h>
+#include "mtx.h"
+#include "mtxl.h"
+
+DEVICE_TYPE MediumChangerFD; /* historic purposes... */
+
+char *argv0;
+
+/* A table for printing out the peripheral device type as ASCII. */
+static char *PeripheralDeviceType[32] =
+{
+ "Disk Drive",
+ "Tape Drive",
+ "Printer",
+ "Processor",
+ "Write-once",
+ "CD-ROM",
+ "Scanner",
+ "Optical",
+ "Medium Changer",
+ "Communications",
+ "ASC IT8",
+ "ASC IT8",
+ "RAID Array",
+ "Enclosure Services",
+ "OCR/W",
+ "Bridging Expander", /* 0x10 */
+ "Reserved", /* 0x11 */
+ "Reserved", /* 0x12 */
+ "Reserved", /* 0x13 */
+ "Reserved", /* 0x14 */
+ "Reserved", /* 0x15 */
+ "Reserved", /* 0x16 */
+ "Reserved", /* 0x17 */
+ "Reserved", /* 0x18 */
+ "Reserved", /* 0x19 */
+ "Reserved", /* 0x1a */
+ "Reserved", /* 0x1b */
+ "Reserved", /* 0x1c */
+ "Reserved", /* 0x1d */
+ "Reserved", /* 0x1e */
+ "Unknown" /* 0x1f */
+};
+
+
+/* okay, now for the structure of an Element Address Assignment Page: */
+
+typedef struct EAAP
+{
+ unsigned char Page_Code;
+ unsigned char Parameter_Length;
+ unsigned char MediumTransportElementAddress[2];
+ unsigned char NumMediumTransportElements[2];
+ unsigned char FirstStorageElementAdddress[2];
+ unsigned char NumStorageElements[2];
+ unsigned char FirstImportExportElementAddress[2];
+ unsigned char NumImportExportElements[2];
+ unsigned char FirstDataTransferElementAddress[2];
+ unsigned char NumDataTransferElements[2];
+ unsigned char Reserved[2];
+} EAAP_Type;
+
+/* okay, now for the structure of a transport geometry
+ * descriptor page:
+ */
+typedef struct TGDP
+{
+ unsigned char Page_Code;
+ unsigned char ParameterLength;
+ unsigned char Rotate;
+ unsigned char ElementNumber; /* we don't care about this... */
+} TGDP_Type;
+
+
+/* Structure of the Device Capabilities Page: */
+typedef struct DCP
+{
+ unsigned char Page_Code;
+ unsigned char ParameterLength;
+ unsigned char CanStore; /* bits about whether elements can store carts */
+ unsigned char SMC2_Caps;
+ unsigned char MT_Transfer; /* bits about whether mt->xx transfers work. */
+ unsigned char ST_Transfer; /* bits about whether st->xx transfers work. */
+ unsigned char IE_Transfer; /* bits about whether id->xx transfers work. */
+ unsigned char DT_Transfer; /* bits about whether DT->xx transfers work. */
+ unsigned char Reserved[4]; /* more reserved data */
+ unsigned char MT_Exchange; /* bits about whether mt->xx exchanges work. */
+ unsigned char ST_Exchange; /* bits about whether st->xx exchanges work. */
+ unsigned char IE_Exchange; /* bits about whether id->xx exchanges work. */
+ unsigned char DT_Exchange; /* bits about whether DT->xx exchanges work. */
+ unsigned char Reserved2[4]; /* more reserved data */
+} DCP_Type;
+
+#define MT_BIT 0x01
+#define ST_BIT 0x02
+#define IE_BIT 0x04
+#define DT_BIT 0x08
+
+/* Okay, now for the inquiry information: */
+
+static void ReportInquiry(DEVICE_TYPE MediumChangerFD)
+{
+ RequestSense_T RequestSense;
+ Inquiry_T *Inquiry;
+ int i;
+
+ Inquiry = RequestInquiry(MediumChangerFD,&RequestSense);
+ if (Inquiry == NULL)
+ {
+ PrintRequestSense(&RequestSense);
+ FatalError("INQUIRY Command Failed\n");
+ }
+
+ printf("Product Type: %s\n",PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
+
+ printf("Vendor ID: '");
+ for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
+ printf("%c", Inquiry->VendorIdentification[i]);
+
+ printf("'\nProduct ID: '");
+ for (i = 0; i < sizeof(Inquiry->ProductIdentification); i++)
+ printf("%c", Inquiry->ProductIdentification[i]);
+
+ printf("'\nRevision: '");
+ for (i = 0; i < sizeof(Inquiry->ProductRevisionLevel); i++)
+ printf("%c", Inquiry->ProductRevisionLevel[i]);
+
+ printf("'\n");
+
+ if (Inquiry->MChngr)
+ {
+ /* check the attached-media-changer bit... */
+ printf("Attached Changer: Yes\n");
+ }
+ else
+ {
+ printf("Attached Changer: No\n");
+ }
+
+ /* Now see if we have a bar code flag: */
+ if (Inquiry->AdditionalLength > 50)
+ {
+ /* see if we have 56 bytes: */
+ if (Inquiry->VendorFlags & 1)
+ {
+ printf("Bar Code Reader: Yes\n");
+ }
+ else
+ {
+ printf("Bar Code Reader: No\n");
+ }
+ }
+
+ free(Inquiry); /* well, we're about to exit, but ... */
+}
+
+/*********** MODE SENSE *******************/
+/* We need 3 different mode sense pages. This is a generic
+ * routine for obtaining mode sense pages.
+ */
+
+static unsigned char
+*mode_sense(DEVICE_TYPE fd, char pagenum, int alloc_len, RequestSense_T *RequestSense)
+{
+ CDB_T CDB;
+ unsigned char *input_buffer; /*the input buffer -- has junk prepended to
+ * actual sense page.
+ */
+ unsigned char *tmp;
+ unsigned char *retval; /* the return value. */
+ int i,pagelen;
+
+ if (alloc_len > 255)
+ {
+ FatalError("mode_sense(6) can only read up to 255 characters!\n");
+ }
+
+ input_buffer = (unsigned char *)xzmalloc(256); /* overdo it, eh? */
+
+ /* clear the sense buffer: */
+ slow_bzero((char *)RequestSense, sizeof(RequestSense_T));
+
+ /* returns an array of bytes in the page, or, if not possible, NULL. */
+ CDB[0] = 0x1a; /* Mode Sense(6) */
+ CDB[1] = 0x08;
+ CDB[2] = pagenum; /* the page to read. */
+ CDB[3] = 0;
+ CDB[4] = 255; /* allocation length. This does max of 256 bytes! */
+ CDB[5] = 0;
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,
+ input_buffer, 255, RequestSense) != 0)
+ {
+#ifdef DEBUG_MODE_SENSE
+ fprintf(stderr,"Could not execute mode sense...\n");
+ fflush(stderr);
+#endif
+ return NULL; /* sorry, couldn't do it. */
+ }
+
+ /* First skip past any header.... */
+ tmp = input_buffer + 4 + input_buffer[3];
+ /* now find out real length of page... */
+ pagelen=tmp[1] + 2;
+ retval = xmalloc(pagelen);
+ /* and copy our data to the new page. */
+ for (i = 0; i < pagelen; i++)
+ {
+ retval[i] = tmp[i];
+ }
+ /* okay, free our input buffer: */
+ free(input_buffer);
+ return retval;
+}
+
+/* Report the Element Address Assignment Page */
+static void ReportEAAP(DEVICE_TYPE MediumChangerFD)
+{
+ EAAP_Type *EAAP;
+ RequestSense_T RequestSense;
+
+ EAAP = (EAAP_Type *)mode_sense(MediumChangerFD, 0x1d, sizeof(EAAP_Type), &RequestSense);
+
+ if (EAAP == NULL)
+ {
+ PrintRequestSense(&RequestSense);
+ printf("EAAP: No\n");
+ return;
+ }
+
+ /* we did get an EAAP, so do our thing: */
+ printf("EAAP: Yes\n");
+ printf("Number of Medium Transport Elements: %d\n", ( ((unsigned int)EAAP->NumMediumTransportElements[0]<<8) + (unsigned int)EAAP->NumMediumTransportElements[1]));
+ printf("Number of Storage Elements: %d\n", ( ((unsigned int)EAAP->NumStorageElements[0]<<8) + (unsigned int)EAAP->NumStorageElements[1]));
+ printf("Number of Import/Export Elements: %d\n", ( ((unsigned int)EAAP->NumImportExportElements[0]<<8) + (unsigned int)EAAP->NumImportExportElements[1]));
+ printf("Number of Data Transfer Elements: %d\n", ( ((unsigned int)EAAP->NumDataTransferElements[0]<<8) + (unsigned int)EAAP->NumDataTransferElements[1]));
+
+ free(EAAP);
+}
+
+/* See if we can get some invert information: */
+
+static void Report_TGDP(DEVICE_TYPE MediumChangerFD)
+{
+ TGDP_Type *result;
+
+ RequestSense_T RequestSense;
+
+ result=(TGDP_Type *)mode_sense(MediumChangerFD,0x1e,255,&RequestSense);
+
+ if (!result)
+ {
+ printf("Transport Geometry Descriptor Page: No\n");
+ return;
+ }
+
+ printf("Transport Geometry Descriptor Page: Yes\n");
+
+ /* Now print out the invert bit: */
+ if ( result->Rotate & 1 )
+ {
+ printf("Invertable: Yes\n");
+ }
+ else
+ {
+ printf("Invertable: No\n");
+ }
+
+ free(result);
+}
+
+/* Okay, let's get the Device Capabilities Page. We don't care
+ * about much here, just whether 'mtx transfer' will work (i.e.,
+ * ST->ST).
+ */
+
+void TransferExchangeTargets(unsigned char ucValue, char *szPrefix)
+{
+ if (ucValue & DT_BIT)
+ {
+ printf("%sData Transfer", szPrefix);
+ }
+
+ if (ucValue & IE_BIT)
+ {
+ printf("%s%sImport/Export", ucValue > (IE_BIT | (IE_BIT - 1)) ? ", " : "", szPrefix);
+ }
+
+ if (ucValue & ST_BIT)
+ {
+ printf("%s%sStorage", ucValue > (ST_BIT | (ST_BIT - 1)) ? ", " : "", szPrefix);
+ }
+
+ if (ucValue & MT_BIT)
+ {
+ printf("%s%sMedium Transfer", ucValue > (MT_BIT | (MT_BIT - 1)) ? ", " : "", szPrefix);
+ }
+}
+
+static void Report_DCP(DEVICE_TYPE MediumChangerFD)
+{
+ DCP_Type *result;
+ RequestSense_T RequestSense;
+
+ /* Get the page. */
+ result=(DCP_Type *)mode_sense(MediumChangerFD,0x1f,sizeof(DCP_Type),&RequestSense);
+ if (!result)
+ {
+ printf("Device Configuration Page: No\n");
+ return;
+ }
+
+ printf("Device Configuration Page: Yes\n");
+
+ printf("Storage: ");
+
+ if (result->CanStore & DT_BIT)
+ {
+ printf("Data Transfer");
+ }
+
+ if (result->CanStore & IE_BIT)
+ {
+ printf("%sImport/Export", result->CanStore > (IE_BIT | (IE_BIT - 1)) ? ", " : "");
+ }
+
+ if (result->CanStore & ST_BIT)
+ {
+ printf("%sStorage", result->CanStore > (ST_BIT | (ST_BIT - 1)) ? ", " : "");
+ }
+
+ if (result->CanStore & MT_BIT)
+ {
+ printf("%sMedium Transfer", result->CanStore > (MT_BIT | (MT_BIT - 1)) ? ", " : "");
+ }
+
+ printf("\n");
+
+ printf("SCSI Media Changer (rev 2): ");
+
+ if (result->SMC2_Caps & 0x01)
+ {
+ printf("Yes\n");
+
+ printf("Volume Tag Reader Present: %s\n", result->SMC2_Caps & 0x02 ? "Yes" : "No");
+ printf("Auto-Clean Enabled: %s\n", result->SMC2_Caps & 0x04 ? "Yes" : "No");
+ }
+ else
+ {
+ printf("No\n");
+ }
+
+ printf("Transfer Medium Transport: ");
+ if ((result->MT_Transfer & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->MT_Transfer, "->");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nTransfer Storage: ");
+ if ((result->ST_Transfer & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->ST_Transfer, "->");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nTransfer Import/Export: ");
+ if ((result->IE_Transfer & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->IE_Transfer, "->");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nTransfer Data Transfer: ");
+ if ((result->DT_Transfer & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->DT_Transfer, "->");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nExchange Medium Transport: ");
+ if ((result->MT_Exchange & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->MT_Exchange, "<>");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nExchange Storage: ");
+ if ((result->ST_Exchange & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->ST_Exchange, "<>");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nExchange Import/Export: ");
+ if ((result->IE_Exchange & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->IE_Exchange, "<>");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\nExchange Data Transfer: ");
+ if ((result->DT_Exchange & 0x0F) != 0)
+ {
+ TransferExchangeTargets(result->DT_Exchange, "<>");
+ }
+ else
+ {
+ printf("None");
+ }
+
+ printf("\n");
+
+ free(result);
+}
+
+void usage(void)
+{
+ FatalError("Usage: loaderinfo -f <generic-device>\n");
+}
+
+
+/* we only have one argument: "-f <device>". */
+int main(int argc, char **argv)
+{
+ DEVICE_TYPE fd;
+ char *filename;
+
+ argv0=argv[0];
+ if (argc != 3)
+ {
+ fprintf(stderr,"argc=%d",argc);
+ usage();
+ }
+
+ if (strcmp(argv[1],"-f")!=0)
+ {
+ usage();
+ }
+
+ filename=argv[2];
+
+ fd=SCSI_OpenDevice(filename);
+
+ /* Now to call the various routines: */
+ ReportInquiry(fd);
+ ReportEAAP(fd);
+ Report_TGDP(fd);
+ Report_DCP(fd);
+ exit(0);
+}
diff --git a/makedist b/makedist
new file mode 100755
index 0000000..93f8121
--- /dev/null
+++ b/makedist
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# note -- this assumes 'bash' shell, GNU tar, 'gzip'.
+
+# pass a version number e.g. 1.4.3 as 1st parameter...
+ME=`pwd`
+
+# okay, now to create a spec file w/the proper version number:
+sed -e "1,\$s/@@VERSION@@/${1}/g" <mtx.spec.in >mtx.spec
+
+cd ..
+if [ ! -s mtx-${1} ]
+then
+ ln -s "${ME}" "mtx-${1}"
+fi
+
+
+tar --exclude CVS --exclude .svn -czvhf mtx-${1}.tar.gz mtx-${1}
+
diff --git a/mam2debug.c b/mam2debug.c
new file mode 100644
index 0000000..7fb8231
--- /dev/null
+++ b/mam2debug.c
@@ -0,0 +1,124 @@
+/* Mammoth 2 Debug Buffer Dumper
+ Copyright 2000 Enhanced Software Technologies Inc.
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ Written by Eric Lee Green <eric@badtux.org>
+ Released under the terms of the GNU General Public License v2 or
+ above.
+
+ This is an example of how to use the mtx library file 'mtxl.c' to
+ do a special-purpose task -- dump the Mammoth2 debug buffer, in this case.
+ Note that this debug buffer is 1M-4M in size, thus may overwhelm the
+ SCSI generic subsystem on some supported platforms...
+
+ syntax:
+
+ mam2debug generic-filename output-filename.
+
+
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "mtx.h"
+#include "mtxl.h"
+
+/* This is a TOTALLY UNDOCUMENTED feature to read the debug data buffer
+ * in an Exabyte Mammoth II and dump it to a file:
+ */
+
+static RequestSense_T *DumpM2DebugBuff(DEVICE_TYPE MediumChangerFD, int outfile)
+{
+ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T));
+ CDB_T CDB;
+
+ unsigned char *databuffer;
+ unsigned char buff_descriptor[4];
+ int numbytes;
+ int testbytes;
+
+ CDB[0]=0x3c; /* command. */
+ CDB[1]=0x03; /* mode - read buff_descriptor! */
+ CDB[2]=0x01; /* page. */
+ CDB[3]=0; /* offset. */
+ CDB[4]=0;
+ CDB[5]=0;
+ CDB[6]=0; /* length. */
+ CDB[7]=0;
+ CDB[8]=4; /* the descriptor is 4 long. */
+ CDB[9]=0;
+
+ if ((testbytes=SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 10,
+ buff_descriptor, 4, RequestSense)) != 0){
+ fprintf(stderr,"mam2debug: could not read buff_descriptor. [%d]\n",testbytes);
+ return RequestSense; /* couldn't do it. */
+ }
+
+ /* okay, read numbytes: */
+ numbytes=(buff_descriptor[1]<<16) + (buff_descriptor[2]<<8) + buff_descriptor[3];
+ databuffer=(unsigned char *) xmalloc(numbytes+1000000); /* see if this helps :-(. */
+ CDB[6]=buff_descriptor[1];
+ CDB[7]=buff_descriptor[2];
+ CDB[8]=buff_descriptor[3];
+
+ CDB[1]=0x02; /* mode -- read buffer! */
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 10,
+ databuffer, numbytes, RequestSense) != 0){
+ fprintf(stderr,"mam2debug: could not read buffer.\n");
+ free(databuffer);
+ return RequestSense; /* couldn't do it. */
+ }
+
+ write(outfile,databuffer,numbytes);
+ close(outfile);
+ free(databuffer);
+ free(RequestSense);
+ return NULL; /* okay! */
+}
+
+static void usage(void) {
+ fprintf(stderr,"Usage: mam2debug scsi-generic-file output-file-name\n");
+ exit(1);
+}
+
+/* Now for the actual main() routine: */
+
+int main(int argc,char** argv) {
+ DEVICE_TYPE changer_fd;
+ static RequestSense_T *result;
+ int outfile;
+
+ if (argc != 3) {
+ usage();
+ }
+
+ changer_fd=SCSI_OpenDevice(argv[1]);
+
+ if (changer_fd <= 0) {
+ fprintf(stderr,"Could not open input device\n");
+ usage();
+ }
+
+ outfile=open(argv[2],O_CREAT|O_WRONLY);
+ if (outfile <=0) {
+ fprintf(stderr,"Could not open output file\n");
+ usage();
+ }
+
+ result=DumpM2DebugBuff(changer_fd, outfile);
+
+ if (result) {
+ PrintRequestSense(result);
+ exit(1);
+ }
+
+ exit(0);
+}
+
diff --git a/mam2debug2.c b/mam2debug2.c
new file mode 100644
index 0000000..9d59395
--- /dev/null
+++ b/mam2debug2.c
@@ -0,0 +1,124 @@
+/* Mammoth 2 Debug Buffer Dumper
+ Copyright 2000 Enhanced Software Technologies Inc.
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ Written by Eric Lee Green <eric@badtux.org>
+ Released under the terms of the GNU General Public License v2 or
+ above.
+
+ This is an example of how to use the mtx library file 'mtxl.c' to
+ do a special-purpose task -- dump the Mammoth2 debug buffer, in this case.
+ Note that this debug buffer is 1M-4M in size, thus may overwhelm the
+ SCSI generic subsystem on some supported platforms...
+
+ syntax:
+
+ mam2debug generic-filename output-filename.
+
+
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "mtx.h"
+#include "mtxl.h"
+
+/* This is a TOTALLY UNDOCUMENTED feature to read the debug data buffer
+ * in an Exabyte Mammoth II and dump it to a file:
+ */
+
+static RequestSense_T *DumpM2DebugBuff(DEVICE_TYPE MediumChangerFD, int outfile)
+{
+ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T));
+ CDB_T CDB;
+
+ unsigned char *databuffer;
+ unsigned char buff_descriptor[4];
+ int numbytes;
+ int testbytes;
+
+ CDB[0]=0x3c; /* command. */
+ CDB[1]=0x03; /* mode - read buff_descriptor! */
+ CDB[2]=0x00; /* page -- data. */
+ CDB[3]=0; /* offset. */
+ CDB[4]=0;
+ CDB[5]=0;
+ CDB[6]=0; /* length. */
+ CDB[7]=0;
+ CDB[8]=4; /* the descriptor is 4 long. */
+ CDB[9]=0;
+
+ if ((testbytes=SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 10,
+ buff_descriptor, 4, RequestSense)) != 0){
+ fprintf(stderr,"mam2debug: could not read buff_descriptor. [%d]\n",testbytes);
+ return RequestSense; /* couldn't do it. */
+ }
+
+ /* okay, read numbytes: */
+ numbytes=(buff_descriptor[1]<<16) + (buff_descriptor[2]<<8) + buff_descriptor[3];
+ databuffer=(unsigned char *) xmalloc(numbytes+1000000); /* see if this helps :-(. */
+ CDB[6]=buff_descriptor[1];
+ CDB[7]=buff_descriptor[2];
+ CDB[8]=buff_descriptor[3];
+
+ CDB[1]=0x02; /* mode -- read buffer! */
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 10,
+ databuffer, numbytes, RequestSense) != 0){
+ fprintf(stderr,"mam2debug: could not read buffer.\n");
+ free(databuffer);
+ return RequestSense; /* couldn't do it. */
+ }
+
+ write(outfile,databuffer,numbytes);
+ close(outfile);
+ free(databuffer);
+ free(RequestSense);
+ return NULL; /* okay! */
+}
+
+static void usage(void) {
+ fprintf(stderr,"Usage: mam2debug scsi-generic-file output-file-name\n");
+ exit(1);
+}
+
+/* Now for the actual main() routine: */
+
+int main(int argc,char** argv) {
+ DEVICE_TYPE changer_fd;
+ static RequestSense_T *result;
+ int outfile;
+
+ if (argc != 3) {
+ usage();
+ }
+
+ changer_fd=SCSI_OpenDevice(argv[1]);
+
+ if (changer_fd <= 0) {
+ fprintf(stderr,"Could not open input device\n");
+ usage();
+ }
+
+ outfile=open(argv[2],O_CREAT|O_WRONLY);
+ if (outfile <=0) {
+ fprintf(stderr,"Could not open output file\n");
+ usage();
+ }
+
+ result=DumpM2DebugBuff(changer_fd, outfile);
+
+ if (result) {
+ PrintRequestSense(result);
+ exit(1);
+ }
+
+ exit(0);
+}
+
diff --git a/msvc/config.h b/msvc/config.h
new file mode 100644
index 0000000..08902cb
--- /dev/null
+++ b/msvc/config.h
@@ -0,0 +1,37 @@
+/* config.h. Generated by configure. */
+/* Copyright 2001 Enhanced Software Technologies Inc.
+ * Released under GNU General Public License V2 or Above
+ * See http://www.gnu.org for more information about the terms of
+ * the GNU General Public License.
+ * $Date: 2007-01-28 19:23:33 -0800 (Sun, 28 Jan 2007) $
+ * $Revision: 125 $
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H 1
+
+/* autoconf changes these. */
+#define HAVE_STRING_H 1
+#define HAVE_UNISTD_H 0
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_SCSI_SCSI_H 0
+#define HAVE_SCSI_SCSI_IOCTL_H 0
+#define HAVE_SCSI_SG_H 0
+#define HAVE_SYS_GSCDDS_H 0
+#define HAVE_CAMLIB_H 0
+#define HAVE_SYS_SCSI_IMPL_USCSI_H 0
+#define HAVE_SYS_SCSI_CTL_H 0
+#define HAVE_DSLIB_H 0
+#define HAVE_DU_DEFS_H 0
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_SYS_IOCTL_H 0
+#define HAVE_SYS_MTIO_H 0
+#define HAVE_DDK_NTDDSCSI_H 0
+
+#define WORDS_BIGENDIAN 0
+
+#endif
+
diff --git a/msvc/loaderinfo/loaderinfo.vcproj b/msvc/loaderinfo/loaderinfo.vcproj
new file mode 100644
index 0000000..4d3df91
--- /dev/null
+++ b/msvc/loaderinfo/loaderinfo.vcproj
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="loaderinfo"
+ ProjectGUID="{13712060-F1FC-4498-97A7-5DA5A38F04DD}"
+ RootNamespace="loaderinfo"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".."
+ PreprocessorDefinitions="WIN32;_DEBUG;DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\loaderinfo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\mtxl.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/msvc/mtx.sln b/msvc/mtx.sln
new file mode 100644
index 0000000..3b39f7f
--- /dev/null
+++ b/msvc/mtx.sln
@@ -0,0 +1,50 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loaderinfo", "loaderinfo\loaderinfo.vcproj", "{13712060-F1FC-4498-97A7-5DA5A38F04DD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mtx", "mtx\mtx.vcproj", "{7DD926F5-30EA-47D4-B67B-E32C0E221440}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scsitape", "scsitape\scsitape.vcproj", "{D19E95BD-87C6-4C91-A208-FB8338580F75}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tapeinfo", "tapeinfo\tapeinfo.vcproj", "{A1C8D34F-66EC-4F74-8261-C96B97727218}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsmhack", "nsmhack\nsmhack.vcproj", "{1B3C0A23-4021-4928-92FA-76743B7F7F76}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scsieject", "scsieject\scsieject.vcproj", "{E3B77A78-FD72-4AD7-933A-0503FB21551D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {13712060-F1FC-4498-97A7-5DA5A38F04DD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {13712060-F1FC-4498-97A7-5DA5A38F04DD}.Debug|Win32.Build.0 = Debug|Win32
+ {13712060-F1FC-4498-97A7-5DA5A38F04DD}.Release|Win32.ActiveCfg = Release|Win32
+ {13712060-F1FC-4498-97A7-5DA5A38F04DD}.Release|Win32.Build.0 = Release|Win32
+ {7DD926F5-30EA-47D4-B67B-E32C0E221440}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7DD926F5-30EA-47D4-B67B-E32C0E221440}.Debug|Win32.Build.0 = Debug|Win32
+ {7DD926F5-30EA-47D4-B67B-E32C0E221440}.Release|Win32.ActiveCfg = Release|Win32
+ {7DD926F5-30EA-47D4-B67B-E32C0E221440}.Release|Win32.Build.0 = Release|Win32
+ {D19E95BD-87C6-4C91-A208-FB8338580F75}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D19E95BD-87C6-4C91-A208-FB8338580F75}.Debug|Win32.Build.0 = Debug|Win32
+ {D19E95BD-87C6-4C91-A208-FB8338580F75}.Release|Win32.ActiveCfg = Release|Win32
+ {D19E95BD-87C6-4C91-A208-FB8338580F75}.Release|Win32.Build.0 = Release|Win32
+ {A1C8D34F-66EC-4F74-8261-C96B97727218}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A1C8D34F-66EC-4F74-8261-C96B97727218}.Debug|Win32.Build.0 = Debug|Win32
+ {A1C8D34F-66EC-4F74-8261-C96B97727218}.Release|Win32.ActiveCfg = Release|Win32
+ {A1C8D34F-66EC-4F74-8261-C96B97727218}.Release|Win32.Build.0 = Release|Win32
+ {1B3C0A23-4021-4928-92FA-76743B7F7F76}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1B3C0A23-4021-4928-92FA-76743B7F7F76}.Debug|Win32.Build.0 = Debug|Win32
+ {1B3C0A23-4021-4928-92FA-76743B7F7F76}.Release|Win32.ActiveCfg = Release|Win32
+ {1B3C0A23-4021-4928-92FA-76743B7F7F76}.Release|Win32.Build.0 = Release|Win32
+ {E3B77A78-FD72-4AD7-933A-0503FB21551D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E3B77A78-FD72-4AD7-933A-0503FB21551D}.Debug|Win32.Build.0 = Debug|Win32
+ {E3B77A78-FD72-4AD7-933A-0503FB21551D}.Release|Win32.ActiveCfg = Release|Win32
+ {E3B77A78-FD72-4AD7-933A-0503FB21551D}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/msvc/mtx/Distributions.txt b/msvc/mtx/Distributions.txt
new file mode 100644
index 0000000..7f13a59
--- /dev/null
+++ b/msvc/mtx/Distributions.txt
@@ -0,0 +1,49 @@
+Debian
+======
+
+Maintainer: BDale Garbee (bdale@gag.com) (Official)
+Stable Version: 1.2.16rel-4
+Testing Version: 1.2.17rel-2
+
+Merged: Yes
+
+FreeBSD
+
+Maintainer: mbr@freebsd.org
+Stable Version: 1.2.17rel
+
+Merged: Yes
+
+Gentoo
+======
+
+Maintainer: Tom Gall (tgall@gentoo.org) (Last change)
+Stable Version: 1.2.18
+
+Merged: No changes
+
+Mandriva
+========
+
+Maintainer: Buchan Milne <bgmilne@linux-mandrake.com>
+Stable Version: 1.2.18-1mdk
+
+Merged: No changes
+
+
+Redhat
+======
+
+Maintainer: Jesse Keating <jkeating@redhat.com> (Last change) (jnovy@redhat.com)
+Stable Version: 1.2.18-8
+
+Merged: No additional changes
+
+
+SuSE
+====
+
+Maintainer http://www.suse.de/feedback
+Stable Version: 1.2.18rel-119
+
+Merged: No additional changes
diff --git a/msvc/mtx/mtx.vcproj b/msvc/mtx/mtx.vcproj
new file mode 100644
index 0000000..bffae8e
--- /dev/null
+++ b/msvc/mtx/mtx.vcproj
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="mtx"
+ ProjectGUID="{7DD926F5-30EA-47D4-B67B-E32C0E221440}"
+ RootNamespace="mtx"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="VERSION=\&quot;1.3.9-rbn\&quot;;LONG_PRINT_REQUEST_SENSE;WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="VERSION=\&quot;1.3.11\&quot;;WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\mtx.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\mtxl.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\mtx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\mtxl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <File
+ RelativePath=".\Distributions.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/msvc/nsmhack/nsmhack.vcproj b/msvc/nsmhack/nsmhack.vcproj
new file mode 100644
index 0000000..9bebb9c
--- /dev/null
+++ b/msvc/nsmhack/nsmhack.vcproj
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="nsmhack"
+ ProjectGUID="{1B3C0A23-4021-4928-92FA-76743B7F7F76}"
+ RootNamespace="nsmhack"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\mtxl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\nsmhack.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\mtx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\mtxl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/msvc/scsieject/scsieject.vcproj b/msvc/scsieject/scsieject.vcproj
new file mode 100644
index 0000000..ca08707
--- /dev/null
+++ b/msvc/scsieject/scsieject.vcproj
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="scsieject"
+ ProjectGUID="{E3B77A78-FD72-4AD7-933A-0503FB21551D}"
+ RootNamespace="scsieject"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4214;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4214;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\mtxl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\scsieject.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/msvc/scsitape/scsitape.vcproj b/msvc/scsitape/scsitape.vcproj
new file mode 100644
index 0000000..cc2d55b
--- /dev/null
+++ b/msvc/scsitape/scsitape.vcproj
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="scsitape"
+ ProjectGUID="{D19E95BD-87C6-4C91-A208-FB8338580F75}"
+ RootNamespace="scsitape"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4214;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4214;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\mtxl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\scsitape.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/msvc/tapeinfo/tapeinfo.vcproj b/msvc/tapeinfo/tapeinfo.vcproj
new file mode 100644
index 0000000..07e8ecc
--- /dev/null
+++ b/msvc/tapeinfo/tapeinfo.vcproj
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="tapeinfo"
+ ProjectGUID="{A1C8D34F-66EC-4F74-8261-C96B97727218}"
+ RootNamespace="tapeinfo"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4214"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\mtxl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tapeinfo.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\mtx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\mtxl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mtx.1 b/mtx.1
new file mode 100644
index 0000000..a5e6cc6
--- /dev/null
+++ b/mtx.1
@@ -0,0 +1,257 @@
+.\" mtx.1 Document copyright 2000 Eric Lee Green
+.\" Program Copyright 1996, 1997 Leonard Zubkoff
+.\" Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+.\" Extensive changes 2000 by Eric Lee Green <eric@badtux.org>
+.\"
+.\" This is free documentation; 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.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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 manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH MTX 1 MTX1.3
+.SH NAME
+mtx \- control SCSI media changer devices
+.SH SYNOPSIS
+mtx [-f <scsi-generic-device>] [nobarcode] [invert] [noattach] command [ command ... ]
+.SH DESCRIPTION
+The
+.B mtx
+command controls single or multi-drive SCSI media changers such as
+tape changers, autoloaders, tape libraries, or optical media jukeboxes.
+It can also be used with media changers that use the 'ATTACHED' API,
+presuming that they properly report the MChanger bit as required
+by the SCSI T-10 SMC specification.
+.SH OPTIONS
+The first argument, given following
+.B -f
+, is the SCSI generic device corresponding to your media changer.
+Consult your operating system's documentation for more information (for
+example, under Linux these are generally /dev/sg0 through /dev/sg15,
+under FreeBSD these are /dev/pass0 through /dev/passX,
+under SunOS it may be a file under /dev/rdsk).
+.P
+The 'invert' option will invert (flip) the media (for optical jukeboxes that
+allow such) before inserting it into the drive or returning it to the
+storage slot.
+.P
+The 'noattach' option forces the regular media changer API even if the
+media changer incorrectly reported that it uses the 'ATTACHED' API.
+.P
+The 'nobarcode' option forces the loader to not request barcodes even if
+the loader is capable of reporting them.
+.P
+Following these options there may follow
+one or more robotics control
+commands. Note that the 'invert' and 'noattach'
+options apply to ALL of robotics control
+commands.
+
+.SH COMMANDS
+.TP 10
+.B --version
+Report the mtx version number (e.g. mtx 1.2.8) and exit.
+
+.TP 10
+.B inquiry
+Report the product type (Medium Changer, Tape Drive, etc.), Vendor ID,
+Product ID, Revision, and whether this uses the Attached Changer API
+(some tape drives use this rather than reporting a Medium Changer on a
+separate LUN or SCSI address).
+.TP 10
+.B noattach
+Make further commands use the regular media changer API rather than the
+_ATTACHED API, no matter what the "Attached" bit said in the Inquiry info.
+Needed with some brain-dead changers that report Attached bit but don't respond
+to _ATTACHED API.
+.TP 10
+.B inventory
+Makes the robot arm go and check what elements are in the slots. This
+is needed for a few libraries like the Breece Hill ones that do not
+automatically check the tape inventory at system startup.
+.TP 10
+.B status
+Reports how many drives and storage elements are contained in the
+device. For each drive, reports whether it has media loaded in it, and
+if so, from which storage slot the media originated. For each storage
+slot, reports whether it is empty or full, and if the media changer
+has a bar code, MIC reader, or some other way of uniquely identifying
+media without loading it into a drive, this reports the volume tag
+and/or alternate volume tag for each piece of media.
+For historical reasons drives are numbered from 0 and storage slots are
+numbered from 1.
+.TP 10
+.B load <slotnum> [ <drivenum> ]
+Load media from slot <slotnum> into drive <drivenum>. Drive 0 is assumed
+if the drive number is omitted.
+.TP 10
+.B unload [<slotnum>] [ <drivenum> ]
+Unloads media from drive <drivenum> into slot <slotnum>. If <drivenum> is
+omitted, defaults to drive 0 (as do all commands).
+If <slotnum> is omitted, defaults to the slot
+that the drive was loaded from. Note that there's currently no way to
+say 'unload drive 1's media to the slot it came from', other than to
+explicitly use that slot number as the destination.
+.TP 10
+.B [eepos <operation>] transfer <slotnum> <slotnum>
+Transfers media from one slot to another, assuming that your mechanism is
+capable of doing so. Usually used to move media to/from an import/export
+port. 'eepos' is used to extend/retract the import/export
+tray on certain mid-range to high end tape libraries (if, e.g., the tray was
+slot 32, you might say say 'eepos 1 transfer 32 32' to extend the tray).
+Valid values for eepos <operation>
+are 0 (do nothing to the import/export tray), 1, and 2 (what 1 and 2 do varies
+depending upon the library, consult your library's SCSI-level
+documentation).
+.TP 10
+.B [eepos <operation>] [invert] [invert2] exchange <slotnum> <slotnum> [<slotnum>]
+Move medium from the first slot to the second slot, placing the medium
+currently in the second slot either back into the first slot or into the
+optional third slot.
+
+.TP 10
+.B first [<drivenum>]
+Loads drive <drivenum> from the first slot in the media
+changer. Unloads the drive if there is already media in it (note: you
+may need to eject the tape using your OS's tape control commands
+first). Note that this command may not be what you want on large
+tape libraries -- e.g. on Exabyte 220, the first slot is usually a
+cleaning tape. If <drivenum> is omitted, defaults to first drive.
+
+.TP 10
+.B last [<drivenum>]
+Loads drive <drivenum> from the last slot in the media changer. Unloads
+the drive if there is already a tape in it. (Note: you may need to eject
+the tape using your OS's tape control commands first).
+.TP 10
+.B next [<drivenum>]
+Unloads the drive and loads the next tape in sequence. If the drive was
+empty, loads the first tape into the drive.
+.TP 10
+.B position <slotnum>
+Positions the robot at a specific slot. Needed by some changers to
+move to and open the import/export, or mailbox, slot.
+
+.SH AUTHORS
+The original 'mtx' program was written by Leonard Zubkoff and extensively
+revised for large multi-drive libraries with bar code readers
+by Eric Lee Green <eric@badtux.org>. See 'mtx.c' for other contributors.
+.SH BUGS AND LIMITATIONS
+.P
+You may need to do a 'mt offline' on the tape drive to eject the tape
+before you can issue the 'mtx unload' command. The Exabyte EZ-17 and 220
+in particular will happily sit there snapping the robot arm's claws around
+thin air trying to grab a tape that's not there.
+.P
+For some Linux distributions, you may need to re-compile the kernel to
+scan SCSI LUN's in order to detect the media changer. Check /proc/scsi/scsi
+to see what's going on.
+.P
+If you try to unload a tape to its 'source' slot, and said slot is
+full, it will instead put the tape into the first empty
+slot. Unfortunately the list of empty slots is not updated between
+commands on the command line, so if you try to unload another drive to
+a full 'source' slot during the same invocation of 'mtx', it will try
+to unload to the same (no longer empty) slot and will urp with a SCSI
+error.
+.P
+
+This program reads the Mode Sense Element Address Assignment Page
+(SCSI) and requests data on all available elements. For larger
+libraries (more than a couple dozen elements)
+this sets a big Allocation_Size in the SCSI command block for the
+REQUEST_ELEMENT_STATUS command in order to be able to read the entire
+result of a big tape library. Some operating systems may not be able
+to handle this. Versions of Linux earlier than 2.2.6, in particular,
+may fail this request due to inability to find contiguous pages of
+memory for the SCSI transfer (later versions of Linux 'sg' device do
+scatter-gather so that this should no longer be a problem).
+.P
+The
+.B eepos
+command remains in effect for all further commands on a command
+line. Thus you might want to follow
+.B eepos 1 transfer 32 32
+with
+.B eepos 0
+as
+the next command (which clears the
+.B eepos
+bits).
+.P
+Need a better name for 'eepos' command! ('eepos' is the name of the bit
+field in the actual low-level SCSI command, and has nothing to do with what
+it does).
+.P
+
+This program has only been tested on Linux with a limited number of
+tape loaders (a dual-drive Exabyte 220 tape library, with bar-code
+reader and 21 slots, an Exabyte EZ-17 7-slot autoloader, and a Seagate
+DDS-4 autochanger with 6 slots). It may not work on other operating systems
+with larger libraries,
+due to the big SCSI request size.
+Please see the projecdt page http://sourceforge.net/projects/mtx for information
+on reporting bugs, requesting features and the mailing list for peer support.
+.SH HINTS
+Under Linux,
+.B cat /proc/scsi/scsi
+will tell you what SCSI devices you have.
+You can then refer to them as
+.B /dev/sga,
+.B /dev/sgb,
+etc. by the order they
+are reported.
+.P
+Under FreeBSD,
+.B camcontrol devlist
+will tell you what SCSI devices you
+have, along with which
+.B pass
+device controls them.
+.P
+Under Solaris, set up your 'sgen' driver so that it'll look for
+tape changers (see /kernel/drv/sgen.conf and the sgen man page), type
+.B touch /reconfigure
+then reboot. You can find your changer in /devices by typing
+.B /usr/sbin/devfsadm -C
+to clean out no-longer-extant entries in your /devices directory, then
+.B find /devices -name \e\(**changer -print
+to find the device name. Set the symbolic link
+.B /dev/changer
+to point
+to that device name (if it is not doing so already).
+.P
+With BRU, set your mount and unmount commands as described on the BRU
+web site at http://www.bru.com to move to the next tape when backing up
+or restoring. With GNU
+.B tar,
+see
+.B mtx.doc
+for an example of how to use
+.B tar
+and
+.B mtx
+to make multi-tape backups.
+
+.SH AVAILABILITY
+This version of
+.B mtx
+is currently being maintained by Robert Nelson <robertnelson@users.sourceforge.net> .
+The 'mtx' home page is http://mtx.sourceforge.net and the actual code is currently available
+there and via SVN from http://sourceforge.net/projects/mtx.
+.SH SEE ALSO
+.BR mt (1), loaderinfo (1), tapeinfo (1), scsitape (1), scsieject (1)
diff --git a/mtx.c b/mtx.c
new file mode 100644
index 0000000..fab11bb
--- /dev/null
+++ b/mtx.c
@@ -0,0 +1,1075 @@
+/*
+
+ MTX -- SCSI Tape Attached Medium Changer Control Program
+ $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+ $Revision: 193 $
+
+ Copyright 1997-1998 by Leonard N. Zubkoff.
+ Copyright 1999-2006 by Eric Lee Green.
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+ The author respectfully requests that any modifications to this software be
+ sent directly to him for evaluation and testing.
+
+ Thanks to Philip A. Prindeville <philipp@enteka.com> of Enteka Enterprise
+ Technology Service for porting MTX to Solaris/SPARC.
+
+ Thanks to Carsten Koch <Carsten.Koch@icem.de> for porting MTX to SGI IRIX.
+
+ Thanks to TECSys Development, Inc. for porting MTX to Digital Unix and
+ OpenVMS.
+
+ Near complete re-write Feb 2000 Eric Lee Green <eric@badtux.org> to add support for
+ multi-drive tape changers, extract out library stuff into mtxl.c,
+ and otherwise bring things up to date for dealing with LARGE tape jukeboxes
+ and other such enterprise-class storage subsystems.
+*/
+
+char *argv0;
+
+#include "mtx.h" /* various defines for bit order etc. */
+#include "mtxl.h"
+
+/* A table for printing out the peripheral device type as ASCII. */
+static char *PeripheralDeviceType[32] =
+{
+ "Disk Drive", /* 0 */
+ "Tape Drive", /* 1 */
+ "Printer", /* 2 */
+ "Processor", /* 3 */
+ "Write-once", /* 4 */
+ "CD-ROM", /* 5 */
+ "Scanner", /* 6 */
+ "Optical", /* 7 */
+ "Medium Changer", /* 8 */
+ "Communications", /* 9 */
+ "ASC IT8", /* a */
+ "ASC IT8", /* b */
+ "RAID Array", /* c */
+ "Enclosure Services", /* d */
+ "RBC Simplified Disk", /* e */
+ "OCR/W", /* f */
+ "Bridging Expander", /* 0x10 */
+ "Reserved", /* 0x11 */
+ "Reserved", /* 0x12 */
+ "Reserved", /* 0x13 */
+ "Reserved", /* 0x14 */
+ "Reserved", /* 0x15 */
+ "Reserved", /* 0x16 */
+ "Reserved", /* 0x17 */
+ "Reserved", /* 0x18 */
+ "Reserved", /* 0x19 */
+ "Reserved", /* 0x1a */
+ "Reserved", /* 0x1b */
+ "Reserved", /* 0x1c */
+ "Reserved", /* 0x1d */
+ "Reserved", /* 0x1e */
+ "Unknown" /* 0x1f */
+};
+
+static int argc;
+static char **argv;
+
+static char *device=NULL; /* the device name passed as argument */
+
+/* Unfortunately this must be true for SGI, because SGI does not
+ use an int :-(.
+*/
+
+static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) -1;
+static int device_opened = 0; /* okay, replace check here. */
+
+static int arg1 = -1; /* first arg to command */
+static int arg2 = -1; /* second arg to command */
+static int arg3 = -1; /* third arg to command, if exchange. */
+
+static SCSI_Flags_T SCSI_Flags = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static Inquiry_T *inquiry_info; /* needed by MoveMedium etc... */
+static ElementStatus_T *ElementStatus = NULL;
+void Position(int dest);
+
+/* pre-defined commands: */
+static void ReportInquiry(void);
+static void Status(void);
+static void Load(void);
+static void Unload(void);
+static void First(void);
+static void Last(void);
+static void Next(void);
+static void Previous(void);
+static void InvertCommand(void);
+static void Transfer(void);
+static void Eepos(void);
+static void NoAttach(void);
+static void Version(void);
+static void do_Inventory(void);
+static void do_Unload(void);
+static void do_Erase(void);
+static void NoBarCode(void);
+static void do_Position(void);
+static void Invert2(void);
+static void Exchange(void);
+static void AltReadElementStatus(void);
+
+struct command_table_struct
+{
+ int num_args;
+ char *name;
+ void (*command)(void);
+ int need_device;
+ int need_status;
+}
+command_table[] =
+{
+ { 0, "inquiry",ReportInquiry, 1,0},
+ { 0, "status", Status, 1,1 },
+ { 0, "invert", InvertCommand, 0,0},
+ { 0, "noattach",NoAttach,0,0},
+ { 1, "eepos", Eepos, 0,0},
+ { 2, "load", Load, 1,1 },
+ { 2, "unload", Unload, 1,1 },
+ { 2, "transfer", Transfer, 1,1 },
+ { 1, "first", First, 1,1 },
+ { 1, "last", Last, 1,1 },
+ { 1, "previous", Previous, 1,1 },
+ { 1, "next", Next, 1,1 },
+ { 0, "--version", Version, 0,0 },
+ { 0, "inventory", do_Inventory, 1,0},
+ { 0, "eject", do_Unload, 1, 0},
+ { 0, "erase", do_Erase, 1, 0},
+ { 0, "nobarcode", NoBarCode, 0,0},
+ { 1, "position", do_Position, 1, 1},
+ { 0, "invert2", Invert2, 0, 0},
+ { 3, "exchange", Exchange, 1, 1 },
+ { 0, "altres", AltReadElementStatus, 0,0},
+ { 0, NULL, NULL }
+};
+
+static void Usage()
+{
+ fprintf(stderr, "Usage:\n\
+ mtx --version\n\
+ mtx [ -f <loader-dev> ] noattach <more commands>\n\
+ mtx [ -f <loader-dev> ] inquiry | inventory \n\
+ mtx [ -f <loader-dev> ] [altres] [nobarcode] status\n\
+ mtx [ -f <loader-dev> ] [altres] first [<drive#>]\n\
+ mtx [ -f <loader-dev> ] [altres] last [<drive#>]\n\
+ mtx [ -f <loader-dev> ] [altres] previous [<drive#>]\n\
+ mtx [ -f <loader-dev> ] [altres] next [<drive#>]\n\
+ mtx [ -f <loader-dev> ] [altres] [invert] load <storage-element-number> [<drive#>]\n\
+ mtx [ -f <loader-dev> ] [altres] [invert] unload [<storage-element-number>][<drive#>]\n\
+ mtx [ -f <loader-dev> ] [altres] [eepos eepos-number] transfer <storage-element-number> <storage-element-number>\n\
+ mtx [ -f <loader-dev> ] [altres] [eepos eepos-number][invert][invert2] exchange <storage-element-number> <storage-element-number>\n\
+ mtx [ -f <loader-dev> ] [altres] position <storage-element-number>\n\
+ mtx [ -f <loader-dev> ] eject\n");
+
+#ifndef VMS
+ exit(1);
+#else
+ sys$exit(VMS_ExitCode);
+#endif
+}
+
+
+static void Version(void)
+{
+ fprintf(stderr, "mtx version %s\n\n", VERSION);
+ Usage();
+}
+
+
+static void NoAttach(void)
+{
+ SCSI_Flags.no_attached = 1;
+}
+
+
+static void InvertCommand(void)
+{
+ SCSI_Flags.invert = 1; /* invert_bit=1;*/
+}
+
+
+static void Invert2(void)
+{
+ SCSI_Flags.invert2 = 1; /* invert2_bit=1;*/
+}
+
+
+static void NoBarCode(void)
+{
+ SCSI_Flags.no_barcodes = 1; /* don't request barcodes */
+}
+
+
+static void do_Position(void)
+{
+ int driveno,src;
+
+ if (arg1 >= 0 && arg1 <= ElementStatus->StorageElementCount)
+ {
+ driveno = arg1 - 1;
+ }
+ else
+ {
+ driveno = 0;
+ }
+
+ src = ElementStatus->StorageElementAddress[driveno];
+ Position(src);
+}
+
+
+static void AltReadElementStatus(void)
+{
+ /* use alternative way to read element status from device - used to support XL1B2 */
+ SCSI_Flags.querytype = MTX_ELEMENTSTATUS_READALL;
+}
+
+
+/* First and Last are easy. Next is the bitch. */
+static void First(void)
+{
+ int driveno;
+ /* okay, first see if we have a drive#: */
+ if (arg1 >= 0 && arg1 < ElementStatus->DataTransferElementCount)
+ {
+ driveno = arg1;
+ }
+ else
+ {
+ driveno = 0;
+ }
+
+ /* now see if there's anything *IN* that drive: */
+ if (ElementStatus->DataTransferElementFull[driveno])
+ {
+ /* if so, then unload it... */
+ arg1 = ElementStatus->DataTransferElementSourceStorageElementNumber[driveno] + 1;
+ if (arg1 == 1)
+ {
+ printf("loading...done.\n"); /* it already has tape #1 in it! */
+ return;
+ }
+ arg2 = driveno;
+ Unload();
+ }
+
+ /* and now to actually do the Load(): */
+ arg1 = 1; /* first! */
+ arg2 = driveno;
+ Load(); /* and voila! */
+}
+
+static void Last(void)
+{
+ int driveno;
+
+ /* okay, first see if we have a drive#: */
+ if (arg1 >= 0 && arg1 < ElementStatus->DataTransferElementCount)
+ {
+ driveno = arg1;
+ }
+ else
+ {
+ driveno = 0;
+ }
+
+ /* now see if there's anything *IN* that drive: */
+ if (ElementStatus->DataTransferElementFull[driveno])
+ {
+ /* if so, then unload it... */
+ arg1 = ElementStatus->DataTransferElementSourceStorageElementNumber[driveno] + 1;
+ if (arg1 >= (ElementStatus->StorageElementCount - ElementStatus->ImportExportCount))
+ {
+ printf("loading...done.\n"); /* it already has last tape in it! */
+ return;
+ }
+ arg2 = driveno;
+ Unload();
+ }
+
+ arg1 = ElementStatus->StorageElementCount - ElementStatus->ImportExportCount; /* the last slot... */
+ arg2 = driveno;
+ Load();
+}
+
+
+static void Previous(void)
+{
+ int driveno;
+ int current = ElementStatus->StorageElementCount - ElementStatus->ImportExportCount + 1;
+
+ /* okay, first see if we have a drive#: */
+ if (arg1 >= 0 && arg1 < ElementStatus->DataTransferElementCount)
+ {
+ driveno = arg1;
+ }
+ else
+ {
+ driveno = 0;
+ }
+
+ /* Now to see if there's anything in that drive! */
+ if (ElementStatus->DataTransferElementFull[driveno])
+ {
+ /* if so, unload it! */
+ current = ElementStatus->DataTransferElementSourceStorageElementNumber[driveno];
+ if (current == 0)
+ {
+ FatalError("No More Media\n"); /* Already at the 1st slot...*/
+ }
+ arg1 = current + 1; /* Args are 1 based */
+ arg2 = driveno;
+ Unload();
+ }
+
+ /* Position current to previous element */
+ for (current--; current >= 0; current--)
+ {
+ if (ElementStatus->StorageElementFull[current])
+ {
+ arg1 = current + 1;
+ arg2 = driveno;
+ Load();
+ return;
+ }
+ }
+
+ FatalError("No More Media\n"); /* First slot */
+}
+
+
+static void Next(void)
+{
+ int driveno;
+ int current = -1;
+
+ /* okay, first see if we have a drive#: */
+ if (arg1 >= 0 && arg1 < ElementStatus->DataTransferElementCount)
+ {
+ driveno = arg1;
+ }
+ else
+ {
+ driveno = 0;
+ }
+
+ /* Now to see if there's anything in that drive! */
+ if (ElementStatus->DataTransferElementFull[driveno])
+ {
+ /* if so, unload it! */
+ current = ElementStatus->DataTransferElementSourceStorageElementNumber[driveno];
+
+ arg1 = current + 1;
+ arg2 = driveno;
+ Unload();
+ }
+
+ for (current++;
+ current < (ElementStatus->StorageElementCount - ElementStatus->ImportExportCount);
+ current++)
+ {
+ if (ElementStatus->StorageElementFull[current])
+ {
+ arg1 = current + 1;
+ arg2 = driveno;
+ Load();
+ return;
+ }
+ }
+
+ FatalError("No More Media\n"); /* last slot */
+}
+
+static void do_Inventory(void)
+{
+ if (Inventory(MediumChangerFD) < 0)
+ {
+ fprintf(stderr,"mtx:inventory failed\n");
+ fflush(stderr);
+ exit(1); /* exit with an error status. */
+ }
+}
+
+/*
+ * For Linux, this allows us to do a short erase on a tape (sigh!).
+ * Note that you'll need to do a 'mt status' on the tape afterwards in
+ * order to get the tape driver in sync with the tape drive again. Also
+ * note that on other OS's, this might do other evil things to the tape
+ * driver. Note that to do an erase, you must first rewind using the OS's
+ * native tools!
+ */
+static void do_Erase(void)
+{
+ RequestSense_T *RequestSense;
+ RequestSense = Erase(MediumChangerFD);
+ if (RequestSense)
+ {
+ PrintRequestSense(RequestSense);
+ exit(1); /* exit with an error status. */
+ }
+}
+
+
+/* This should eject a tape or magazine, depending upon the device sent
+ * to.
+ */
+static void do_Unload(void)
+{
+ if (LoadUnload(MediumChangerFD, 0) < 0)
+ {
+ fprintf(stderr, "mtx:eject failed\n");
+ fflush(stderr);
+ }
+}
+
+static void ReportInquiry(void)
+{
+ RequestSense_T RequestSense;
+ Inquiry_T *Inquiry;
+ int i;
+
+ Inquiry = RequestInquiry(MediumChangerFD,&RequestSense);
+ if (Inquiry == NULL)
+ {
+ PrintRequestSense(&RequestSense);
+ FatalError("INQUIRY Command Failed\n");
+ }
+
+ printf("Product Type: %s\n", PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
+ printf("Vendor ID: '");
+ for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
+ {
+ printf("%c", Inquiry->VendorIdentification[i]);
+ }
+
+ printf("'\nProduct ID: '");
+ for (i = 0; i < sizeof(Inquiry->ProductIdentification); i++)
+ {
+ printf("%c", Inquiry->ProductIdentification[i]);
+ }
+
+ printf("'\nRevision: '");
+ for (i = 0; i < sizeof(Inquiry->ProductRevisionLevel); i++)
+ {
+ printf("%c", Inquiry->ProductRevisionLevel[i]);
+ }
+ printf("'\n");
+
+ if (Inquiry->MChngr)
+ {
+ /* check the attached-media-changer bit... */
+ printf("Attached Changer API: Yes\n");
+ }
+ else
+ {
+ printf("Attached Changer API: No\n");
+ }
+
+ free(Inquiry); /* well, we're about to exit, but ... */
+}
+
+static void Status(void)
+{
+ int StorageElementNumber;
+ int TransferElementNumber;
+
+ printf( " Storage Changer %s:%d Drives, %d Slots ( %d Import/Export )\n",
+ device,
+ ElementStatus->DataTransferElementCount,
+ ElementStatus->StorageElementCount,
+ ElementStatus->ImportExportCount);
+
+
+ for (TransferElementNumber = 0;
+ TransferElementNumber < ElementStatus->DataTransferElementCount;
+ TransferElementNumber++)
+ {
+
+ printf("Data Transfer Element %d:", TransferElementNumber);
+ if (ElementStatus->DataTransferElementFull[TransferElementNumber])
+ {
+ if (ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber] > -1)
+ {
+ printf("Full (Storage Element %d Loaded)",
+ ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber]+1);
+ }
+ else
+ {
+ printf("Full (Unknown Storage Element Loaded)");
+ }
+
+ if (ElementStatus->DataTransferPrimaryVolumeTag[TransferElementNumber][0])
+ {
+ printf(":VolumeTag = %s", ElementStatus->DataTransferPrimaryVolumeTag[TransferElementNumber]);
+ }
+
+ if (ElementStatus->DataTransferAlternateVolumeTag[TransferElementNumber][0])
+ {
+ printf(":AlternateVolumeTag = %s", ElementStatus->DataTransferAlternateVolumeTag[TransferElementNumber]);
+ }
+ putchar('\n');
+ }
+ else
+ {
+ printf("Empty\n");
+ }
+ }
+
+ for (StorageElementNumber = 0;
+ StorageElementNumber < ElementStatus->StorageElementCount;
+ StorageElementNumber++)
+ {
+ printf( " Storage Element %d%s:%s", StorageElementNumber + 1,
+ (ElementStatus->StorageElementIsImportExport[StorageElementNumber]) ? " IMPORT/EXPORT" : "",
+ (ElementStatus->StorageElementFull[StorageElementNumber] ? "Full " : "Empty"));
+
+ if (ElementStatus->PrimaryVolumeTag[StorageElementNumber][0])
+ {
+ printf(":VolumeTag=%s", ElementStatus->PrimaryVolumeTag[StorageElementNumber]);
+ }
+
+ if (ElementStatus->AlternateVolumeTag[StorageElementNumber][0])
+ {
+ printf(":AlternateVolumeTag=%s", ElementStatus->AlternateVolumeTag[StorageElementNumber]);
+ }
+ putchar('\n');
+ }
+
+#ifdef VMS
+ VMS_DefineStatusSymbols();
+#endif
+}
+
+void Position(int dest)
+{
+ if (PositionElement(MediumChangerFD,dest,ElementStatus) != NULL)
+ {
+ FatalError("Could not position transport\n");
+ }
+}
+
+void Move(int src, int dest) {
+ RequestSense_T *result; /* from MoveMedium */
+
+ result = MoveMedium(MediumChangerFD, src, dest, ElementStatus, inquiry_info, &SCSI_Flags);
+ if (result)
+ {
+ /* we have an error! */
+
+ if (result->AdditionalSenseCode == 0x30 &&
+ result->AdditionalSenseCodeQualifier == 0x03)
+ {
+ FatalError("Cleaning Cartridge Installed and Ejected\n");
+ }
+
+ if (result->AdditionalSenseCode == 0x3A &&
+ result->AdditionalSenseCodeQualifier == 0x00)
+ {
+ FatalError("Drive needs offline before move\n");
+ }
+
+ if (result->AdditionalSenseCode == 0x3B &&
+ result->AdditionalSenseCodeQualifier == 0x0D)
+ {
+ FatalError("Destination Element Address %d is Already Full\n", dest);
+ }
+
+ if (result->AdditionalSenseCode == 0x3B &&
+ result->AdditionalSenseCodeQualifier == 0x0E)
+ {
+ FatalError("Source Element Address %d is Empty\n", src);
+ }
+
+ PrintRequestSense(result);
+ FatalError("MOVE MEDIUM from Element Address %d to %d Failed\n", src, dest);
+ }
+}
+
+
+/* okay, now for the Load, Unload, etc. logic: */
+
+static void Load(void)
+{
+ int src, dest;
+
+ /* okay, check src, dest: arg1=src, arg2=dest */
+ if (arg1 < 1)
+ {
+ FatalError("No source specified\n");
+ }
+
+ if (arg2 < 0)
+ {
+ arg2 = 0; /* default to 1st drive :-( */
+ }
+
+ arg1--; /* we use zero-based arrays */
+
+ if (!device_opened)
+ {
+ FatalError("No Media Changer Device Specified\n");
+ }
+
+ if (arg1 < 0 || arg1 >= ElementStatus->StorageElementCount)
+ {
+ FatalError( "Invalid <storage-element-number> argument '%d' to 'load' command\n",
+ arg1 + 1);
+ }
+
+ if (arg2 < 0 || arg2 >= ElementStatus->DataTransferElementCount)
+ {
+ FatalError( "illegal <drive-number> argument '%d' to 'load' command\n",
+ arg2);
+ }
+
+ if (ElementStatus->DataTransferElementFull[arg2])
+ {
+ FatalError( "Drive %d Full (Storage Element %d loaded)\n", arg2,
+ ElementStatus->DataTransferElementSourceStorageElementNumber[arg2] + 1);
+ }
+
+ /* Now look up the actual devices: */
+ src = ElementStatus->StorageElementAddress[arg1];
+ dest = ElementStatus->DataTransferElementAddress[arg2];
+
+ fprintf(stdout, "Loading media from Storage Element %d into drive %d...", arg1 + 1, arg2);
+ fflush(stdout);
+
+ Move(src,dest); /* load it into the particular slot, if possible! */
+
+ fprintf(stdout,"done\n");
+ fflush(stdout);
+
+ /* now set the status for further commands on this line... */
+ ElementStatus->StorageElementFull[arg1] = false;
+ ElementStatus->DataTransferElementFull[arg2] = true;
+}
+
+static void Transfer(void)
+{
+ int src,dest;
+
+ if (arg1 < 1)
+ {
+ FatalError("No source specified\n");
+ }
+
+ if (arg2 < 1)
+ {
+ FatalError("No destination specified\n");
+ }
+
+ if (arg1 > ElementStatus->StorageElementCount)
+ {
+ FatalError("Invalid source\n");
+ }
+
+ if (arg2 > ElementStatus->StorageElementCount)
+ {
+ FatalError("Invalid destination\n");
+ }
+
+ src = ElementStatus->StorageElementAddress[arg1 - 1];
+ dest = ElementStatus->StorageElementAddress[arg2 - 1];
+ Move(src,dest);
+}
+
+/****************************************************************
+ * Exchange() -- exchange medium in two slots, if so
+ * supported by the jukebox in question.
+ ***************************************************************/
+
+static void Exchange(void)
+{
+ RequestSense_T *result; /* from ExchangeMedium */
+ int src,dest,dest2;
+
+ if (arg1 < 1)
+ {
+ FatalError("No source specified\n");
+ }
+
+ if (arg2 < 1)
+ {
+ FatalError("No destination specified\n");
+ }
+
+ if (arg1 > ElementStatus->StorageElementCount)
+ {
+ FatalError("Invalid source\n");
+ }
+
+ if (arg2 > ElementStatus->StorageElementCount)
+ {
+ FatalError("Invalid destination\n");
+ }
+
+ if (arg3 == -1)
+ {
+ arg3 = arg1; /* true exchange of medium */
+ }
+
+ src = ElementStatus->StorageElementAddress[arg1 - 1];
+ dest = ElementStatus->StorageElementAddress[arg2 - 1];
+ dest2 = ElementStatus->StorageElementAddress[arg3 - 1];
+
+ result = ExchangeMedium(MediumChangerFD, src, dest, dest2, ElementStatus, &SCSI_Flags);
+ if (result)
+ {
+ /* we have an error! */
+ if (result->AdditionalSenseCode == 0x30 &&
+ result->AdditionalSenseCodeQualifier == 0x03)
+ {
+ FatalError("Cleaning Cartridge Installed and Ejected\n");
+ }
+
+ if (result->AdditionalSenseCode == 0x3A &&
+ result->AdditionalSenseCodeQualifier == 0x00)
+ {
+ FatalError("Drive needs offline before move\n");
+ }
+
+ if (result->AdditionalSenseCode == 0x3B &&
+ result->AdditionalSenseCodeQualifier == 0x0D)
+ {
+ FatalError("Destination Element Address %d is Already Full\n", dest);
+ }
+
+ if (result->AdditionalSenseCode == 0x3B &&
+ result->AdditionalSenseCodeQualifier == 0x0E)
+ {
+ FatalError("Source Element Address %d is Empty\n", src);
+ }
+
+ PrintRequestSense(result);
+
+ FatalError("EXCHANGE MEDIUM from Element Address %d to %d Failed\n", src, dest);
+ }
+}
+
+static void Eepos(void)
+{
+ if (arg1 < 0 || arg1 > 3)
+ {
+ FatalError("eepos equires argument between 0 and 3.\n");
+ }
+
+ SCSI_Flags.eepos = (unsigned char)arg1;
+}
+
+
+static void Unload(void)
+{
+ int src, dest; /* the actual SCSI-level numbers */
+
+ if (arg2 < 0)
+ {
+ arg2 = 0; /* default to 1st drive :-( */
+ }
+
+ /* check for filehandle: */
+ if (!device_opened)
+ {
+ FatalError("No Media Changer Device Specified\n");
+ }
+
+ /* okay, we should be there: */
+ if (arg1 < 0)
+ {
+ arg1 = ElementStatus->DataTransferElementSourceStorageElementNumber[arg2];
+ if (arg1 < 0)
+ {
+ FatalError("No Source for tape in drive %d!\n",arg2);
+ }
+ }
+ else
+ {
+ arg1--; /* go from bogus 1-base to zero-base */
+ }
+
+ if (arg1 >= ElementStatus->StorageElementCount)
+ {
+ FatalError( "illegal <storage-element-number> argument '%d' to 'unload' command\n",
+ arg1 + 1);
+ }
+
+ if (arg2 < 0 || arg2 >= ElementStatus->DataTransferElementCount)
+ {
+ FatalError( "illegal <drive-number> argument '%d' to 'unload' command\n",
+ arg2);
+ }
+
+ if (!ElementStatus->DataTransferElementFull[arg2])
+ {
+ FatalError("Data Transfer Element %d is Empty\n", arg2);
+ }
+
+ /* Now see if something already lives where we wanna go... */
+ if (ElementStatus->StorageElementFull[arg1])
+ {
+ FatalError("Storage Element %d is Already Full\n", arg1 + 1);
+ }
+
+ /* okay, now to get src, dest: */
+ src=ElementStatus->DataTransferElementAddress[arg2];
+ if (arg1 >= 0)
+ {
+ dest = ElementStatus->StorageElementAddress[arg1];
+ }
+ else
+ {
+ dest = ElementStatus->DataTransferElementSourceStorageElementNumber[arg2];
+ }
+
+ if (dest < 0)
+ {
+ /* we STILL don't know... */
+ FatalError("Do not know which slot to unload tape into!\n");
+ }
+
+ fprintf(stdout, "Unloading drive %d into Storage Element %d...", arg2, arg1 + 1);
+ fflush(stdout); /* make it real-time :-( */
+
+ Move(src,dest);
+
+ fprintf(stdout, "done\n");
+ fflush(stdout);
+
+ ElementStatus->StorageElementFull[arg1] = true;
+ ElementStatus->DataTransferElementFull[arg2] = false;
+}
+
+/*****************************************************************
+ ** ARGUMENT PARSING SUBROUTINES: Parse arguments, dispatch.
+ *****************************************************************/
+
+/* ***
+ * int get_arg(idx):
+ *
+ * If we have an actual argument at the index position indicated (i.e. we
+ * have not gone off the edge of the world), we return
+ * its number. If we don't, or it's not a numeric argument,
+ * we return -1. Note that 'get_arg' is kind of misleading, we only accept
+ * numeric arguments, not any other kind.
+ */
+int get_arg(int idx)
+{
+ char *arg;
+ int retval = -1;
+
+ if (idx >= argc)
+ {
+ return -1; /* sorry! */
+ }
+
+ arg=argv[idx];
+ if (*arg < '0' || *arg > '9')
+ {
+ return -1; /* sorry! */
+ }
+
+ retval = atoi(arg);
+ return retval;
+}
+
+/* open_device() -- set the 'fh' variable.... */
+void open_device(void)
+{
+ if (device_opened)
+ {
+ SCSI_CloseDevice("Unknown", MediumChangerFD); /* close it, sigh... new device now! */
+ }
+
+ MediumChangerFD = SCSI_OpenDevice(device);
+ device_opened = 1; /* SCSI_OpenDevice does an exit() if not. */
+}
+
+
+/* we see if we've got a file open. If not, we open one :-(. Then
+ * we execute the actual command. Or not :-(.
+ */
+void execute_command(struct command_table_struct *command)
+{
+ RequestSense_T RequestSense;
+
+ if (device == NULL && command->need_device)
+ {
+ /* try to get it from TAPE environment variable... */
+ device = getenv("CHANGER");
+ if (device == NULL)
+ {
+ device = getenv("TAPE");
+ if (device == NULL)
+ {
+ device = "/dev/changer"; /* Usage(); */
+ }
+ }
+ open_device();
+ }
+
+ if (!ElementStatus && command->need_status)
+ {
+ inquiry_info = RequestInquiry(MediumChangerFD,&RequestSense);
+ if (!inquiry_info)
+ {
+ PrintRequestSense(&RequestSense);
+ FatalError("INQUIRY command Failed\n");
+ }
+
+ ElementStatus = ReadElementStatus(MediumChangerFD, &RequestSense, inquiry_info, &SCSI_Flags);
+ if (!ElementStatus)
+ {
+ PrintRequestSense(&RequestSense);
+ FatalError("READ ELEMENT STATUS Command Failed\n");
+ }
+ }
+
+ /* okay, now to execute the command... */
+ command->command();
+}
+
+/* parse_args():
+ * Basically, we are parsing argv/argc. We can have multiple commands
+ * on a line now, such as "unload 3 0 load 4 0" to unload one tape and
+ * load in another tape into drive 0, and we execute these commands one
+ * at a time as we come to them. If we don't have a -f at the start, we
+ * barf. If we leave out a drive #, we default to drive 0 (the first drive
+ * in the cabinet).
+ */
+
+int parse_args(void)
+{
+ int i, cmd_tbl_idx;
+ struct command_table_struct *command;
+
+ i = 1;
+ while (i < argc)
+ {
+ if (strcmp(argv[i], "-f") == 0)
+ {
+ i++;
+ if (i >= argc)
+ {
+ Usage();
+ }
+
+ device = argv[i++];
+ open_device(); /* open the device and do a status scan on it... */
+ }
+ else
+ {
+ cmd_tbl_idx = 0; /* default to the first command... */
+ command = &command_table[cmd_tbl_idx];
+
+ while (command->name != NULL)
+ {
+ if (strcmp(command->name, argv[i]) == 0)
+ {
+ /* we have a match... */
+ break;
+ }
+ /* otherwise we don't have a match... */
+ cmd_tbl_idx++;
+ command = &command_table[cmd_tbl_idx];
+ }
+
+ /* if it's not a command, exit.... */
+ if (!command->name)
+ {
+ Usage();
+ }
+
+ i++; /* go to the next argument, if possible... */
+ /* see if we need to gather arguments, though! */
+ if (command->num_args == 0)
+ {
+ execute_command(command); /* execute_command handles 'stuff' */
+ }
+ else
+ {
+ arg1 = get_arg(i); /* checks i... */
+
+ if (arg1 != -1)
+ {
+ i++; /* next! */
+ }
+
+ if (command->num_args>=2 && arg1 != -1)
+ {
+ arg2 = get_arg(i);
+ if (arg2 != -1)
+ {
+ i++;
+ }
+
+ if (command->num_args==3 && arg2 != -1)
+ {
+ arg3 = get_arg(i);
+ if (arg3 != -1)
+ {
+ i++;
+ }
+ }
+ }
+ execute_command(command);
+ }
+ arg1 = -1;
+ arg2 = -1;
+ arg3 = -1;
+ }
+ }
+
+ /* should never get here. */
+ return 0;
+}
+
+
+
+int main(int ArgCount, char *ArgVector[])
+{
+#ifdef VMS
+ RequestSense_T RequestSense;
+#endif
+
+ /* save these where we can get at them elsewhere... */
+ argc = ArgCount;
+ argv = ArgVector;
+
+ argv0 = argv[0];
+
+ parse_args(); /* also executes them as it sees them */
+
+#ifndef VMS
+ if (device)
+ {
+ SCSI_CloseDevice(device, MediumChangerFD);
+ }
+ return 0;
+#else
+ if (device)
+ {
+ ElementStatus = ReadElementStatus(MediumChangerFD,&RequestSense);
+ if (!ElementStatus)
+ {
+ PrintRequestSense(&RequestSense);
+ FatalError("READ ELEMENT STATUS Command Failed\n");
+ }
+ VMS_DefineStatusSymbols();
+ SCSI_CloseDevice(device, MediumChangerFD);
+ }
+
+ return SS$_NORMAL;
+#endif
+}
diff --git a/mtx.doc b/mtx.doc
new file mode 100644
index 0000000..ae814e8
--- /dev/null
+++ b/mtx.doc
@@ -0,0 +1,209 @@
+[WARNING: This document is of historical value only! Please read
+ 'mtxl.README.html' and 'man mtx' for current documentation! The only
+ thing useful here is examples of how to use the 'tar' command for
+ multi-tape backups.
+]
+
+ MTX - SCSI Tape Medium Changer Control Program
+
+ Version 1.1 for Linux, Solaris, IRIX, Digital Unix, and OpenVMS
+
+ 2 June 1998
+
+ Leonard N. Zubkoff
+ Dandelion Digital
+ lnz@dandelion.com
+
+ Copyright 1997-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+
+ INTRODUCTION
+
+The MTX program controls the robotic mechanism in DDS Autoloaders such as the
+Seagate 4586NP (Archive Python 28849-XXX). This program is also reported to
+work with the Seagate 4584NP, HP Surestore 12000, Quantum DLT 2500 XT, and AIWA
+DL-210. The 4586NP responds to both Logical Units 0 and 1 on the selected
+Target ID. Logical Unit 0 supports commands from the SCSI-3 Sequential Stream
+Device Command Set and must be accessed via the SCSI tape devices /dev/st<N>.
+Logical Unit 1 only supports commands from the SCSI-3 Medium Changer Command
+Set and must be accessed via the SCSI Generic devices /dev/sg<N>. In addition,
+Logical Unit 0 also acts as an Attached Medium Changer and supports the READ
+ELEMENT STATUS and MOVE MEDIUM commands. Since using the Primary Device
+(Logical Unit 0) via the Attached Medium Changer interface is sufficient for
+the commands provided by this program, Logical Unit 1 is not normally used.
+The AIWA DL-210, by contrast, does not support the Attached Medium Changer
+commands on Logical Unit 0 and so MTX must be used with Logical Unit 1 via the
+SCSI Generic devices /dev/sg<N>. Note that when using the SCSI Generic devices
+the Linux kernel option "max_scsi_luns=2" may be necessary.
+
+Medium Changers support four types of elements: Medium Transport Elements,
+Storage Elements, Import Export Elements, and Data Transfer Elements. For the
+limited case of DDS Autoloaders, only the Data Transfer Element and Storage
+Element types are really applicable. The Data Transfer Element is the primary
+device where a volume can be loaded to actually perform data transfers. A
+Storage Element is a place a volume can be when it is waiting to be used. For
+a DDS Autoloader, the Storage Elements are the slots in the cartridge where
+tapes may be placed, and the Data Transfer Element is the tape mechanism.
+
+Every Medium Changer Element has a unique integer Element Address that
+identifies it in the address space of all Elements known to the Medium Changer.
+For the 4586NP, the Data Transfer Element is Address 1 and the Storage Elements
+are Addresses 2-5 or 2-13. To simplify the human interface, this program does
+not use Element Addresses directly. Rather, it uses Storage Element Numbers
+which range from 1 to the number of Storage Elements available.
+
+The specific tape device to be operated on can either be supplied on the
+command line with the "-f <tape-device>" option, or via the TAPE environment
+variable.
+
+
+ BUILDING MTX
+
+The Makefile contains sections for Linux, Solaris/SPARC, SGI IRIX, and Digital
+UNIX. Comment/uncomment as necessary for the target environment. For OpenVMS,
+see the file "vms/000readme" for information on building MTX; a VMS release
+including pre-built binaries should be available from the WKU VMS FILESERV
+ARCHIVES, which are located at URLs http://www2.wku.edu/www/fileserv/ and
+ftp://ftp.wku.edu/vms/fileserv/.
+
+
+ COMMANDS
+
+MTX provides the following commands:
+
+
+mtx [ -f <tape-device> ] inquiry
+
+The "inquiry" command reports the Vendor ID, Product ID, and Revision from a
+SCSI INQUIRY command.
+
+kelewan:~# setenv TAPE /dev/st0
+
+kelewan:~# mtx inquiry
+Vendor ID: 'ARCHIVE ', Product ID: 'Python 28849-XXX', Revision: '4.CM'
+
+
+mtx [ -f <tape-device> ] status
+
+The "status" command reports on the status of the DDS Autloader. The report
+indicates the status of the Data Transfer Element and each of the Storage
+Elements. In the first example, no tape is currently loaded. In the second
+example, Storage Element Number 1 is loaded. The Storage Element loaded into
+the Data Transfer Element is usually reported by the DDS Autoloader, or it can
+be inferred by MTX if there is only a single empty Storage Element.
+
+kelewan:~# mtx status
+Data Transfer Element: Empty
+Storage Element 1: Full
+Storage Element 2: Full
+Storage Element 3: Full
+Storage Element 4: Full
+
+
+kelewan:~# mtx status
+Data Transfer Element: Full (Storage Element 1 Loaded)
+Storage Element 1: Empty
+Storage Element 2: Full
+Storage Element 3: Full
+Storage Element 4: Full
+
+
+mtx [ -f <tape-device> ] load <storage-element-number>
+
+The "load" command loads the volume in Storage Element <storage-element-number>
+into the Data Transfer Element. An error is signaled if the Data Transfer
+Element is already full.
+
+
+mtx [ -f <tape-device> ] unload [ <storage-element-number> ]
+
+The "unload" command unloads the volume in the Data Transfer Element into
+Storage Element <storage-element-number>. If <storage-element-number> is not
+provided, then the volume is unloaded back into the Storage Element from which
+it was originally loaded, if known. An error is signaled if the Storage
+Element is already full.
+
+
+mtx [ -f <tape-device> ] first
+
+The "first" command unloads any volume in the Data Transfer Element and then
+loads the volume in the lowest numbered non-empty Storage Element. If the
+correct Storage Element is already loaded, the unload/load is suppressed.
+
+
+mtx [ -f <tape-device> ] next
+
+The "next" command unloads any volume in the Data Transfer Element and then
+loads the volume in the lowest numbered non-empty Storage Element above the
+Storage Element that was just unloaded. If there is no next Storage Element,
+the unload is still performed and the Data Transfer Element will be left empty
+so that the volume is not accidentally overwritten.
+
+
+mtx [ -f <tape-device> ] last
+
+The "last" command unloads any volume in the Data Transfer Element and then
+loads the volume in the highest numbered non-empty Storage Element. If the
+correct Storage Element is already loaded, the unload/load is suppressed.
+
+
+mtx [ -f <tape-device> ] previous
+
+The "previous" command unloads any volume in the Data Transfer Element and then
+loads the volume in the highest numbered non-empty Storage Element below the
+Storage Element that was just unloaded. If there is no previous Storage
+Element, the unload is still performed and the Data Transfer Element will be
+left empty so that the volume is not accidentally overwritten.
+
+
+The interface is designed to allow both explicit control of precisely which
+Storage Element is loaded, as well as sequential access among only the Storage
+Elements that actually have volumes present. Thus for example, one way of
+using MTX would be to perform Monday's incremental backups on Storage Element
+1, Tuesday's on Storage Element 2, and so on. Multi-volume full backups are
+also conveniently supported, as in:
+
+setenv TAPE "/dev/st0"
+
+mtx status
+
+mtx first
+
+time tar --create --one-file-system --atime-preserve \
+ --listed-incremental `date +%y%m%d`.ss \
+ --multi-volume --new-volume-script "mtx next" \
+ --directory / <wherever>
+
+mtx first
+
+time tar --compare --multi-volume --new-volume-script "mtx next" \
+ --directory /
+
+mtx unload
+
+
+ LINUX KERNEL REQUIREMENTS
+
+Because the MOVE MEDIUM command may require 60 seconds or more to perform a
+volume load or unload request, a longer timeout must be provided. Linux
+kernels 2.0.30 and 2.1.28 should already contain a long enough timeout. For
+earlier kernels, edit the file "linux/drivers/scsi/scsi_ioctl.c" and add the
+following entries to the switch statement in ioctl_command:
+
+ case MOVE_MEDIUM:
+ case READ_ELEMENT_STATUS:
+ timeout = 5 * 60 * HZ; /* 5 minutes */
+ retries = 1;
+ break;
+
+For older kernels, you may also need to add the following definitions to
+"linux/include/scsi/scsi.h":
+
+#define MOVE_MEDIUM 0xa5
+#define READ_ELEMENT_STATUS 0xb8
+
+Note also that "/usr/include/scsi" should be a symbolic link to the directory
+"linux/include/scsi" from your kernel source.
+
+Finally, when using MTX you may see some console messages from the SCSI tape
+driver mentioning that there is no tape present. These can safely be ignored.
diff --git a/mtx.h b/mtx.h
new file mode 100644
index 0000000..93b6c07
--- /dev/null
+++ b/mtx.h
@@ -0,0 +1,607 @@
+/* MTX -- SCSI Tape Attached Medium Control Program
+
+ Copyright 1997-1998 Leonard N. Zubkoff <lnz@dandelion.com>
+
+ Changes 1999 Eric Lee Green to add support for multi-drive tape changers.
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+ $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+ $Revision: 193 $
+ See mtx.c for licensing information.
+
+*/
+
+#ifndef MTX_H /* protect against multiple includes... */
+#define MTX_H 1
+
+/* surround all the Unix-stuff w/ifndef VMS */
+#ifdef VMS
+#include "[.vms]defs.h"
+#else /* all the Unix stuff: */
+
+#ifdef _MSC_VER
+#include "msvc/config.h" /* all the autoconf stuff. */
+#else
+#include "config.h" /* all the autoconf stuff. */
+#endif
+
+/* all the general Unix includes: */
+
+#include <stdio.h>
+#include <errno.h>
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_STDARG_H
+# include <stdarg.h>
+#endif
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+/* Now greatly modified to use GNU Autoconf stuff: */
+/* If we use the 'sg' interface, like Linux, do this: */
+#if HAVE_SCSI_SG_H
+# include <scsi/scsi.h>
+# include <scsi/scsi_ioctl.h>
+# include <scsi/sg.h>
+typedef int DEVICE_TYPE; /* the sg interface uses this. */
+# define HAVE_GET_ID_LUN 1 /* signal that we have it... */
+#endif
+
+/* Windows Native programs built using MinGW */
+#if HAVE_DDK_NTDDSCSI_H
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <ddk/ntddscsi.h>
+# undef DEVICE_TYPE
+
+typedef int DEVICE_TYPE;
+#endif
+
+/* Windows Native programs built using Microsoft Visual C */
+#ifdef _MSC_VER
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <winioctl.h>
+# include <ntddscsi.h>
+# undef DEVICE_TYPE
+
+typedef int DEVICE_TYPE;
+#endif
+
+/* The 'cam' interface, like FreeBSD: */
+#if HAVE_CAMLIB_H
+# include <camlib.h> /* easy (?) access to the CAM user library. */
+# include <cam/cam_ccb.h>
+# include <cam/scsi/scsi_message.h> /* sigh sigh sigh! */
+typedef struct cam_device *DEVICE_TYPE;
+#endif
+
+
+/* the 'uscsi' interface, as used on Solaris: */
+#if HAVE_SYS_SCSI_IMPL_USCSI_H
+#include <sys/scsi/impl/uscsi.h>
+typedef int DEVICE_TYPE;
+#endif
+
+/* the scsi_ctl interface, as used on HP/UX: */
+#if HAVE_SYS_SCSI_CTL_H
+# include <sys/wsio.h>
+# include <sys/spinlock.h>
+# include <sys/scsi.h>
+# include <sys/scsi_ctl.h>
+ typedef int DEVICE_TYPE;
+# ifndef VERSION
+# define VERSION "1.2.12 hbb"
+# endif
+#endif
+
+/* the 'gsc' interface, as used on AIX: */
+#if HAVE_SYS_GSCDDS_H
+# include <sys/gscdds.h>
+ typedef int DEVICE_TYPE;
+#endif
+
+ /* the 'dslib' interface, as used on SGI. */
+#if HAVE_DSLIB_H
+#include <dslib.h>
+typedef dsreq_t *DEVICE_TYPE; /* 64-bit pointers/32bit int on later sgi? */
+#endif
+
+
+#if ((defined(__alpha) && defined(__osf__)) || \
+ defined(ultrix) || defined(__ultrix))
+#include "du/defs.h"
+#endif
+
+
+#endif /* VMS protect. */
+
+/* Do a test for LITTLE_ENDIAN_BITFIELDS. Use WORDS_BIGENDIAN as set
+ * by configure:
+ */
+
+#if WORDS_BIGENDIAN
+# define BIG_ENDIAN_BITFIELDS
+#else
+# define LITTLE_ENDIAN_BITFIELDS
+#endif
+
+/* Get rid of some Hocky Pux defines: */
+#ifdef S_NO_SENSE
+#undef S_NO_SENSE
+#endif
+#ifdef S_RECOVERED_ERROR
+#undef S_RECOVERED_ERROR
+#endif
+#ifdef S_NOT_READY
+#undef S_NOT_READY
+#endif
+#ifdef S_MEDIUM_ERROR
+#undef S_MEDIUM_ERROR
+#endif
+#ifdef S_HARDWARE_ERROR
+#undef S_HARDWARE_ERROR
+#endif
+#ifdef S_UNIT_ATTENTION
+#undef S_UNIT_ATTENTION
+#endif
+#ifdef S_BLANK_CHECK
+#undef S_BLANK_CHECK
+#endif
+#ifdef S_VOLUME_OVERFLOW
+#undef S_VOLUME_OVERFLOW
+#endif
+
+/* Note: These are only used for defaults for when we don't have
+ * the element assignment mode page to tell us real amount...
+ */
+#define MAX_STORAGE_ELEMENTS 64 /* for the BIG jukeboxes! */
+#define MAX_TRANSFER_ELEMENTS 2 /* we just do dual-drive for now :-} */
+#define MAX_TRANSPORT_ELEMENTS 1 /* we just do one arm for now... */
+
+#define MTX_ELEMENTSTATUS_ORIGINAL 0
+#define MTX_ELEMENTSTATUS_READALL 1
+
+/* These are flags used for the READ_ELEMENT_STATUS and MOVE_MEDIUM
+ * commands:
+ */
+typedef struct SCSI_Flags_Struct
+{
+ unsigned char eepos;
+ unsigned char invert;
+ unsigned char no_attached; /* ignore _attached bit */
+ unsigned char no_barcodes; /* don't try to get barcodes. */
+ int numbytes;
+ int elementtype;
+ int numelements;
+ int attached;
+ int has_barcodes;
+ int querytype; //MTX_ELEMENTSTATUS
+ unsigned char invert2; /* used for EXCHANGE command, sigh. */
+} SCSI_Flags_T;
+
+#ifdef _MSC_VER
+typedef unsigned char boolean;
+
+#define false 0
+#define true 1
+
+typedef unsigned char Direction_T;
+
+#define Input 0
+#define Output 1
+#else
+typedef enum { false, true } boolean;
+
+typedef enum { Input, Output } Direction_T;
+#endif
+
+
+typedef unsigned char CDB_T[12];
+
+
+typedef struct Inquiry
+{
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
+ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
+ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
+ boolean RMB:1; /* Byte 1 Bit 7 */
+ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
+ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
+ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
+ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
+ unsigned char :2; /* Byte 3 Bits 4-5 */
+ boolean TrmIOP:1; /* Byte 3 Bit 6 */
+ boolean AENC:1; /* Byte 3 Bit 7 */
+#else
+ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
+ unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
+ boolean RMB:1; /* Byte 1 Bit 7 */
+ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
+ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
+ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
+ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
+ boolean AENC:1; /* Byte 3 Bit 7 */
+ boolean TrmIOP:1; /* Byte 3 Bit 6 */
+ unsigned char :2; /* Byte 3 Bits 4-5 */
+ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
+#endif
+ unsigned char AdditionalLength; /* Byte 4 */
+ unsigned char :8; /* Byte 5 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ boolean ADDR16:1; /* Byte 6 bit 0 */
+ boolean Obs6_1:1; /* Byte 6 bit 1 */
+ boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
+ boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
+ boolean MultiP:1; /* Byte 6 bit 4 */
+ boolean VS:1; /* Byte 6 bit 5 */
+ boolean EncServ:1; /* Byte 6 bit 6 */
+ boolean BQue:1; /* Byte 6 bit 7 */
+#else
+ boolean BQue:1; /* Byte 6 bit 7 */
+ boolean EncServ:1; /* Byte 6 bit 6 */
+ boolean VS:1; /* Byte 6 bit 5 */
+ boolean MultiP:1; /* Byte 6 bit 4 */
+ boolean MChngr:1; /* Media Changer */ /* Byte 6 bit 3 */
+ boolean Obs6_2:1; /* obsolete */ /* Byte 6 bit 2 */
+ boolean Obs6_1:1; /* Byte 6 bit 1 */
+ boolean ADDR16:1; /* Byte 6 bit 0 */
+#endif
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ boolean SftRe:1; /* Byte 7 Bit 0 */
+ boolean CmdQue:1; /* Byte 7 Bit 1 */
+ boolean :1; /* Byte 7 Bit 2 */
+ boolean Linked:1; /* Byte 7 Bit 3 */
+ boolean Sync:1; /* Byte 7 Bit 4 */
+ boolean WBus16:1; /* Byte 7 Bit 5 */
+ boolean WBus32:1; /* Byte 7 Bit 6 */
+ boolean RelAdr:1; /* Byte 7 Bit 7 */
+#else
+ boolean RelAdr:1; /* Byte 7 Bit 7 */
+ boolean WBus32:1; /* Byte 7 Bit 6 */
+ boolean WBus16:1; /* Byte 7 Bit 5 */
+ boolean Sync:1; /* Byte 7 Bit 4 */
+ boolean Linked:1; /* Byte 7 Bit 3 */
+ boolean :1; /* Byte 7 Bit 2 */
+ boolean CmdQue:1; /* Byte 7 Bit 1 */
+ boolean SftRe:1; /* Byte 7 Bit 0 */
+#endif
+ unsigned char VendorIdentification[8]; /* Bytes 8-15 */
+ unsigned char ProductIdentification[16]; /* Bytes 16-31 */
+ unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */
+ unsigned char FullProductRevisionLevel[19]; /* bytes 36-54 */
+ unsigned char VendorFlags; /* byte 55 */
+}
+Inquiry_T;
+
+/* Hockey Pux may define these. If so, *UN*define them. */
+#ifdef ILI
+#undef ILI
+#endif
+
+#ifdef EOM
+#undef EOM
+#endif
+
+typedef struct RequestSense
+{
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
+ boolean Valid:1; /* Byte 0 Bit 7 */
+#else
+ boolean Valid:1; /* Byte 0 Bit 7 */
+ unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */
+#endif
+ unsigned char SegmentNumber; /* Byte 1 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
+ unsigned char :1; /* Byte 2 Bit 4 */
+ boolean ILI:1; /* Byte 2 Bit 5 */
+ boolean EOM:1; /* Byte 2 Bit 6 */
+ boolean Filemark:1; /* Byte 2 Bit 7 */
+#else
+ boolean Filemark:1; /* Byte 2 Bit 7 */
+ boolean EOM:1; /* Byte 2 Bit 6 */
+ boolean ILI:1; /* Byte 2 Bit 5 */
+ unsigned char :1; /* Byte 2 Bit 4 */
+ unsigned char SenseKey:4; /* Byte 2 Bits 0-3 */
+#endif
+ unsigned char Information[4]; /* Bytes 3-6 */
+ unsigned char AdditionalSenseLength; /* Byte 7 */
+ unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */
+ unsigned char AdditionalSenseCode; /* Byte 12 */
+ unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */
+ unsigned char :8; /* Byte 14 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char BitPointer:3; /* Byte 15 */
+ boolean BPV:1;
+ unsigned char :2;
+ boolean CommandData :1;
+ boolean SKSV:1;
+#else
+ boolean SKSV:1;
+ boolean CommandData :1;
+ unsigned char :2;
+ boolean BPV:1;
+ unsigned char BitPointer:3; /* Byte 15 */
+#endif
+ unsigned char FieldData[2]; /* Byte 16,17 */
+}
+RequestSense_T;
+
+/* Okay, now for the element status mode sense page (0x1d): */
+
+typedef struct ElementModeSensePageHeader {
+ unsigned char PageCode; /* byte 0 */
+ unsigned char ParameterLengthList; /* byte 1; */
+ unsigned char MediumTransportStartHi; /* byte 2,3 */
+ unsigned char MediumTransportStartLo;
+ unsigned char NumMediumTransportHi; /* byte 4,5 */
+ unsigned char NumMediumTransportLo; /* byte 4,5 */
+ unsigned char StorageStartHi; /* byte 6,7 */
+ unsigned char StorageStartLo; /* byte 6,7 */
+ unsigned char NumStorageHi; /* byte 8,9 */
+ unsigned char NumStorageLo; /* byte 8,9 */
+ unsigned char ImportExportStartHi; /* byte 10,11 */
+ unsigned char ImportExportStartLo; /* byte 10,11 */
+ unsigned char NumImportExportHi; /* byte 12,13 */
+ unsigned char NumImportExportLo; /* byte 12,13 */
+ unsigned char DataTransferStartHi; /* byte 14,15 */
+ unsigned char DataTransferStartLo; /* byte 14,15 */
+ unsigned char NumDataTransferHi; /* byte 16,17 */
+ unsigned char NumDataTransferLo; /* byte 16,17 */
+ unsigned char Reserved1; /* byte 18, 19 */
+ unsigned char Reserved2; /* byte 18, 19 */
+} ElementModeSensePage_T;
+
+typedef struct ElementModeSenseHeader {
+ int MaxReadElementStatusData; /* 'nuff for all of below. */
+ int NumElements; /* total # of elements. */
+ int MediumTransportStart;
+ int NumMediumTransport;
+ int StorageStart;
+ int NumStorage;
+ int ImportExportStart;
+ int NumImportExport;
+ int DataTransferStart;
+ int NumDataTransfer;
+} ElementModeSense_T;
+
+
+#ifdef _MSC_VER
+typedef char ElementTypeCode_T;
+
+#define AllElementTypes 0
+#define MediumTransportElement 1
+#define StorageElement 2
+#define ImportExportElement 3
+#define DataTransferElement 4
+#else
+typedef enum ElementTypeCode
+{
+ AllElementTypes = 0,
+ MediumTransportElement = 1,
+ StorageElement = 2,
+ ImportExportElement = 3,
+ DataTransferElement = 4
+}
+ElementTypeCode_T;
+#endif
+
+
+typedef struct ElementStatusDataHeader
+{
+ unsigned char FirstElementAddressReported[2]; /* Bytes 0-1 */
+ unsigned char NumberOfElementsAvailable[2]; /* Bytes 2-3 */
+ unsigned char :8; /* Byte 4 */
+ unsigned char ByteCountOfReportAvailable[3]; /* Bytes 5-7 */
+}
+ElementStatusDataHeader_T;
+
+
+typedef struct ElementStatusPage
+{
+ ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char :6; /* Byte 1 Bits 0-5 */
+ boolean AVolTag:1; /* Byte 1 Bit 6 */
+ boolean PVolTag:1; /* Byte 1 Bit 7 */
+#else
+ boolean PVolTag:1; /* Byte 1 Bit 7 */
+ boolean AVolTag:1; /* Byte 1 Bit 6 */
+ unsigned char :6; /* Byte 1 Bits 0-5 */
+#endif
+ unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
+ unsigned char :8; /* Byte 4 */
+ unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
+}
+ElementStatusPage_T;
+
+typedef struct Element2StatusPage
+{
+ ElementTypeCode_T ElementTypeCode:8; /* Byte 0 */
+ unsigned char VolBits ; /* byte 1 */
+#define E2_PVOLTAG 0x80
+#define E2_AVOLTAG 0x40
+ unsigned char ElementDescriptorLength[2]; /* Bytes 2-3 */
+ unsigned char :8; /* Byte 4 */
+ unsigned char ByteCountOfDescriptorDataAvailable[3]; /* Bytes 5-7 */
+}
+Element2StatusPage_T;
+
+
+
+typedef struct TransportElementDescriptorShort
+{
+ unsigned char ElementAddress[2]; /* Bytes 0-1 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ boolean Full:1; /* Byte 2 Bit 0 */
+ unsigned char :1; /* Byte 2 Bit 1 */
+ boolean Except:1; /* Byte 2 Bit 2 */
+ unsigned char :5; /* Byte 2 Bits 3-7 */
+#else
+ unsigned char :5; /* Byte 2 Bits 3-7 */
+ boolean Except:1; /* Byte 2 Bit 2 */
+ unsigned char :1; /* Byte 2 Bit 1 */
+ boolean Full:1; /* Byte 2 Bit 0 */
+#endif
+ unsigned char :8; /* Byte 3 */
+ unsigned char AdditionalSenseCode; /* Byte 4 */
+ unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
+ unsigned char :8; /* Byte 6 */
+ unsigned char :8; /* Byte 7 */
+ unsigned char :8; /* Byte 8 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char :6; /* Byte 9 Bits 0-5 */
+ boolean SValid:1; /* Byte 9 Bit 6 */
+ boolean Invert:1; /* Byte 9 Bit 7 */
+#else
+ boolean Invert:1; /* Byte 9 Bit 7 */
+ boolean SValid:1; /* Byte 9 Bit 6 */
+ unsigned char :6; /* Byte 9 Bits 0-5 */
+#endif
+ unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
+#ifdef HAS_LONG_DESCRIPTORS
+ unsigned char Reserved[4]; /* Bytes 12-15 */
+#endif
+}
+TransportElementDescriptorShort_T;
+
+
+typedef struct TransportElementDescriptor
+{
+ unsigned char ElementAddress[2]; /* Bytes 0-1 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ boolean Full:1; /* Byte 2 Bit 0 */
+ unsigned char :1; /* Byte 2 Bit 1 */
+ boolean Except:1; /* Byte 2 Bit 2 */
+ unsigned char :5; /* Byte 2 Bits 3-7 */
+#else
+ unsigned char :5; /* Byte 2 Bits 3-7 */
+ boolean Except:1; /* Byte 2 Bit 2 */
+ unsigned char :1; /* Byte 2 Bit 1 */
+ boolean Full:1; /* Byte 2 Bit 0 */
+#endif
+ unsigned char :8; /* Byte 3 */
+ unsigned char AdditionalSenseCode; /* Byte 4 */
+ unsigned char AdditionalSenseCodeQualifier; /* Byte 5 */
+ unsigned char :8; /* Byte 6 */
+ unsigned char :8; /* Byte 7 */
+ unsigned char :8; /* Byte 8 */
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ unsigned char :6; /* Byte 9 Bits 0-5 */
+ boolean SValid:1; /* Byte 9 Bit 6 */
+ boolean Invert:1; /* Byte 9 Bit 7 */
+#else
+ boolean Invert:1; /* Byte 9 Bit 7 */
+ boolean SValid:1; /* Byte 9 Bit 6 */
+ unsigned char :6; /* Byte 9 Bits 0-5 */
+#endif
+ unsigned char SourceStorageElementAddress[2]; /* Bytes 10-11 */
+ unsigned char PrimaryVolumeTag[36]; /* barcode */
+ unsigned char AlternateVolumeTag[36];
+#ifdef HAS_LONG_DESCRIPTORS
+ unsigned char Reserved[4]; /* 4 extra bytes? */
+#endif
+
+}
+TransportElementDescriptor_T;
+
+
+
+
+/* Now for element status data; */
+
+typedef unsigned char barcode[37];
+
+typedef struct ElementStatus {
+
+ int StorageElementCount;
+ int ImportExportCount;
+ int DataTransferElementCount;
+ int *DataTransferElementAddress; /* array. */
+ int *DataTransferElementSourceStorageElementNumber; /* array */
+ barcode *DataTransferPrimaryVolumeTag; /* array. */
+ barcode *DataTransferAlternateVolumeTag; /* array. */
+ barcode *PrimaryVolumeTag; /* array */
+ barcode *AlternateVolumeTag; /* array */
+ int *StorageElementAddress; /* array */
+ boolean *StorageElementIsImportExport; /* array */
+
+ int TransportElementAddress; /* assume only one of those... */
+
+ boolean *DataTransferElementFull; /* array */
+ boolean *StorageElementFull; /* array */
+
+} ElementStatus_T;
+
+
+/* Now for the SCSI ID and LUN information: */
+typedef struct scsi_id {
+ int id;
+ int lun;
+} scsi_id_t;
+
+#define MEDIUM_CHANGER_TYPE 8 /* what type bits are set for medium changers. */
+
+/* The following two structs are used for the brain-dead functions of the
+ * NSM jukebox.
+ */
+
+typedef struct NSM_Param {
+ unsigned char page_code;
+ unsigned char reserved;
+ unsigned char page_len_msb;
+ unsigned char page_len_lsb;
+ unsigned char allocation_msb;
+ unsigned char allocation_lsb;
+ unsigned char reserved2[2];
+ unsigned char command_code[4];
+ unsigned char command_params[2048]; /* egregious overkill. */
+} NSM_Param_T;
+
+extern RequestSense_T scsi_error_sense;
+
+typedef struct NSM_Result {
+ unsigned char page_code;
+ unsigned char reserved;
+ unsigned char page_len_msb;
+ unsigned char page_len_lsb;
+ unsigned char command_code[4];
+ unsigned char ces_code[2];
+ unsigned char return_data[0xffff]; /* egregioius overkill */
+} NSM_Result_T;
+
+#endif /* of multi-include protection. */
diff --git a/mtx.spec b/mtx.spec
new file mode 100644
index 0000000..7ccba9b
--- /dev/null
+++ b/mtx.spec
@@ -0,0 +1,109 @@
+Name: mtx
+Version: 1.3.12
+Release: 1%{?dist}
+Summary: SCSI media changer control program
+License: GPL
+Group: Utilities/System
+Source0: ftp://ftp.opensource-sw.net/pub/mtx/stable/%{name}-%{version}.tar.gz
+Url: http://%{name}.sourceforge.net
+BuildRoot: /var/tmp/%{name}-%{version}
+
+
+%description
+The MTX program controls the robotic mechanism in autoloaders and tape
+libraries such as the HP SureStore DAT 40x6, Exabyte EZ-17, and
+Exabyte 220. This program is also reported to work with a variety of other tape
+libraries and autochangers from Tandberg/Overland, Breece Hill, HP, and
+Seagate.
+
+%prep
+%setup -q
+
+%build
+%configure
+make
+
+%install
+mkdir -p $RPM_BUILD_ROOT/sbin
+install mtx $RPM_BUILD_ROOT/sbin/mtx
+mkdir -p $RPM_BUILD_ROOT/usr/sbin
+install loaderinfo $RPM_BUILD_ROOT/usr/sbin/loaderinfo
+install scsieject $RPM_BUILD_ROOT/usr/sbin/scsieject
+install scsitape $RPM_BUILD_ROOT/usr/sbin/scsitape
+install tapeinfo $RPM_BUILD_ROOT/usr/sbin/tapeinfo
+mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man1
+install mtx.1 $RPM_BUILD_ROOT/%{_mandir}/man1/mtx.1
+install loaderinfo.1 $RPM_BUILD_ROOT/%{_mandir}/man1/loaderinfo.1
+install scsieject.1 $RPM_BUILD_ROOT/%{_mandir}/man1/scsieject.1
+install scsitape.1 $RPM_BUILD_ROOT/%{_mandir}/man1/scsitape.1
+install tapeinfo.1 $RPM_BUILD_ROOT/%{_mandir}/man1/tapeinfo.1
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc mtx.doc CHANGES README mtxl.README.html
+%doc COMPATABILITY FAQ LICENSE* TODO contrib
+%{_mandir}/man1/*
+/sbin/mtx
+/usr/sbin/*
+
+%changelog
+* Fri Sep 27 2002 Eric Green <eric@badtux.org>
+- 1.3.0rel
+- move changelog to end.
+- change source directory to ftp.badtux.net.
+- use * for files to catch new files.
+
+* Wed Apr 18 2001 Kenneth Porter <shiva@well.com>
+- 1.2.12pre1
+- Need to create usr/sbin for install
+
+* Fri Mar 02 2001 Eric Green <eric@estinc.com>
+- 1.2.11pre6
+- Move tapeinfo,loaderinfo, scsitape to /usr/sbin rather than /sbin
+
+* Wed Feb 28 2001 Kenneth Porter <shiva@well.com>
+- 1.2.11pre5
+- Remove commented-out patch.
+- Use mandir FHS macro and configure macro.
+- Install more stuff.
+- Use build policy for stripping.
+
+* Wed Jan 17 2001 Eric Green <eric@estinc.com>
+- 1.2.11pre3
+- Removed patch, now use ./configure.
+
+* Mon Nov 27 2000 Eric Green <eric@estinc.com>
+- 1.2.10
+- Fixed patching to use the portable.patch.
+
+* Tue Jul 25 2000 Eric Green <eric@estinc.com>
+- 1.2.8
+- Added portability patch to mtx.spec so should compile on Red Hat Alpha etc.
+
+* Thu Jun 6 2000 Eric Green <eric@estinc.com>
+- 1.2.7
+- Fixed single-drive Exabyte 220 special case.
+- Fixed ADIC DAT Autochanger special case.
+- Fixed mtx.spec to move the binaries to /sbin since we need root access
+
+* Fri May 12 2000 Kenneth Porter <shiva@well.com>
+- 1.2.6
+- Fixed 'eepos' stuff to use | rather than || (whoops!)
+- Accept a 4-byte element descriptor for the robot arm for certain older
+- autochangers.
+
+* Mon May 8 2000 Kenneth Porter <shiva@well.com>
+- Spell sourceforge right so the link at rpmfind.net will work.
+
+* Thu May 4 2000 Kenneth Porter <shiva@well.com>
+- 1.2.5
+
+* Thu Oct 29 1998 Ian Macdonald <ianmacd@xs4all.nl>
+- moved mtx from /sbin to /bin, seeing as mt is also located there
+
+* Fri Oct 23 1998 Ian Macdonald <ianmacd@xs4all.nl>
+- first RPM release
diff --git a/mtx.spec.in b/mtx.spec.in
new file mode 100644
index 0000000..f6fd5ed
--- /dev/null
+++ b/mtx.spec.in
@@ -0,0 +1,109 @@
+Name: mtx
+Version: @@VERSION@@
+Release: 1%{?dist}
+Summary: SCSI media changer control program
+License: GPL
+Group: Utilities/System
+Source0: ftp://ftp.opensource-sw.net/pub/mtx/stable/%{name}-%{version}.tar.gz
+Url: http://%{name}.sourceforge.net
+BuildRoot: /var/tmp/%{name}-%{version}
+
+
+%description
+The MTX program controls the robotic mechanism in autoloaders and tape
+libraries such as the HP SureStore DAT 40x6, Exabyte EZ-17, and
+Exabyte 220. This program is also reported to work with a variety of other tape
+libraries and autochangers from Tandberg/Overland, Breece Hill, HP, and
+Seagate.
+
+%prep
+%setup -q
+
+%build
+%configure
+make
+
+%install
+mkdir -p $RPM_BUILD_ROOT/sbin
+install mtx $RPM_BUILD_ROOT/sbin/mtx
+mkdir -p $RPM_BUILD_ROOT/usr/sbin
+install loaderinfo $RPM_BUILD_ROOT/usr/sbin/loaderinfo
+install scsieject $RPM_BUILD_ROOT/usr/sbin/scsieject
+install scsitape $RPM_BUILD_ROOT/usr/sbin/scsitape
+install tapeinfo $RPM_BUILD_ROOT/usr/sbin/tapeinfo
+mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man1
+install mtx.1 $RPM_BUILD_ROOT/%{_mandir}/man1/mtx.1
+install loaderinfo.1 $RPM_BUILD_ROOT/%{_mandir}/man1/loaderinfo.1
+install scsieject.1 $RPM_BUILD_ROOT/%{_mandir}/man1/scsieject.1
+install scsitape.1 $RPM_BUILD_ROOT/%{_mandir}/man1/scsitape.1
+install tapeinfo.1 $RPM_BUILD_ROOT/%{_mandir}/man1/tapeinfo.1
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc mtx.doc CHANGES README mtxl.README.html
+%doc COMPATABILITY FAQ LICENSE* TODO contrib
+%{_mandir}/man1/*
+/sbin/mtx
+/usr/sbin/*
+
+%changelog
+* Fri Sep 27 2002 Eric Green <eric@badtux.org>
+- 1.3.0rel
+- move changelog to end.
+- change source directory to ftp.badtux.net.
+- use * for files to catch new files.
+
+* Wed Apr 18 2001 Kenneth Porter <shiva@well.com>
+- 1.2.12pre1
+- Need to create usr/sbin for install
+
+* Fri Mar 02 2001 Eric Green <eric@estinc.com>
+- 1.2.11pre6
+- Move tapeinfo,loaderinfo, scsitape to /usr/sbin rather than /sbin
+
+* Wed Feb 28 2001 Kenneth Porter <shiva@well.com>
+- 1.2.11pre5
+- Remove commented-out patch.
+- Use mandir FHS macro and configure macro.
+- Install more stuff.
+- Use build policy for stripping.
+
+* Wed Jan 17 2001 Eric Green <eric@estinc.com>
+- 1.2.11pre3
+- Removed patch, now use ./configure.
+
+* Mon Nov 27 2000 Eric Green <eric@estinc.com>
+- 1.2.10
+- Fixed patching to use the portable.patch.
+
+* Tue Jul 25 2000 Eric Green <eric@estinc.com>
+- 1.2.8
+- Added portability patch to mtx.spec so should compile on Red Hat Alpha etc.
+
+* Thu Jun 6 2000 Eric Green <eric@estinc.com>
+- 1.2.7
+- Fixed single-drive Exabyte 220 special case.
+- Fixed ADIC DAT Autochanger special case.
+- Fixed mtx.spec to move the binaries to /sbin since we need root access
+
+* Fri May 12 2000 Kenneth Porter <shiva@well.com>
+- 1.2.6
+- Fixed 'eepos' stuff to use | rather than || (whoops!)
+- Accept a 4-byte element descriptor for the robot arm for certain older
+- autochangers.
+
+* Mon May 8 2000 Kenneth Porter <shiva@well.com>
+- Spell sourceforge right so the link at rpmfind.net will work.
+
+* Thu May 4 2000 Kenneth Porter <shiva@well.com>
+- 1.2.5
+
+* Thu Oct 29 1998 Ian Macdonald <ianmacd@xs4all.nl>
+- moved mtx from /sbin to /bin, seeing as mt is also located there
+
+* Fri Oct 23 1998 Ian Macdonald <ianmacd@xs4all.nl>
+- first RPM release
diff --git a/mtxl.README.html b/mtxl.README.html
new file mode 100644
index 0000000..7f7e6d4
--- /dev/null
+++ b/mtxl.README.html
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+
+ <title>SCSI Media Changer and Backup Device Control System</title>
+
+ </head>
+
+ <body>
+<center>
+ <h1>SCSI Media Changer and Backup Device Control System</h1>
+</center>
+<p>
+[Also see the SourceForge <a href="http://sourceforge.net/projects/mtx">
+project page</a>.]
+<p>
+<i>mtx</i> is a set of low level driver programs to control features
+of SCSI backup related devices such as autoloaders, tape changers,
+media jukeboxes, and tape drives. It can also report much data,
+including serial numbers, maximum block sizes, and TapeAlert(tm)
+messages that most modern tape drives implement (to tell you the exact
+reason why a backup or restore failed), as well as do raw SCSI READ
+and WRITE commands to tape drives (not important on Linux, but
+important on Solaris due to the fact that the Solaris tape driver
+supports none of the additional features of tape drives invented after
+1988). <i>mtx</i> is designed to be a low level driver in a larger
+scripted backup solution, such as <a
+href="http://amanda.sourceforge.net">Amanda</a>.
+<i>mtx</i> is not
+supposed to itself be a high level interface to the SCSI devices that
+it controls.
+<p>
+This version has the following features:
+
+ <ul>
+ <li> Will deal with LARGE media libraries (over a hundred elements).
+ <li> Supports multi-drive media changers such as the Exabyte 220 dual-
+drive tape library.
+ <li> Supports the 'invert' bit for optical jukeboxes that need that in
+order to flip their media.
+ <li> Supports the 'eepos' bits for libraries that need this to extend/retract
+their import/export tray.
+ <li> Now supports import/export elements!
+ <li> Reports volume tags (bar codes) and "alternate volume tags"
+(whatever those are!) for those tape libraries
+that support them.
+<li> Now runs under FreeBSD and at least Solaris 8.
+
+<li> Now has a 'man' page!
+<li> The actual SCSI manipulation has been separated out into a library, so
+that you can create your own "C" programs that manipulate SCSI media changers
+directly. (Please note: this is under GPL, so any such programs will have
+to be under GPL also).
+</ul>
+
+<p>
+ This program supposedly supports FreeBSD, Solaris, Linux, HP/UX, and
+IRIX. Tru64 Unix and VMS are probably irretrievably broken at this
+time. This program has been tested under FreeBSD, Solaris, and Linux,
+and there only with a limited set of hardware. See the COMPATIBILITY
+list in the source code.
+</ul>
+<h2> Source Code </h2>
+The current source code is:
+<ul>
+<li> <a href="http://mtx.sourceforge.net/mtx-1.2.13.tar.gz">http://mtx.sourceforge.net/mtx-1.2.13.tar.gz</a>
+</ul>
+RPMs may be available from the following place:
+<ul>
+<li> <a href="http://rpmfind.net/linux/RPM/mtx.html">RPMfind's 'mtx' page</a>
+</ul>
+A .spec file is now included in the 'mtx' distribution for building your
+own RPM's.
+<p>
+Note that RPMs
+are courtesy of <a href="http://www.sewingwitch.com/ken/">Kenneth Porter</a>,
+who should be contacted regarding rpm-related problems.
+<p>
+
+<h2> Known Bugs And Limitations </h2>
+<ul>
+<li>
+ You may need to do a 'mt offline' (or equivalent for your OS)
+ on the tape drive to
+ eject the tape before you can issue the 'mtx unload' command.
+The Exabyte EZ-17 and 220 in particular will happily
+ sit there snapping the robot arm's claws around thin air
+ trying to grab a tape that's not there.
+<li>
+The 'next' command does not understand the 'invert' bit (i.e., does not
+recognize that for optical jukeboxes, the 'next' of side one is to unload,
+invert, and reload the same disk). It always advances to the next
+slot instead.
+ <li>
+ For some Linux distributions, you may need to re-compile
+ the kernel to scan SCSI LUN's in order to detect the media
+ changer. Check /proc/scsi/scsi to see what's going on.
+
+<li>
+ If you try to unload a tape to its 'source' slot, and said
+ slot is full, it will instead put the tape into the first
+ empty slot. Unfortunately the list of empty slots is not
+ updated between commands on the command line, so if you
+ try to unload another drive to a full 'source' slot during
+ the same invocation of 'mtx', it will try to unload to the
+ same (no longer empty) slot and will urp with a SCSI
+ error.
+
+<li> For big tape libraries (more than a couple dozen elements) this
+may set a big Allocation_Size in the SCSI command block for the
+REQUEST_ELEMENT_STATUS command. Some operating systems may not be able
+to handle this. Versions of Linux earlier than 2.2.6, in particular,
+may fail this request due to inability to find contiguous pages of
+memory for the SCSI transfer (later versions of Linux 'sg' device do
+scatter-gather so that this should no longer be a problem).
+
+<li> VMS and Tru64 support are probably irretrievably busted.
+
+
+<li> This program will only use the first arm of multiple-arm robots unless
+the robot re-maps all arms to one element ID.
+
+<li> It has been reported that this program works on Solaris 7 using the 'sst'
+driver, and may work on Solaris 8 using the 'sgen' driver. 'sst' can
+be gotten from the Amanda contrib directory at
+<a href="http://download.sourceforge.net/amanda/">http://download.sourceforge.net/amanda</a>.
+
+</ul>
+
+<h2> Philosophy </h2>
+The Unix philosophy is "many small tools chained together". <i>mtx</i> supplies
+those small tools so that you can create your own backup and
+recovery tools by chaining
+<i>mtx</i> pieces together, whether it be with /bin/sh, Perl, Python, or
+CAML.
+
+
+<h2> Support </h2>
+<ul>
+<li>There is now a 'mtx' mailing list at <a href="http://sourceforge.net/projects/mtx/">http://sourceforge.net/projects/mtx/</a>.
+<li>There is now a 'mtx' home page at <a href="http://mtx.sourceforge.net">http://mtx.sourceforge.net</a>.
+<li> There is now a FAQ that is part of the source code. Please read the
+FAQ first.
+<li>Report problems to Eric Lee Green (<a
+href="mailto:eric@badtux.org">eric@badtux.org</a>). READ THE FAQ FIRST!
+</ul>
+
+<h2> See Also: </h2>
+<ul>
+<li>The man page for 'mtx'! (once you get it installed).
+<li>T-10 SCSI Working Group home page at <a href="http://www.t10.org">www.t10.org</a>.
+<li>The Linux 'sg' SCSI generic driver home page at <a href="http://www.torque.net/sg/">http://www.torque.net/sg/</a>.
+<li> <a href="http://badtux.org/eric">The Home Page Of &lt;UL&gt; Tags Anonymous</a> Hi, my name is Eric, and I am addicted to the &lt;UL&gt; tag...
+</ul>
+ <hr>
+ <address>Maintained by <a href="mailto:eric@badtux.org">Eric Lee Green</a><br>
+ Hosted by <a href="http://www.valinux.com">VA Linux</a>'s <a href="http://www.sourceforge.net">SourceForge</a></address><br>
+
+
+<!-- Created: Fri Mar 3 12:19:38 MST 2000 -->
+<!-- hhmts start -->
+Last modified: Mon Jun 25 15:37:22 MST 2001
+<!-- hhmts end -->
+ </body>
+</html>
diff --git a/mtxl.c b/mtxl.c
new file mode 100644
index 0000000..3ae77a6
--- /dev/null
+++ b/mtxl.c
@@ -0,0 +1,1907 @@
+/* MTX -- SCSI Tape Attached Medium Changer Control Program
+
+ Copyright 1997-1998 by Leonard N. Zubkoff.
+ Copyright 1999-2006 by Eric Lee Green.
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+ $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+ $Revision: 193 $
+
+ This file created Feb 2000 by Eric Lee Green <eric@badtux.org> from pieces
+ extracted from mtx.c, plus a near total re-write of most of the beast.
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+*/
+
+
+/*
+ * FatalError: changed Feb. 2000 elg@badtux.org to eliminate a buffer
+ * overflow :-(. That could be important if mtxl is SUID for some reason.
+*/
+
+#include "mtx.h"
+#include "mtxl.h"
+
+/* #define DEBUG_NSM 1 */
+
+/* #define DEBUG_MODE_SENSE 1 */
+/* #define DEBUG */
+/* #define DEBUG_SCSI */
+#define __WEIRD_CHAR_SUPPRESS 1
+
+/* zap the following define when we finally add real import/export support */
+#define IMPORT_EXPORT_HACK 1 /* for the moment, import/export == storage */
+
+/* First, do some SCSI routines: */
+
+/* the camlib is used on FreeBSD. */
+#if HAVE_CAMLIB_H
+# include "scsi_freebsd.c"
+#endif
+
+/* the scsi_ctl interface is used on HP/UX. */
+#if HAVE_SYS_SCSI_CTL_H
+# include "scsi_hpux.c"
+#endif
+
+/* the 'sg' interface is used on Linux. */
+#if HAVE_SCSI_SG_H
+# include "scsi_linux.c"
+#endif
+
+/* the IOCTL_SCSI_PASSTHROUGH interface is used on Windows. */
+#if HAVE_DDK_NTDDSCSI_H || defined(_MSC_VER)
+# include "scsi_win32.c"
+#endif
+
+/* The 'uscsi' interface is used on Solaris. */
+#if HAVE_SYS_SCSI_IMPL_USCSI_H
+# include "scsi_sun.c"
+#endif
+
+/* The 'gsc' interface, is used on AIX. */
+#if HAVE_SYS_GSCDDS_H
+# include "scsi_aix.c"
+#endif
+
+/* The 'dslib' interface is used on SGI. */
+#if HAVE_DSLIB_H
+# include "scsi_sgi.c"
+#endif
+
+/* Hmm, dunno what to do about Digital Unix at the moment. */
+#ifdef DIGITAL_UNIX
+# include "du/scsi.c"
+#endif
+
+#ifdef VMS
+# include "[.vms]scsi.c"
+#endif
+
+extern char *argv0; /* something to let us do good error messages. */
+
+/* create a global RequestSenseT value. */
+RequestSense_T scsi_error_sense;
+
+/* Now for some low-level SCSI stuff: */
+
+Inquiry_T *RequestInquiry(DEVICE_TYPE fd, RequestSense_T *RequestSense)
+{
+ Inquiry_T *Inquiry;
+ CDB_T CDB;
+
+ Inquiry = (Inquiry_T *) xmalloc(sizeof(Inquiry_T));
+
+ CDB[0] = 0x12; /* INQUIRY */
+ CDB[1] = 0; /* EVPD = 0 */
+ CDB[2] = 0; /* Page Code */
+ CDB[3] = 0; /* Reserved */
+ CDB[4] = sizeof(Inquiry_T); /* Allocation Length */
+ CDB[5] = 0; /* Control */
+
+ /* set us a very short timeout, sigh... */
+ SCSI_Set_Timeout(30); /* 30 seconds, sigh! */
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, Inquiry, sizeof(Inquiry_T), RequestSense) != 0)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "SCSI Inquiry Command failed\n");
+#endif
+ free(Inquiry);
+ return NULL; /* sorry! */
+ }
+ return Inquiry;
+}
+
+
+#if defined(DEBUG_NSM) || defined(DEBUG_EXCHANGE)
+/* DEBUG */
+static void dump_cdb(unsigned char *CDB, int len)
+{
+ fprintf(stderr,"CDB:");
+ PrintHex(1, CDB, len);
+}
+#endif
+
+
+#if defined(DEBUG_NSM) || defined(DEBUG_ADIC)
+/* DEBUG */
+static void dump_data(unsigned char *data, int len)
+{
+ if (!len)
+ {
+ fprintf(stderr,"**NO DATA**\n");
+ return;
+ }
+
+ fprintf(stderr,"DATA:");
+ PrintHex(1, data, len);
+}
+#endif
+
+
+int BigEndian16(unsigned char *BigEndianData)
+{
+ return (BigEndianData[0] << 8) + BigEndianData[1];
+}
+
+
+int BigEndian24(unsigned char *BigEndianData)
+{
+ return (BigEndianData[0] << 16) + (BigEndianData[1] << 8) + BigEndianData[2];
+}
+
+
+void FatalError(char *ErrorMessage, ...)
+{
+#define FORMAT_BUF_LEN 1024
+
+ char FormatBuffer[FORMAT_BUF_LEN];
+ char *SourcePointer;
+ char *TargetPointer = FormatBuffer;
+ char Character, LastCharacter = '\0';
+ int numchars = 0;
+
+ va_list ArgumentPointer;
+ va_start(ArgumentPointer, ErrorMessage);
+ /* SourcePointer = "mtx: "; */
+ sprintf(TargetPointer,"%s: ",argv0);
+ numchars=strlen(TargetPointer);
+
+ while ((Character = *ErrorMessage++) != '\0')
+ {
+ if (LastCharacter == '%')
+ {
+ if (Character == 'm')
+ {
+ SourcePointer = strerror(errno);
+ while ((Character = *SourcePointer++) != '\0')
+ {
+ *TargetPointer++ = Character;
+ numchars++;
+ if (numchars == FORMAT_BUF_LEN - 1)
+ {
+ break;
+ }
+ }
+ if (numchars == FORMAT_BUF_LEN - 1)
+ {
+ break; /* break outer loop... */
+ }
+ }
+ else
+ {
+ *TargetPointer++ = '%';
+ *TargetPointer++ = Character;
+ numchars++;
+ if (numchars == FORMAT_BUF_LEN - 1)
+ {
+ break;
+ }
+ }
+ LastCharacter = '\0';
+ }
+ else
+ {
+ if (Character != '%')
+ {
+ *TargetPointer++ = Character;
+ numchars++;
+ if (numchars == FORMAT_BUF_LEN-1)
+ {
+ break;
+ }
+ }
+ LastCharacter = Character;
+ }
+ }
+
+ *TargetPointer = '\0'; /* works even if we had to break from above... */
+ vfprintf(stderr, FormatBuffer, ArgumentPointer);
+ va_end(ArgumentPointer);
+
+#ifndef VMS
+ exit(1);
+#else
+ sys$exit(VMS_ExitCode);
+#endif
+}
+
+/* This is a really slow and stupid 'bzero' implementation'... */
+void slow_bzero(char *buffer, int numchars)
+{
+ while (numchars--)
+ {
+ *buffer++ = 0;
+ }
+}
+
+/* malloc some memory while checking for out-of-memory conditions. */
+void *xmalloc(size_t Size)
+{
+ void *Result = (void *) malloc(Size);
+ if (Result == NULL)
+ {
+ FatalError("cannot allocate %d bytes of memory\n", Size);
+ }
+ return Result;
+}
+
+/* malloc some memory, zeroing it too: */
+void *xzmalloc(size_t Size)
+{
+ void *Result = (void *)xmalloc(Size);
+
+ slow_bzero(Result, Size);
+ return Result;
+}
+
+
+int min(int x, int y)
+{
+ return (x < y ? x : y);
+}
+
+
+int max(int x, int y)
+{
+ return (x > y ? x : y);
+}
+
+
+/* Okay, this is a hack for the NSM modular jukebox series, which
+ * uses the "SEND DIAGNOSTIC" command to do shit.
+ */
+
+int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
+ int param_len, int timeout)
+{
+ CDB_T CDB;
+ int list_len = param_len + sizeof(NSM_Param_T) - 2048;
+
+ /* Okay, now for the command: */
+ CDB[0] = 0x1D;
+ CDB[1] = 0x10;
+ CDB[2] = 0;
+ CDB[3] = (unsigned char)(list_len >> 8);
+ CDB[4] = (unsigned char)list_len;
+ CDB[5] = 0;
+
+#ifdef DEBUG_NSM
+ dump_cdb(&CDB,6);
+ dump_data(nsm_command,list_len);
+#endif
+ fflush(stderr);
+ /* Don't set us any timeout unless timeout is > 0 */
+ if (timeout > 0)
+ {
+ SCSI_Set_Timeout(timeout); /* 30 minutes, sigh! */
+ }
+
+ /* Now send the command: */
+ if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6, nsm_command, list_len, &scsi_error_sense))
+ {
+ return -1; /* we failed */
+ }
+ return 0; /* Did it! */
+}
+
+NSM_Result_T *RecNSMHack( DEVICE_TYPE MediumChangerFD,
+ int param_len, int timeout)
+{
+ CDB_T CDB;
+
+ NSM_Result_T *retval = (NSM_Result_T *)xzmalloc(sizeof(NSM_Result_T));
+
+ int list_len = param_len + sizeof(NSM_Result_T) - 0xffff;
+
+ /* Okay, now for the command: */
+ CDB[0] = 0x1C;
+ CDB[1] = 0x00;
+ CDB[2] = 0;
+ CDB[3] = (unsigned char)(list_len >> 8);
+ CDB[4] = (unsigned char)list_len;
+ CDB[5] = 0;
+
+#ifdef DEBUG_NSM
+ dump_cdb(&CDB,6);
+#endif
+
+ /* Don't set us any timeout unless timeout is > 0 */
+ if (timeout > 0)
+ {
+ SCSI_Set_Timeout(timeout);
+ }
+
+ /* Now send the command: */
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 6, retval, list_len, &scsi_error_sense))
+ {
+ return NULL; /* we failed */
+ }
+
+#ifdef DEBUG_NSM
+ fprintf(stderr,
+ "page_code=%02x page_len=%d command_code=%s\n",
+ retval->page_code,
+ (int) ((retval->page_len_msb << 8) + retval->page_len_lsb),
+ retval->command_code);
+#endif
+
+ return retval; /* Did it! (maybe!)*/
+}
+
+/* Routine to inventory the library. Needed by, e.g., some Breece Hill
+ * loaders. Sends an INITIALIZE_ELEMENT_STATUS command. This command
+ * has no parameters, such as a range to scan :-(.
+ */
+
+int Inventory(DEVICE_TYPE MediumChangerFD)
+{
+ CDB_T CDB;
+
+ /* okay, now for the command: */
+ CDB[0] = 0x07;
+ CDB[1] = CDB[2] = CDB[3] = CDB[4] = CDB[5] = 0;
+
+ /* set us a very long timeout, sigh... */
+ SCSI_Set_Timeout(30 * 60); /* 30 minutes, sigh! */
+
+ if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0)
+ {
+ /* If error is UNIT ATTENTION then retry the request */
+ if (scsi_error_sense.ErrorCode != 0x70 || scsi_error_sense.SenseKey != 6 ||
+ ClearUnitAttention(MediumChangerFD, &scsi_error_sense) != 0 ||
+ SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0)
+ {
+ PrintRequestSense(&scsi_error_sense);
+ fprintf(stderr, "Initialize Element Status (0x07) failed\n");
+ return -1; /* could not do! */
+ }
+ }
+ return 0; /* did do! */
+}
+
+/* Routine to read the Mode Sense Element Address Assignment Page */
+/* We try to read the page. If we can't read the page, we return NULL.
+ * Our caller really isn't too worried about why we could not read the
+ * page, it will simply default to some kind of default values.
+ */
+ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
+{
+ CDB_T CDB;
+ ElementModeSense_T *retval; /* processed SCSI. */
+ unsigned char input_buffer[136];
+ ElementModeSensePage_T *sense_page; /* raw SCSI. */
+
+ /* okay, now for the command: */
+ CDB[0] = 0x1A; /* Mode Sense(6) */
+ CDB[1] = 0x08;
+ CDB[2] = 0x1D; /* Mode Sense Element Address Assignment Page */
+ CDB[3] = 0;
+ CDB[4] = 136; /* allocation_length... */
+ CDB[5] = 0;
+
+ /* clear the data buffer: */
+ slow_bzero((char *)&scsi_error_sense, sizeof(RequestSense_T));
+ slow_bzero((char *)input_buffer, sizeof(input_buffer));
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 6,
+ &input_buffer, sizeof(input_buffer), &scsi_error_sense) != 0)
+ {
+ /* If error is UNIT ATTENTION then retry the request */
+ if (scsi_error_sense.ErrorCode != 0x70 || scsi_error_sense.SenseKey != 6 ||
+ ClearUnitAttention(MediumChangerFD, &scsi_error_sense) != 0 ||
+ SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 6,
+ &input_buffer, sizeof(input_buffer), &scsi_error_sense) != 0)
+ {
+ PrintRequestSense(&scsi_error_sense);
+ fprintf(stderr,"Mode sense (0x1A) for Page 0x1D failed\n");
+ fflush(stderr);
+ return NULL; /* sorry, couldn't do it. */
+ }
+ }
+
+ /* Could do it, now build return value: */
+
+#ifdef DEBUG_MODE_SENSE
+ PrintHex(0, input_buffer, 30);
+#endif
+
+ /* first, skip past: mode data header, and block descriptor header if any */
+ sense_page=(ElementModeSensePage_T *)(input_buffer+4+input_buffer[3]);
+
+#ifdef DEBUG_MODE_SENSE
+ fprintf(stderr,"*sense_page=%x %x\n",*((unsigned char *)sense_page),sense_page->PageCode);
+ fflush(stderr);
+#endif
+
+ retval = (ElementModeSense_T *)xzmalloc(sizeof(ElementModeSense_T));
+
+ /* Remember that all SCSI values are big-endian: */
+ retval->MediumTransportStart =
+ (((int)sense_page->MediumTransportStartHi) << 8) +
+ sense_page->MediumTransportStartLo;
+
+ retval->NumMediumTransport =
+ (((int)(sense_page->NumMediumTransportHi))<<8) +
+ sense_page->NumMediumTransportLo;
+
+ /* HACK! Some HP autochangers don't report NumMediumTransport right! */
+ /* ARG! TAKE OUT THE %#@!# HACK! */
+#ifdef STUPID_DUMB_IDIOTIC_HP_LOADER_HACK
+ if (!retval->NumMediumTransport)
+ {
+ retval->NumMediumTransport = 1;
+ }
+#endif
+
+#ifdef DEBUG_MODE_SENSE
+ fprintf(stderr, "rawNumStorage= %d %d rawNumImportExport= %d %d\n",
+ sense_page->NumStorageHi, sense_page->NumStorageLo,
+ sense_page->NumImportExportHi, sense_page->NumImportExportLo);
+ fprintf(stderr, "rawNumTransport=%d %d rawNumDataTransfer=%d %d\n",
+ sense_page->NumMediumTransportHi, sense_page->NumMediumTransportLo,
+ sense_page->NumDataTransferHi, sense_page->NumDataTransferLo);
+ fflush(stderr);
+#endif
+
+ retval->StorageStart =
+ ((int)sense_page->StorageStartHi << 8) + sense_page->StorageStartLo;
+
+ retval->NumStorage =
+ ((int)sense_page->NumStorageHi << 8) + sense_page->NumStorageLo;
+
+ retval->ImportExportStart =
+ ((int)sense_page->ImportExportStartHi << 8) + sense_page->ImportExportStartLo;
+
+ retval->NumImportExport =
+ ((int)sense_page->NumImportExportHi << 8) + sense_page->NumImportExportLo;
+
+ retval->DataTransferStart =
+ ((int)sense_page->DataTransferStartHi << 8) + sense_page->DataTransferStartLo;
+
+ retval->NumDataTransfer =
+ ((int)sense_page->NumDataTransferHi << 8) + sense_page->NumDataTransferLo;
+
+ /* allocate a couple spares 'cause some HP autochangers and maybe others
+ * don't properly report the robotics arm(s) count here...
+ */
+ retval->NumElements =
+ retval->NumStorage+retval->NumImportExport +
+ retval->NumDataTransfer+retval->NumMediumTransport;
+
+ retval->MaxReadElementStatusData =
+ (sizeof(ElementStatusDataHeader_T) +
+ 4 * sizeof(ElementStatusPage_T) +
+ retval->NumElements * sizeof(TransportElementDescriptor_T));
+
+#ifdef IMPORT_EXPORT_HACK
+ retval->NumStorage = retval->NumStorage+retval->NumImportExport;
+#endif
+
+#ifdef DEBUG_MODE_SENSE
+ fprintf(stderr, "NumMediumTransport=%d\n", retval->NumMediumTransport);
+ fprintf(stderr, "NumStorage=%d\n", retval->NumStorage);
+ fprintf(stderr, "NumImportExport=%d\n", retval->NumImportExport);
+ fprintf(stderr, "NumDataTransfer=%d\n", retval->NumDataTransfer);
+ fprintf(stderr, "MaxReadElementStatusData=%d\n", retval->MaxReadElementStatusData);
+ fprintf(stderr, "NumElements=%d\n", retval->NumElements);
+ fflush(stderr);
+#endif
+
+ return retval;
+}
+
+static void FreeElementData(ElementStatus_T *data)
+{
+ free(data->DataTransferElementAddress);
+ free(data->DataTransferElementSourceStorageElementNumber);
+ free(data->DataTransferPrimaryVolumeTag);
+ free(data->DataTransferAlternateVolumeTag);
+ free(data->PrimaryVolumeTag);
+ free(data->AlternateVolumeTag);
+ free(data->StorageElementAddress);
+ free(data->StorageElementIsImportExport);
+ free(data->StorageElementFull);
+ free(data->DataTransferElementFull);
+}
+
+
+/* allocate data */
+
+static ElementStatus_T *AllocateElementData(ElementModeSense_T *mode_sense)
+{
+ ElementStatus_T *retval;
+
+ retval = (ElementStatus_T *)xzmalloc(sizeof(ElementStatus_T));
+
+ /* now for the invidual component arrays.... */
+
+ retval->DataTransferElementAddress =
+ (int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
+ retval->DataTransferElementSourceStorageElementNumber =
+ (int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
+ retval->DataTransferPrimaryVolumeTag =
+ (barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumDataTransfer + 1));
+ retval->DataTransferAlternateVolumeTag =
+ (barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumDataTransfer + 1));
+ retval->PrimaryVolumeTag =
+ (barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumStorage + 1));
+ retval->AlternateVolumeTag =
+ (barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumStorage + 1));
+ retval->StorageElementAddress =
+ (int *)xzmalloc(sizeof(int) * (mode_sense->NumStorage + 1));
+ retval->StorageElementIsImportExport =
+ (boolean *)xzmalloc(sizeof(boolean) * (mode_sense->NumStorage + 1));
+ retval->StorageElementFull =
+ (boolean *)xzmalloc(sizeof(boolean) * (mode_sense->NumStorage + 1));
+ retval->DataTransferElementFull =
+ (boolean *)xzmalloc(sizeof(boolean) * (mode_sense->NumDataTransfer + 1));
+
+ return retval; /* sigh! */
+}
+
+
+void copy_barcode(unsigned char *src, unsigned char *dest)
+{
+ int i;
+
+ for (i=0; i < 36; i++)
+ {
+ *dest = *src++;
+
+ if ((*dest < 32) || (*dest > 127))
+ {
+ *dest = '\0';
+ }
+
+ dest++;
+ }
+ *dest = 0; /* null-terminate */
+}
+
+/* This #%!@# routine has more parameters than I can count! */
+static unsigned char *SendElementStatusRequestActual(
+ DEVICE_TYPE MediumChangerFD,
+ RequestSense_T *RequestSense,
+ Inquiry_T *inquiry_info,
+ SCSI_Flags_T *flags,
+ int ElementStart,
+ int NumElements,
+ int NumBytes
+ )
+{
+ CDB_T CDB;
+ boolean is_attached = false;
+
+ unsigned char *DataBuffer; /* size of data... */
+
+#ifdef HAVE_GET_ID_LUN
+ scsi_id_t *scsi_id;
+#endif
+ if (inquiry_info->MChngr &&
+ inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)
+ {
+ is_attached = true;
+ }
+
+ if (flags->no_attached)
+ {
+ /* override, sigh */
+ is_attached = false;
+ }
+
+ DataBuffer = (unsigned char *)xzmalloc(NumBytes + 1);
+
+ slow_bzero((char *)RequestSense, sizeof(RequestSense_T));
+
+#ifdef HAVE_GET_ID_LUN
+ scsi_id = SCSI_GetIDLun(MediumChangerFD);
+#endif
+
+ CDB[0] = 0xB8; /* READ ELEMENT STATUS */
+
+ if (is_attached)
+ {
+ CDB[0] = 0xB4; /* whoops, READ_ELEMENT_STATUS_ATTACHED! */
+ }
+
+#ifdef HAVE_GET_ID_LUN
+ CDB[1] = (scsi_id->lun << 5) | ((flags->no_barcodes) ?
+ 0 : 0x10) | flags->elementtype; /* Lun + VolTag + Type code */
+ free(scsi_id);
+#else
+ /* Element Type Code = 0, VolTag = 1 */
+ CDB[1] = (unsigned char)((flags->no_barcodes ? 0 : 0x10) | flags->elementtype);
+#endif
+ /* Starting Element Address */
+ CDB[2] = (unsigned char)(ElementStart >> 8);
+ CDB[3] = (unsigned char)ElementStart;
+
+ /* Number Of Elements */
+ CDB[4]= (unsigned char)(NumElements >> 8);
+ CDB[5]= (unsigned char)NumElements;
+
+ CDB[6] = 0; /* Reserved */
+
+ /* allocation length */
+ CDB[7]= (unsigned char)(NumBytes >> 16);
+ CDB[8]= (unsigned char)(NumBytes >> 8);
+ CDB[9]= (unsigned char)NumBytes;
+
+ CDB[10] = 0; /* Reserved */
+ CDB[11] = 0; /* Control */
+
+#ifdef DEBUG_BARCODE
+ fprintf(stderr,"CDB:\n");
+ PrintHex(2, CDB, 12);
+#endif
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
+ DataBuffer,NumBytes, RequestSense) != 0)
+ {
+
+#ifdef DEBUG
+ fprintf(stderr, "Read Element Status (0x%02X) failed\n", CDB[0]);
+#endif
+
+ /*
+ First see if we have sense key of 'illegal request',
+ additional sense code of '24', additional sense qualfier of
+ '0', and field in error of '4'. This means that we issued a request
+ w/bar code reader and did not have one, thus must re-issue the request
+ w/out barcode :-(.
+ */
+
+ /*
+ Most autochangers and tape libraries set a sense key here if
+ they do not have a bar code reader. For some reason, the ADIC DAT
+ uses a different sense key? Let's retry w/o bar codes for *ALL*
+ sense keys.
+ */
+
+ if (RequestSense->SenseKey > 1)
+ {
+ /* we issued a code requesting bar codes, there is no bar code reader? */
+ /* clear out our sense buffer first... */
+ slow_bzero((char *)RequestSense, sizeof(RequestSense_T));
+
+ CDB[1] &= ~0x10; /* clear bar code flag! */
+
+#ifdef DEBUG_BARCODE
+ fprintf(stderr,"CDB:\n");
+ PrintHex(2, CDB, 12);
+#endif
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
+ DataBuffer, NumBytes, RequestSense) != 0)
+ {
+ free(DataBuffer);
+ return NULL;
+ }
+ }
+ else
+ {
+ free(DataBuffer);
+ return NULL;
+ }
+ }
+
+#ifdef DEBUG_BARCODE
+ /* print a bunch of extra debug data :-(. */
+ PrintRequestSense(RequestSense); /* see what it sez :-(. */
+ fprintf(stderr,"Data:\n");
+ PrintHex(2, DataBuffer, 40);
+#endif
+ return DataBuffer; /* we succeeded! */
+}
+
+
+unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,
+ RequestSense_T *RequestSense,
+ Inquiry_T *inquiry_info,
+ SCSI_Flags_T *flags,
+ int ElementStart,
+ int NumElements,
+ int NumBytes
+ )
+{
+ unsigned char *DataBuffer; /* size of data... */
+ int real_numbytes;
+
+ DataBuffer = SendElementStatusRequestActual(MediumChangerFD,
+ RequestSense,
+ inquiry_info,
+ flags,
+ ElementStart,
+ NumElements,
+ NumBytes
+ );
+ /*
+ One weird loader wants either 8 or BYTE_COUNT_OF_REPORT
+ values for the ALLOCATION_LENGTH. Give it what it wants
+ if we get an Sense Key of 05 Illegal Request with a
+ CDB position of 7 as the field in error.
+ */
+
+ if (DataBuffer == NULL &&
+ RequestSense->SenseKey == 5 &&
+ RequestSense->CommandData &&
+ RequestSense->BitPointer == 7)
+ {
+ NumBytes=8; /* send an 8 byte request */
+ DataBuffer=SendElementStatusRequestActual( MediumChangerFD,
+ RequestSense,
+ inquiry_info,
+ flags,
+ ElementStart,
+ NumElements,
+ NumBytes
+ );
+ }
+
+ /* the above code falls thru into this: */
+ if (DataBuffer != NULL)
+ {
+ /* see if we need to retry with a bigger NumBytes: */
+ real_numbytes = ((int)DataBuffer[5] << 16) +
+ ((int)DataBuffer[6] << 8) +
+ (int)DataBuffer[7] + 8;
+
+ if (real_numbytes > NumBytes)
+ {
+ /* uh-oh, retry! */
+ free(DataBuffer); /* solve memory leak */
+ DataBuffer = SendElementStatusRequestActual(MediumChangerFD,
+ RequestSense,
+ inquiry_info,
+ flags,
+ ElementStart,
+ NumElements,
+ real_numbytes
+ );
+ }
+ }
+
+ return DataBuffer;
+}
+
+
+
+/******************* ParseElementStatus ***********************************/
+/* This does the actual grunt work of parsing element status data. It fills
+ * in appropriate pieces of its input data. It may be called multiple times
+ * while we are gathering element status.
+ */
+
+static void ParseElementStatus( int *EmptyStorageElementAddress,
+ int *EmptyStorageElementCount,
+ unsigned char *DataBuffer,
+ ElementStatus_T *ElementStatus,
+ ElementModeSense_T *mode_sense,
+ int *pNextElement
+ )
+{
+ unsigned char *DataPointer = DataBuffer;
+ TransportElementDescriptor_T TEBuf;
+ TransportElementDescriptor_T *TransportElementDescriptor;
+ ElementStatusDataHeader_T *ElementStatusDataHeader;
+ Element2StatusPage_T *ElementStatusPage;
+ Element2StatusPage_T ESBuf;
+ int ElementCount;
+ int TransportElementDescriptorLength;
+ int BytesAvailable;
+ int ImportExportIndex;
+
+ ElementStatusDataHeader = (ElementStatusDataHeader_T *) DataPointer;
+ DataPointer += sizeof(ElementStatusDataHeader_T);
+ ElementCount =
+ BigEndian16(ElementStatusDataHeader->NumberOfElementsAvailable);
+
+#ifdef DEBUG
+ fprintf(stderr,"ElementCount=%d\n",ElementCount);
+ fflush(stderr);
+#endif
+
+ while (ElementCount > 0)
+ {
+#ifdef DEBUG
+ int got_element_num=0;
+
+ fprintf(stderr,"Working on element # %d Element Count %d\n",got_element_num,ElementCount);
+ got_element_num++;
+#endif
+
+ memcpy(&ESBuf, DataPointer, sizeof(ElementStatusPage_T));
+ ElementStatusPage = &ESBuf;
+ DataPointer += sizeof(ElementStatusPage_T);
+
+ TransportElementDescriptorLength =
+ BigEndian16(ElementStatusPage->ElementDescriptorLength);
+
+ if (TransportElementDescriptorLength <
+ sizeof(TransportElementDescriptorShort_T))
+ {
+ /* Foo, Storage Element Descriptors can be 4 bytes?! */
+ if ((ElementStatusPage->ElementTypeCode != MediumTransportElement &&
+ ElementStatusPage->ElementTypeCode != StorageElement &&
+ ElementStatusPage->ElementTypeCode != ImportExportElement ) ||
+ TransportElementDescriptorLength < 4)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"boom! ElementTypeCode=%d\n",ElementStatusPage->ElementTypeCode);
+#endif
+ FatalError("Transport Element Descriptor Length too short: %d\n", TransportElementDescriptorLength);
+ }
+ }
+#ifdef DEBUG
+ fprintf(stderr,"Transport Element Descriptor Length=%d\n",TransportElementDescriptorLength);
+#endif
+ BytesAvailable =
+ BigEndian24(ElementStatusPage->ByteCountOfDescriptorDataAvailable);
+#ifdef DEBUG
+ fprintf(stderr,"%d bytes of descriptor data available in descriptor\n",
+ BytesAvailable);
+#endif
+ /* work around a bug in ADIC DAT loaders */
+ if (BytesAvailable <= 0)
+ {
+ ElementCount--; /* sorry :-( */
+ }
+ while (BytesAvailable > 0)
+ {
+ /* TransportElementDescriptor =
+ (TransportElementDescriptor_T *) DataPointer; */
+ memcpy(&TEBuf, DataPointer,
+ (TransportElementDescriptorLength <= sizeof(TEBuf)) ?
+ TransportElementDescriptorLength :
+ sizeof(TEBuf));
+ TransportElementDescriptor = &TEBuf;
+
+ if (pNextElement != NULL)
+ {
+ if (BigEndian16(TransportElementDescriptor->ElementAddress) != 0 || *pNextElement == 0)
+ {
+ (*pNextElement) = BigEndian16(TransportElementDescriptor->ElementAddress) + 1;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ DataPointer += TransportElementDescriptorLength;
+ BytesAvailable -= TransportElementDescriptorLength;
+ ElementCount--;
+
+ switch (ElementStatusPage->ElementTypeCode)
+ {
+ case MediumTransportElement:
+ ElementStatus->TransportElementAddress = BigEndian16(TransportElementDescriptor->ElementAddress);
+#ifdef DEBUG
+ fprintf(stderr,"TransportElementAddress=%d\n",ElementStatus->TransportElementAddress);
+#endif
+ break;
+
+ /* we treat ImportExport elements as if they were normal
+ * storage elements now, sigh...
+ */
+ case ImportExportElement:
+#ifdef DEBUG
+ fprintf(stderr,"ImportExportElement=%d\n",ElementStatus->StorageElementCount);
+#endif
+ if (ElementStatus->ImportExportCount >= mode_sense->NumImportExport)
+ {
+ fprintf(stderr,"Warning:Too Many Import/Export Elements Reported (expected %d, now have %d\n",
+ mode_sense->NumImportExport,
+ ElementStatus->ImportExportCount + 1);
+ fflush(stderr);
+ return; /* we're done :-(. */
+ }
+
+ ImportExportIndex = mode_sense->NumStorage - mode_sense->NumImportExport + ElementStatus->ImportExportCount;
+
+ ElementStatus->StorageElementAddress[ImportExportIndex] =
+ BigEndian16(TransportElementDescriptor->ElementAddress);
+ ElementStatus->StorageElementFull[ImportExportIndex] =
+ TransportElementDescriptor->Full;
+
+ if ( (TransportElementDescriptorLength > 11) &&
+ (ElementStatusPage->VolBits & E2_AVOLTAG))
+ {
+ copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
+ ElementStatus->AlternateVolumeTag[ImportExportIndex]);
+ }
+ else
+ {
+ ElementStatus->AlternateVolumeTag[ImportExportIndex][0] = 0; /* null string. */;
+ }
+ if ((TransportElementDescriptorLength > 11) &&
+ (ElementStatusPage->VolBits & E2_PVOLTAG))
+ {
+ copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
+ ElementStatus->PrimaryVolumeTag[ImportExportIndex]);
+ }
+ else
+ {
+ ElementStatus->PrimaryVolumeTag[ImportExportIndex][0]=0; /* null string. */
+ }
+
+ ElementStatus->StorageElementIsImportExport[ImportExportIndex] = 1;
+
+ ElementStatus->ImportExportCount++;
+ break;
+
+ case StorageElement:
+#ifdef DEBUG
+ fprintf(stderr,"StorageElementCount=%d ElementAddress = %d ",ElementStatus->StorageElementCount,BigEndian16(TransportElementDescriptor->ElementAddress));
+#endif
+ /* ATL/Exabyte kludge -- skip slots that aren't installed :-( */
+ if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
+ TransportElementDescriptor->AdditionalSenseCodeQualifier==0x02)
+ continue;
+
+ ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount] =
+ BigEndian16(TransportElementDescriptor->ElementAddress);
+ ElementStatus->StorageElementFull[ElementStatus->StorageElementCount] =
+ TransportElementDescriptor->Full;
+#ifdef DEBUG
+ if (TransportElementDescriptor->Except)
+ fprintf(stderr,"ASC,ASCQ = 0x%x,0x%x ",TransportElementDescriptor->AdditionalSenseCode,TransportElementDescriptor->AdditionalSenseCodeQualifier);
+ fprintf(stderr,"TransportElement->Full = %d\n",TransportElementDescriptor->Full);
+#endif
+ if (!TransportElementDescriptor->Full)
+ {
+ EmptyStorageElementAddress[(*EmptyStorageElementCount)++] =
+ ElementStatus->StorageElementCount; /* slot idx. */
+ /* ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount]; */
+ }
+ if ((TransportElementDescriptorLength > 11) &&
+ (ElementStatusPage->VolBits & E2_AVOLTAG))
+ {
+ copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
+ ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount]);
+ }
+ else
+ {
+ ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount][0]=0; /* null string. */;
+ }
+ if ((TransportElementDescriptorLength > 11) &&
+ (ElementStatusPage->VolBits & E2_PVOLTAG))
+ {
+ copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
+ ElementStatus->PrimaryVolumeTag[ElementStatus->StorageElementCount]);
+ }
+ else
+ {
+ ElementStatus->PrimaryVolumeTag[ElementStatus->StorageElementCount][0]=0; /* null string. */
+ }
+
+ ElementStatus->StorageElementCount++;
+ /*
+ Note that the original mtx had no check here for
+ buffer overflow, though some drives might mistakingly
+ do one...
+ */
+
+ if (ElementStatus->StorageElementCount > mode_sense->NumStorage)
+ {
+ fprintf(stderr,"Warning:Too Many Storage Elements Reported (expected %d, now have %d\n",
+ mode_sense->NumStorage,
+ ElementStatus->StorageElementCount);
+ fflush(stderr);
+ return; /* we're done :-(. */
+ }
+ break;
+
+ case DataTransferElement:
+ /* tape drive not installed, go back to top of loop */
+
+ /* if (TransportElementDescriptor->Except) continue ; */
+
+ /* Note: This is for Exabyte tape libraries that improperly
+ report that they have a 2nd tape drive when they don't. We
+ could generalize this in an ideal world, but my attempt to
+ do so failed with dual-drive Exabyte tape libraries that
+ *DID* have the second drive. Sigh.
+ */
+ if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
+ TransportElementDescriptor->AdditionalSenseCodeQualifier==0x04)
+ {
+ continue;
+ }
+
+ /* generalize it. Does it work? Let's try it! */
+ /*
+ No, dammit, following does not work on dual-drive Exabyte
+ 'cause if a tape is in the drive, it sets the AdditionalSense
+ code to something (sigh).
+ */
+ /* if (TransportElementDescriptor->AdditionalSenseCode!=0)
+ continue;
+ */
+
+ ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount] =
+ BigEndian16(TransportElementDescriptor->ElementAddress);
+ ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount] =
+ TransportElementDescriptor->Full;
+ ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount] =
+ BigEndian16(TransportElementDescriptor->SourceStorageElementAddress);
+
+#if DEBUG
+ fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
+ ElementStatus->DataTransferElementCount,
+ ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
+ ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount],
+ ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount]);
+#endif
+ if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer)
+ {
+ FatalError("Too many Data Transfer Elements Reported\n");
+ }
+
+ if (ElementStatusPage->VolBits & E2_PVOLTAG)
+ {
+ copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
+ ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
+ }
+ else
+ {
+ ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
+ }
+
+ if (ElementStatusPage->VolBits & E2_AVOLTAG)
+ {
+ copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
+ ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
+ }
+ else
+ {
+ ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
+ }
+
+ ElementStatus->DataTransferElementCount++;
+
+ /* 0 actually is a usable element address */
+ /* if (DataTransferElementAddress == 0) */
+ /* FatalError( */
+ /* "illegal Data Transfer Element Address %d reported\n", */
+ /* DataTransferElementAddress); */
+ break;
+
+ default:
+ FatalError("illegal Element Type Code %d reported\n",
+ ElementStatusPage->ElementTypeCode);
+ }
+ }
+ }
+
+#ifdef DEBUG
+ if (pNextElement)
+ fprintf(stderr,"Next start element will be %d\n",*pNextElement);
+#endif
+}
+
+
+/********************* Real ReadElementStatus ********************* */
+
+/*
+ * We no longer do the funky trick to figure out ALLOCATION_LENGTH.
+ * Instead, we use the SCSI Generic command rather than SEND_SCSI_COMMAND
+ * under Linux, which gets around the @#%@ 4k buffer size in Linux.
+ * We still have the restriction that Linux cuts off the last two
+ * bytes of the SENSE DATA (Q#@$%@#$^ Linux!). Which means that the
+ * verbose widget won't work :-(.
+
+ * We now look for that "attached" bit in the inquiry_info to see whether
+ * to use READ_ELEMENT_ATTACHED or plain old READ_ELEMENT. In addition, we
+ * look at the device type in the inquiry_info to see whether it is a media
+ * changer or tape device, and if it's a media changer device, we ignore the
+ * attached bit (one beta tester found an old 4-tape DAT changer that set
+ * the attached bit for both the tape device AND the media changer device).
+
+*/
+
+ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *RequestSense, Inquiry_T *inquiry_info, SCSI_Flags_T *flags)
+{
+ ElementStatus_T *ElementStatus;
+
+ unsigned char *DataBuffer; /* size of data... */
+
+ int EmptyStorageElementCount=0;
+ int *EmptyStorageElementAddress; /* [MAX_STORAGE_ELEMENTS]; */
+
+ int empty_idx = 0;
+ boolean is_attached = false;
+ int i,j;
+
+ ElementModeSense_T *mode_sense = NULL;
+
+ if (inquiry_info->MChngr && inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)
+ {
+ is_attached = true;
+ }
+
+ if (flags->no_attached)
+ {
+ /* override, sigh */
+ is_attached = false;
+ }
+
+ if (!is_attached)
+ {
+ mode_sense = ReadAssignmentPage(MediumChangerFD);
+ }
+
+ if (!mode_sense)
+ {
+ mode_sense = (ElementModeSense_T *)xmalloc(sizeof(ElementModeSense_T));
+ mode_sense->NumMediumTransport = MAX_TRANSPORT_ELEMENTS;
+ mode_sense->NumStorage = MAX_STORAGE_ELEMENTS;
+ mode_sense->NumDataTransfer = MAX_TRANSFER_ELEMENTS;
+ mode_sense->MaxReadElementStatusData =
+ (sizeof(ElementStatusDataHeader_T) + 3 * sizeof(ElementStatusPage_T) +
+ (MAX_STORAGE_ELEMENTS+MAX_TRANSFER_ELEMENTS+MAX_TRANSPORT_ELEMENTS) *
+ sizeof(TransportElementDescriptor_T));
+
+ /* don't care about the others anyhow at the moment... */
+ }
+
+ ElementStatus = AllocateElementData(mode_sense);
+
+ /* Now to initialize it (sigh). */
+ ElementStatus->StorageElementCount = 0;
+ ElementStatus->DataTransferElementCount = 0;
+
+ /* first, allocate some empty storage stuff: Note that we pass this
+ * down to ParseElementStatus (sigh!)
+ */
+
+ EmptyStorageElementAddress = (int *)xzmalloc((mode_sense->NumStorage+1)*sizeof(int));
+ for (i = 0; i < mode_sense->NumStorage; i++)
+ {
+ EmptyStorageElementAddress[i] = -1;
+ }
+
+ /* Okay, now to send some requests for the various types of stuff: */
+
+ /* -----------STORAGE ELEMENTS---------------- */
+ /* Let's start with storage elements: */
+
+ for (i = 0; i < mode_sense->NumDataTransfer; i++)
+ {
+ /* initialize them to an illegal # so that we can fix later... */
+ ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
+ }
+
+ if (flags->querytype == MTX_ELEMENTSTATUS_ORIGINAL)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Using original element status polling method (storage, import/export, drivers etc independantly)\n");
+#endif
+ flags->elementtype = StorageElement; /* sigh! */
+ DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
+ inquiry_info, flags,
+ mode_sense->StorageStart,
+ /* adjust for import/export. */
+ mode_sense->NumStorage - mode_sense->NumImportExport,
+ mode_sense->MaxReadElementStatusData);
+
+ if (!DataBuffer)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Had no elements!\n");
+#endif
+ /* darn. Free up stuff and return. */
+#ifdef DEBUG_MODE_SENSE
+ PrintRequestSense(RequestSense);
+#endif
+ FreeElementData(ElementStatus);
+ return NULL;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Parsing storage elements\n");
+#endif
+ ParseElementStatus(EmptyStorageElementAddress, &EmptyStorageElementCount,
+ DataBuffer,ElementStatus,mode_sense,NULL);
+
+ free(DataBuffer); /* sigh! */
+
+ /* --------------IMPORT/EXPORT--------------- */
+ /* Next let's see if we need to do Import/Export: */
+ if (mode_sense->NumImportExport > 0)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Sending request for Import/Export status\n");
+#endif
+ flags->elementtype = ImportExportElement;
+ DataBuffer = SendElementStatusRequest( MediumChangerFD,RequestSense,
+ inquiry_info, flags,
+ mode_sense->ImportExportStart,
+ mode_sense->NumImportExport,
+ mode_sense->MaxReadElementStatusData);
+
+ if (!DataBuffer)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Had no input/export element!\n");
+#endif
+ /* darn. Free up stuff and return. */
+#ifdef DEBUG_MODE_SENSE
+ PrintRequestSense(RequestSense);
+#endif
+ FreeElementData(ElementStatus);
+ return NULL;
+ }
+#ifdef DEBUG
+ fprintf(stderr,"Parsing inport/export element status\n");
+#endif
+#ifdef DEBUG_ADIC
+ dump_data(DataBuffer, 100); /* dump some data :-(. */
+#endif
+ ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
+ DataBuffer, ElementStatus, mode_sense, NULL);
+
+ ElementStatus->StorageElementCount += ElementStatus->ImportExportCount;
+ }
+
+ /* ----------------- DRIVES ---------------------- */
+
+#ifdef DEBUG
+ fprintf(stderr,"Sending request for data transfer element (drive) status\n");
+#endif
+ flags->elementtype = DataTransferElement; /* sigh! */
+ DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
+ inquiry_info, flags,
+ mode_sense->DataTransferStart,
+ mode_sense->NumDataTransfer,
+ mode_sense->MaxReadElementStatusData);
+ if (!DataBuffer)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"No data transfer element status.");
+#endif
+ /* darn. Free up stuff and return. */
+#ifdef DEBUG_MODE_SENSE
+ PrintRequestSense(RequestSense);
+#endif
+ FreeElementData(ElementStatus);
+ return NULL;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"Parsing data for data transfer element (drive) status\n");
+#endif
+ ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
+ DataBuffer,ElementStatus, mode_sense, NULL);
+
+ free(DataBuffer); /* sigh! */
+
+ /* ----------------- Robot Arm(s) -------------------------- */
+
+ /* grr, damned brain dead HP doesn't report that it has any! */
+ if (!mode_sense->NumMediumTransport)
+ {
+ ElementStatus->TransportElementAddress = 0; /* default it sensibly :-(. */
+ }
+ else
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Sending request for robot arm status\n");
+#endif
+ flags->elementtype = MediumTransportElement; /* sigh! */
+ DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
+ inquiry_info, flags,
+ mode_sense->MediumTransportStart,
+ 1, /* only get 1, sigh. */
+ mode_sense->MaxReadElementStatusData);
+ if (!DataBuffer)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Loader reports no robot arm!\n");
+#endif
+ /* darn. Free up stuff and return. */
+#ifdef DEBUG_MODE_SENSE
+ PrintRequestSense(RequestSense);
+#endif
+ FreeElementData(ElementStatus);
+ return NULL;
+ }
+#ifdef DEBUG
+ fprintf(stderr,"Parsing robot arm data\n");
+#endif
+ ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
+ DataBuffer, ElementStatus, mode_sense, NULL);
+
+ free(DataBuffer);
+ }
+ }
+ else
+ {
+ int nLastEl=-1, nNextEl=0;
+
+#ifdef DEBUG
+ fprintf(stderr,"Using alternative element status polling method (all elements)\n");
+#endif
+ /* ----------------- ALL Elements ---------------------- */
+ /* Just keep asking for elements till no more are returned
+ - increment our starting address as we go acording to the
+ number of elements returned from the last call
+ */
+
+ while(nLastEl!=nNextEl)
+ {
+ flags->elementtype = AllElementTypes;//StorageElement; /* sigh! */ /*XL1B2 firewire changer does not seem to respond to specific types so just use all elements*/
+ DataBuffer = SendElementStatusRequest( MediumChangerFD,
+ RequestSense,
+ inquiry_info,
+ flags,
+ nNextEl,//mode_sense->StorageStart,
+ /* adjust for import/export. */
+ mode_sense->NumStorage - mode_sense->NumImportExport,//FIX ME:this should be a more sensible value
+ mode_sense->MaxReadElementStatusData);
+ if (!DataBuffer)
+ {
+ if (RequestSense->AdditionalSenseCode == 0x21 &&
+ RequestSense->AdditionalSenseCodeQualifier == 0x01)
+ {
+ /* Error is invalid element address, we've probably just hit the end */
+ break;
+ }
+
+ /* darn. Free up stuff and return. */
+ FreeElementData(ElementStatus);
+ return NULL;
+ }
+
+ nLastEl = nNextEl;
+
+ ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
+ DataBuffer, ElementStatus, mode_sense, &nNextEl);
+
+ free(DataBuffer); /* sigh! */
+ }
+
+ ElementStatus->StorageElementCount += ElementStatus->ImportExportCount;
+ }
+
+ /*---------------------- Sanity Checking ------------------- */
+
+ if (ElementStatus->DataTransferElementCount == 0)
+ FatalError("no Data Transfer Element reported\n");
+
+ if (ElementStatus->StorageElementCount == 0)
+ FatalError("no Storage Elements reported\n");
+
+
+ /* ---------------------- Reset SourceStorageElementNumbers ------- */
+
+ /*
+ * Re-write the SourceStorageElementNumber code *AGAIN*.
+ *
+ * Pass1:
+ * Translate from raw element # to our translated # (if possible).
+ * First, check the SourceStorageElementNumbers against the list of
+ * filled slots. If the slots indicated are empty, we accept that list as
+ * valid. Otherwise decide the SourceStorageElementNumbers are invalid.
+ *
+ * Pass2:
+ * If we had some invalid (or unknown) SourceStorageElementNumbers
+ * then we must search for free slots, and assign SourceStorageElementNumbers
+ * to those free slots. We happen to already built a list of free
+ * slots as part of the process of reading the storage element numbers
+ * from the tape. So that's easy enough to do!
+ */
+
+#ifdef DEBUG_TAPELIST
+ fprintf(stderr, "empty slots: %d\n", EmptyStorageElementCount);
+ if (EmptyStorageElementCount)
+ {
+ for (i = 0; i < EmptyStorageElementCount; i++)
+ {
+ fprintf(stderr, "empty: %d\n", EmptyStorageElementAddress[i]);
+ }
+ }
+#endif
+
+ /*
+ * Now we re-assign origin slots if the "real" origin slot
+ * is obviously defective:
+ */
+ /* pass one: */
+ for (i = 0; i < ElementStatus->DataTransferElementCount; i++)
+ {
+ int elnum;
+
+ /* if we have an element, then ... */
+ if (ElementStatus->DataTransferElementFull[i])
+ {
+ elnum = ElementStatus->DataTransferElementSourceStorageElementNumber[i];
+ /* if we have an element number, then ... */
+ if (elnum >= 0)
+ {
+ /* Now to translate the elnum: */
+ ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
+ for (j = 0; j < ElementStatus->StorageElementCount; j++)
+ {
+ if (elnum == ElementStatus->StorageElementAddress[j])
+ {
+ /* now see if the element # is already occupied:*/
+ if (!ElementStatus->StorageElementFull[j])
+ {
+ /* properly set the source... */
+ ElementStatus->DataTransferElementSourceStorageElementNumber[i] = j;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Pass2: */
+ /* We have invalid sources, so let's see what they should be: */
+ /* Note: If EmptyStorageElementCount is < # of drives, the leftover
+ * drives will be assigned a -1 (see the initialization loop for
+ * EmptyStorageElementAddress above), which will be reported as "slot 0"
+ * by the user interface. This is an invalid value, but more useful for us
+ * to have than just crapping out here :-(.
+ */
+ empty_idx=0;
+ for (i = 0; i < ElementStatus->DataTransferElementCount; i++)
+ {
+ if (ElementStatus->DataTransferElementFull[i] &&
+ ElementStatus->DataTransferElementSourceStorageElementNumber[i] < 0)
+ {
+#ifdef DEBUG_TAPELIST
+ fprintf(stderr,"for drive %d, changing to %d (empty slot #%d)\n",
+ i,
+ EmptyStorageElementAddress[empty_idx],
+ empty_idx);
+#endif
+ ElementStatus->DataTransferElementSourceStorageElementNumber[i] =
+ EmptyStorageElementAddress[empty_idx++];
+ }
+ }
+
+ /* and done! */
+ free(mode_sense);
+ free(EmptyStorageElementAddress);
+ return ElementStatus;
+}
+
+/*************************************************************************/
+
+RequestSense_T *PositionElement(DEVICE_TYPE MediumChangerFD,
+ int DestinationAddress,
+ ElementStatus_T *ElementStatus)
+{
+ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T));
+ CDB_T CDB;
+
+ CDB[0] = 0x2b;
+ CDB[1] = 0;
+ CDB[2] = (unsigned char)(ElementStatus->TransportElementAddress >> 8);
+ CDB[3] = (unsigned char)ElementStatus->TransportElementAddress;
+ CDB[4] = (unsigned char)(DestinationAddress >> 8);
+ CDB[5] = (unsigned char)DestinationAddress;
+ CDB[6] = 0;
+ CDB[7] = 0;
+ CDB[8] = 0;
+ CDB[9] = 0;
+
+ if(SCSI_ExecuteCommand( MediumChangerFD, Output, &CDB, 10,
+ NULL, 0, RequestSense) != 0)
+ {
+ return RequestSense;
+ }
+ free(RequestSense);
+ return NULL; /* success */
+}
+
+
+/* Now the actual media movement routine! */
+RequestSense_T *MoveMedium( DEVICE_TYPE MediumChangerFD, int SourceAddress,
+ int DestinationAddress,
+ ElementStatus_T *ElementStatus,
+ Inquiry_T *inquiry_info, SCSI_Flags_T *flags)
+{
+ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T));
+ CDB_T CDB;
+
+ if (inquiry_info->MChngr && inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)
+ {
+ /* if using the ATTACHED API */
+ CDB[0] = 0xA7; /* MOVE_MEDIUM_ATTACHED */
+ }
+ else
+ {
+ CDB[0] = 0xA5; /* MOVE MEDIUM */
+ }
+
+ CDB[1] = 0; /* Reserved */
+
+ /* Transport Element Address */
+ CDB[2] = (unsigned char)(ElementStatus->TransportElementAddress >> 8);
+ CDB[3] = (unsigned char)ElementStatus->TransportElementAddress;
+
+ /* Source Address */
+ CDB[4] = (unsigned char)(SourceAddress >> 8);
+ CDB[5] = (unsigned char)SourceAddress;
+
+ /* Destination Address */
+ CDB[6] = (unsigned char)(DestinationAddress >> 8);
+ CDB[7] = (unsigned char)DestinationAddress;
+
+ CDB[8] = 0; /* Reserved */
+ CDB[9] = 0; /* Reserved */
+
+ if (flags->invert)
+ {
+ CDB[10] = 1; /* Reserved */
+ }
+ else
+ {
+ CDB[10] = 0;
+ }
+ /* eepos controls the tray for import/export elements, sometimes. */
+ CDB[11] = flags->eepos << 6; /* Control */
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
+ NULL, 0, RequestSense) != 0)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "Move Medium (0x%02X) failed\n", CDB[0]);
+#endif
+ return RequestSense;
+ }
+
+ free(RequestSense);
+ return NULL; /* success! */
+}
+
+
+/* Now the actual Exchange Medium routine! */
+RequestSense_T *ExchangeMedium( DEVICE_TYPE MediumChangerFD, int SourceAddress,
+ int DestinationAddress, int Dest2Address,
+ ElementStatus_T *ElementStatus,
+ SCSI_Flags_T *flags)
+{
+ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T));
+ CDB_T CDB;
+
+ CDB[0] = 0xA6; /* EXCHANGE MEDIUM */
+ CDB[1] = 0; /* Reserved */
+
+ /* Transport Element Address */
+ CDB[2] = (unsigned char)(ElementStatus->TransportElementAddress >> 8);
+ CDB[3] = (unsigned char)ElementStatus->TransportElementAddress;
+
+ /* Source Address */
+ CDB[4] = (unsigned char)(SourceAddress >> 8);
+ CDB[5] = (unsigned char)SourceAddress;
+
+ /* Destination Address */
+ CDB[6] = (unsigned char)(DestinationAddress >> 8);
+ CDB[7] = (unsigned char)DestinationAddress;
+
+ /* move destination back to source? */
+ CDB[8] = (unsigned char)(Dest2Address >> 8);
+ CDB[9] = (unsigned char)Dest2Address;
+ CDB[10] = 0;
+
+ if (flags->invert)
+ {
+ CDB[10] |= 2; /* INV2 */
+ }
+
+ if (flags->invert2)
+ {
+ CDB[1] |= 1; /* INV1 */
+ }
+
+ /* eepos controls the tray for import/export elements, sometimes. */
+ CDB[11] = flags->eepos << 6; /* Control */
+
+#ifdef DEBUG_EXCHANGE
+ dump_cdb(&CDB,12);
+#endif
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
+ NULL, 0, RequestSense) != 0)
+ {
+ return RequestSense;
+ }
+ free(RequestSense);
+ return NULL; /* success! */
+}
+
+
+/*
+ * for Linux, this creates a way to do a short erase... the @#$%@ st.c
+ * driver defaults to doing a long erase!
+ */
+
+RequestSense_T *Erase(DEVICE_TYPE MediumChangerFD)
+{
+ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T));
+ CDB_T CDB;
+
+ CDB[0] = 0x19;
+ CDB[1] = 0; /* Short! */
+ CDB[2] = CDB[3] = CDB[4] = CDB[5] = 0;
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6, NULL, 0, RequestSense) != 0)
+ {
+ /* If error is UNIT ATTENTION then retry the request */
+ if (RequestSense->ErrorCode != 0x70 || RequestSense->SenseKey != 6 ||
+ ClearUnitAttention(MediumChangerFD, RequestSense) != 0 ||
+ SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6, NULL, 0, RequestSense) != 0)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "Erase (0x19) failed\n");
+#endif
+ return RequestSense;
+ }
+ }
+
+ free(RequestSense);
+ return NULL; /* Success! */
+}
+
+/* Routine to send an LOAD/UNLOAD from the MMC/SSC spec to a device.
+ * For tapes and changers this can be used either to eject a tape
+ * or to eject a magazine (on some Seagate changers, when sent to LUN 1 ).
+ * For CD/DVDs this is used to Load or Unload a disc which is required by
+ * some media changers.
+ */
+
+int LoadUnload(DEVICE_TYPE fd, int bLoad)
+{
+ CDB_T CDB;
+ /* okay, now for the command: */
+
+ CDB[0] = 0x1B;
+ CDB[4] = bLoad ? 3 : 2;
+ CDB[1] = CDB[2] = CDB[3] = CDB[5] = 0;
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, NULL, 0, &scsi_error_sense) != 0)
+ {
+ /* If error is UNIT ATTENTION then retry the request */
+ if (scsi_error_sense.ErrorCode != 0x70 || scsi_error_sense.SenseKey != 6 ||
+ ClearUnitAttention(fd, &scsi_error_sense) != 0 ||
+ SCSI_ExecuteCommand(fd, Input, &CDB, 6, NULL, 0, &scsi_error_sense) != 0)
+ {
+ PrintRequestSense(&scsi_error_sense);
+ fprintf(stderr, "Eject (0x1B) failed\n");
+ return -1; /* could not do! */
+ }
+ }
+ return 0; /* did do! */
+}
+
+/* Routine to send an START/STOP from the MMC/SSC spec to a device.
+ * For tape drives this may be required prior to using the changer
+ * Load or Unload commands.
+ * For CD/DVD drives this is used to Load or Unload a disc which may be
+ * required by some media changers.
+ */
+
+int StartStop(DEVICE_TYPE fd, int bStart)
+{
+ CDB_T CDB;
+ /* okay, now for the command: */
+
+ CDB[0] = 0x1B;
+ CDB[4] = bStart ? 1 : 0;
+ CDB[1] = CDB[2] = CDB[3] = CDB[5] = 0;
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,NULL, 0, &scsi_error_sense) != 0)
+ {
+ PrintRequestSense(&scsi_error_sense);
+ fprintf(stderr, "Eject (0x1B) failed\n");
+ return -1; /* could not do! */
+ }
+ return 0; /* did do! */
+}
+
+/* Routine to send a LOCK/UNLOCK from the SSC/MMC spec to a device.
+ * This can be used to prevent or allow the Tape or CD/DVD from being
+ * removed.
+ */
+
+int LockUnlock(DEVICE_TYPE fd, int bLock)
+{
+ CDB_T CDB;
+ /* okay, now for the command: */
+
+ CDB[0] = 0x1E;
+ CDB[1] = CDB[2] = CDB[3] = CDB[5] = 0;
+ CDB[4] = (char)bLock;
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, NULL, 0, &scsi_error_sense) != 0)
+ {
+ PrintRequestSense(&scsi_error_sense);
+ fprintf(stderr, "Lock/Unlock (0x1E) failed\n");
+ return -1; /* could not do! */
+ }
+ return 0; /* did do! */
+}
+
+int ClearUnitAttention(DEVICE_TYPE fd, RequestSense_T *RequestSense)
+{
+ CDB_T CDB;
+ int RetryCount = 10; /* Unit Attentions may be stacked */
+ RequestSense_T unit_attention_sense;
+
+ CDB[0] = 0x03; /* Request Sense */
+ CDB[4] = (char)sizeof(*RequestSense);
+ CDB[1] = CDB[2] = CDB[3] = CDB[5] = 0;
+
+ while (RetryCount-- > 0)
+ {
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,
+ &unit_attention_sense, sizeof(unit_attention_sense),
+ RequestSense) != 0)
+ {
+ fprintf(stderr, "RequestSense (0x03) failed\n");
+ return -1; /* could not do! */
+ }
+
+ if (unit_attention_sense.SenseKey == 0)
+ {
+ /* If SenseKey is NO SENSE then we are done. */
+ return 0;
+ }
+ }
+ return -1; /* did do! */
+
+}
+
+static char Spaces[] = " ";
+
+void PrintHex(int Indent, unsigned char *Buffer, int Length)
+{
+ int idxBuffer;
+ int idxAscii;
+ int PadLength;
+ char cAscii;
+
+ for (idxBuffer = 0; idxBuffer < Length; idxBuffer++)
+ {
+ if ((idxBuffer % 16) == 0)
+ {
+ if (idxBuffer > 0)
+ {
+ fputc('\'', stderr);
+
+ for (idxAscii = idxBuffer - 16; idxAscii < idxBuffer; idxAscii++)
+ {
+ cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x7F ? Buffer[idxAscii] : '.';
+ fputc(cAscii, stderr);
+ }
+ fputs("'\n", stderr);
+ }
+ fprintf(stderr, "%.*s%04X: ", Indent, Spaces, idxBuffer);
+ }
+ fprintf(stderr, "%02X ", (unsigned char)Buffer[idxBuffer]);
+ }
+
+ PadLength = 16 - (Length % 16);
+
+ if (PadLength > 0)
+ {
+ fprintf(stderr, "%.*s'", 3 * PadLength, Spaces);
+
+ for (idxAscii = idxBuffer - (16 - PadLength); idxAscii < idxBuffer; idxAscii++)
+ {
+ cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x80 ? Buffer[idxAscii] : '.';
+ fputc(cAscii, stderr);
+ }
+ fputs("'\n", stderr);
+ }
+
+ fflush(stderr);
+}
+
+static char *sense_keys[] =
+{
+ "No Sense", /* 00 */
+ "Recovered Error", /* 01 */
+ "Not Ready", /* 02 */
+ "Medium Error", /* 03 */
+ "Hardware Error", /* 04 */
+ "Illegal Request", /* 05 */
+ "Unit Attention", /* 06 */
+ "Data Protect", /* 07 */
+ "Blank Check", /* 08 */
+ "0x09", /* 09 */
+ "0x0a", /* 0a */
+ "Aborted Command", /* 0b */
+ "0x0c", /* 0c */
+ "Volume Overflow", /* 0d */
+ "Miscompare", /* 0e */
+ "0x0f" /* 0f */
+};
+
+static char Yes[] = "yes";
+static char No[] = "no";
+
+void PrintRequestSense(RequestSense_T *RequestSense)
+{
+ char *msg;
+
+ fprintf(stderr, "mtx: Request Sense: Long Report=yes\n");
+ fprintf(stderr, "mtx: Request Sense: Valid Residual=%s\n", RequestSense->Valid ? Yes : No);
+
+ if (RequestSense->ErrorCode == 0x70)
+ {
+ msg = "Current" ;
+ }
+ else if (RequestSense->ErrorCode == 0x71)
+ {
+ msg = "Deferred" ;
+ }
+ else
+ {
+ msg = "Unknown?!" ;
+ }
+
+ fprintf(stderr, "mtx: Request Sense: Error Code=%0x (%s)\n", RequestSense->ErrorCode, msg);
+ fprintf(stderr, "mtx: Request Sense: Sense Key=%s\n", sense_keys[RequestSense->SenseKey]);
+ fprintf(stderr, "mtx: Request Sense: FileMark=%s\n", RequestSense->Filemark ? Yes : No);
+ fprintf(stderr, "mtx: Request Sense: EOM=%s\n", RequestSense->EOM ? Yes : No);
+ fprintf(stderr, "mtx: Request Sense: ILI=%s\n", RequestSense->ILI ? Yes : No);
+
+ if (RequestSense->Valid)
+ {
+ fprintf(stderr, "mtx: Request Sense: Residual = %02X %02X %02X %02X\n",RequestSense->Information[0],RequestSense->Information[1],RequestSense->Information[2],RequestSense->Information[3]);
+ }
+
+ fprintf(stderr,"mtx: Request Sense: Additional Sense Code = %02X\n", RequestSense->AdditionalSenseCode);
+ fprintf(stderr,"mtx: Request Sense: Additional Sense Qualifier = %02X\n", RequestSense->AdditionalSenseCodeQualifier);
+
+ if (RequestSense->SKSV)
+ {
+ fprintf(stderr,"mtx: Request Sense: Field in Error = %02X\n", RequestSense->BitPointer);
+ }
+
+ fprintf(stderr, "mtx: Request Sense: BPV=%s\n", RequestSense->BPV ? Yes : No);
+ fprintf(stderr, "mtx: Request Sense: Error in CDB=%s\n", RequestSense->CommandData ? Yes : No);
+ fprintf(stderr, "mtx: Request Sense: SKSV=%s\n", RequestSense->SKSV ? Yes : No);
+
+ if (RequestSense->BPV || RequestSense -> SKSV)
+ {
+ fprintf(stderr, "mtx: Request Sense: Field Pointer = %02X %02X\n",
+ RequestSense->FieldData[0], RequestSense->FieldData[1]);
+ }
+
+ fflush(stderr);
+}
diff --git a/mtxl.h b/mtxl.h
new file mode 100644
index 0000000..073f4fa
--- /dev/null
+++ b/mtxl.h
@@ -0,0 +1,109 @@
+/*
+ MTX -- SCSI Tape Attached Medium Changer Control Program
+
+ Copyright 1997-1998 Leonard N. Zubkoff <lnz@dandelion.com>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+ This file created by Eric Lee Green <eric@badtux.org>
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+ $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+ $Revision: 193 $
+*/
+
+/* Much of the guts of mtx.c has been extracted to mtxl.c, a library file
+ * full of utility routines. This file is the header file for that library.
+ * -E
+ */
+
+#ifndef MTXL_H
+#define MTXL_H 1
+
+#include "mtx.h"
+
+#undef min
+#undef max
+
+void FatalError(char *ErrorMessage, ...);
+void *xmalloc(size_t Size);
+void *xzmalloc(size_t Size);
+void slow_bzero(char *buffer, int numchars);
+
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName);
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD);
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense);
+
+void PrintRequestSense(RequestSense_T *RequestSense);
+
+int BigEndian16(unsigned char *BigEndianData);
+int BigEndian24(unsigned char *BigEndianData);
+int min(int x, int y);
+int max(int x, int y);
+
+void PrintHex(int Indent, unsigned char *Buffer, int Length);
+int ClearUnitAttention(DEVICE_TYPE fd, RequestSense_T *RequestSense);
+
+ElementStatus_T *ReadElementStatus( DEVICE_TYPE MediumChangerFD,
+ RequestSense_T *RequestSense,
+ Inquiry_T *inquiry_info,
+ SCSI_Flags_T *flags);
+
+Inquiry_T *RequestInquiry( DEVICE_TYPE fd,
+ RequestSense_T *RequestSense);
+
+RequestSense_T *MoveMedium( DEVICE_TYPE MediumChangerFD,
+ int SourceAddress,
+ int DestinationAddress,
+ ElementStatus_T *ElementStatus,
+ Inquiry_T *inquiry_info,
+ SCSI_Flags_T *flags);
+
+RequestSense_T *ExchangeMedium( DEVICE_TYPE MediumChangerFD,
+ int SourceAddress,
+ int DestinationAddress,
+ int Dest2Address,
+ ElementStatus_T *ElementStatus,
+ SCSI_Flags_T *flags);
+
+RequestSense_T *PositionElement(DEVICE_TYPE MediumChangerFD,
+ int DestinationAddress,
+ ElementStatus_T *ElementStatus);
+
+int Inventory(DEVICE_TYPE MediumChangerFD); /* inventory library */
+int LoadUnload(DEVICE_TYPE fd, int bLoad); /* load/unload tape, magazine or disc */
+int StartStop(DEVICE_TYPE fd, int bStart); /* start/stop device */
+int LockUnlock(DEVICE_TYPE fd, int bLock); /* lock/unlock medium in device */
+RequestSense_T *Erase(DEVICE_TYPE fd); /* send SHORT erase to drive */
+
+void SCSI_Set_Timeout(int secs); /* set the SCSI timeout */
+void SCSI_Default_Timeout(void); /* go back to default timeout */
+
+/* we may not have this function :-(. */
+#ifdef HAVE_GET_ID_LUN
+ scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd);
+#endif
+
+/* These two hacks are so that I can stick the tongue out on an
+ * NSM optical jukebox.
+ */
+NSM_Result_T *RecNSMHack(DEVICE_TYPE MediumChangerFD,
+ int param_len, int timeout);
+
+int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
+ int param_len, int timeout);
+
+#endif
+
diff --git a/nsmhack.c b/nsmhack.c
new file mode 100644
index 0000000..b2ac2c2
--- /dev/null
+++ b/nsmhack.c
@@ -0,0 +1,342 @@
+/* Copyright 2001 DISC Inc.
+ * Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+ * Released under terms of the GNU General Public License as required
+ * by the license on the file "mtxl.c". See file "LICENSE" for details.
+ */
+
+#define DEBUG_NSM 1
+
+/* This is a hack to make the NSM modular series jukeboxes stick out
+ * their tongue, then retract tongue, so we can import media. They
+ * automatically stick out their tongue when exporting media, but
+ * importing media is not working, you try to do a MOVE_MEDIUM and
+ * it says "What medium?" before even sticking out its tongue.
+ * My manager has turned in a change request to NSM engineering to direct
+ * their firmware guys to add EEPOS support to the NSM modular jukeboxes so
+ * that we have tongue firmware that's compatible with Exabyte, Sony, Breece
+ * Hill, etc., but until that new firmware is here, this hack will work.
+ */
+
+/* Note: Perhaps "hack" is an overstatement, since this will also
+ * eventually add pack management and other things of that nature
+ * that are extremely loader dependent.
+ */
+
+/* Commands:
+ -f <devicenode>
+ tongue_out <sourceslot>
+ tongue_in
+ tongue_button_wait
+ tongue_button_enable
+ tongue_button_disable
+*/
+
+
+#include "mtxl.h" /* get the SCSI routines out of the main file */
+
+/****************************************************************/
+/* Variables: */
+/****************************************************************/
+
+/* the device handle we're operating upon, sigh. */
+static char *device; /* the text of the device thingy. */
+static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) -1;
+char *argv0;
+int arg[4]; /* arguments for the command. */
+#define arg1 (arg[0]) /* for backward compatibility, sigh */
+static SCSI_Flags_T SCSI_Flags = { 0, 0, 0,0 };
+
+static ElementStatus_T *ElementStatus = NULL;
+
+/* Okay, now let's do the main routine: */
+
+void Usage(void) {
+ FatalError("Usage: nsmhack -f <generic-device> <command> where <command> is:\n [tongue_out] | [tongue_in] | [tongue_button_wait] | [tongue_button_enable]\n | tongue_button_disable. \n");
+}
+
+static int S_tongue_out(void);
+static int S_tongue_in(void);
+static int S_slotinfo(void);
+static int S_jukeinfo(void);
+
+struct command_table_struct {
+ int num_args;
+ char *name;
+ int (*command)(void);
+} command_table[] = {
+ { 1, "tongue_out", S_tongue_out },
+ { 0, "tongue_in", S_tongue_in },
+ { 0, "slotinfo", S_slotinfo },
+ { 0, "jukeinfo", S_jukeinfo },
+ { 0, NULL, NULL }
+};
+
+
+/* open_device() -- set the 'fh' variable.... */
+void open_device(void) {
+
+ if (MediumChangerFD != -1) {
+ SCSI_CloseDevice("Unknown",MediumChangerFD); /* close it, sigh... new device now! */
+ }
+
+ MediumChangerFD = SCSI_OpenDevice(device);
+
+}
+
+static int get_arg(char *arg) {
+ int retval=-1;
+
+ if (*arg < '0' || *arg > '9') {
+ return -1; /* sorry! */
+ }
+
+ retval=atoi(arg);
+ return retval;
+}
+
+/* we see if we've got a file open. If not, we open one :-(. Then
+ * we execute the actual command. Or not :-(.
+ */
+int execute_command(struct command_table_struct *command) {
+
+ /* if the device is not already open, then open it from the
+ * environment.
+ */
+ if (MediumChangerFD == -1) {
+ /* try to get it from STAPE or TAPE environment variable... */
+ device=getenv("STAPE");
+ if (device==NULL) {
+ device=getenv("TAPE");
+ if (device==NULL) {
+ Usage();
+ }
+ }
+ open_device();
+ }
+
+
+ /* okay, now to execute the command... */
+ return command->command();
+}
+
+/* parse_args():
+ * Basically, we are parsing argv/argc. We can have multiple commands
+ * on a line now, such as "unload 3 0 load 4 0" to unload one tape and
+ * load in another tape into drive 0, and we execute these commands one
+ * at a time as we come to them. If we don't have a -f at the start, we
+ * barf. If we leave out a drive #, we default to drive 0 (the first drive
+ * in the cabinet).
+ */
+
+int parse_args(int argc,char **argv) {
+ int i,cmd_tbl_idx,retval,arg_idx;
+ struct command_table_struct *command;
+
+ i=1;
+ arg_idx=0;
+ while (i<argc) {
+ if (strcmp(argv[i],"-f") == 0) {
+ i++;
+ if (i>=argc) {
+ Usage();
+ }
+ device=argv[i++];
+ open_device(); /* open the device and do a status scan on it... */
+ } else {
+ cmd_tbl_idx=0;
+ command=&command_table[0]; /* default to the first command... */
+ command=&command_table[cmd_tbl_idx];
+ while (command->name) {
+ if (!strcmp(command->name,argv[i])) {
+ /* we have a match... */
+ break;
+ }
+ /* otherwise we don't have a match... */
+ cmd_tbl_idx++;
+ command=&command_table[cmd_tbl_idx];
+ }
+ /* if it's not a command, exit.... */
+ if (!command->name) {
+ Usage();
+ }
+ i++; /* go to the next argument, if possible... */
+ /* see if we need to gather arguments, though! */
+ arg1=-1; /* default it to something */
+ for (arg_idx=0;arg_idx < command->num_args ; arg_idx++) {
+ if (i < argc) {
+ arg[arg_idx]=get_arg(argv[i]);
+ if (arg[arg_idx] != -1) {
+ i++; /* increment i over the next cmd. */
+ }
+ } else {
+ arg[arg_idx]=0; /* default to 0 setmarks or whatever */
+ }
+ }
+ retval=execute_command(command); /* execute_command handles 'stuff' */
+ exit(retval);
+ }
+ }
+ return 0; /* should never get here */
+}
+
+static void init_param(NSM_Param_T *param, char *command, int paramlen, int resultlen) {
+ int i;
+
+ /* zero it out first: */
+ memset((char *)param,0,sizeof(NSM_Param_T));
+
+ resultlen=resultlen+sizeof(NSM_Result_T)-0xffff;
+
+
+ param->page_code=0x80;
+ param->reserved=0;
+ param->page_len_msb=((paramlen+8)>>8) & 0xff;
+ param->page_len_lsb=(paramlen+8) & 0xff;
+ param->allocation_msb=((resultlen + 10) >> 8) & 0xff;
+ param->allocation_lsb= (resultlen+10) & 0xff;
+ param->reserved2[0]=0;
+ param->reserved2[1]=0;
+
+ for (i=0;i<4;i++) {
+ param->command_code[i]=command[i];
+ }
+
+}
+
+static NSM_Result_T *SendRecHack(NSM_Param_T *param,int param_len,
+ int read_len) {
+ NSM_Result_T *result;
+ /* send the command: */
+ if (SendNSMHack(MediumChangerFD,param,param_len,0)) {
+ PrintRequestSense(&scsi_error_sense);
+ FatalError("SendNSMHack failed.\n");
+ }
+
+ /* Now read the result: */
+ result=RecNSMHack(MediumChangerFD,read_len,0);
+ if (!result) {
+ PrintRequestSense(&scsi_error_sense);
+ FatalError("RecNSMHack failed.\n");
+ }
+
+ return result;
+}
+
+
+/* Print some info about the NSM jukebox. */
+static int S_jukeinfo(void) {
+ NSM_Result_T *result;
+ NSM_Param_T param;
+
+ if (!device)
+ Usage();
+
+ /* okay, we have a device: Let's get vendor ID: */
+ init_param(&param,"1010",0,8);
+ result=SendRecHack(&param,0,8);
+ /* Okay, we got our result, print out the vendor ID: */
+ result->return_data[8]=0;
+ printf("Vendor ID: %s\n",result->return_data);
+ free(result);
+
+ /* Get our product ID: */
+ init_param(&param,"1011",0,16);
+ result=SendRecHack(&param,0,16);
+ result->return_data[16]=0;
+ printf("Product ID: %s\n",result->return_data);
+ free(result);
+
+ init_param(&param,"1012",0,4);
+ result=SendRecHack(&param,0,4);
+ result->return_data[4]=0;
+ printf("Product Revision: %s\n",result->return_data);
+ free(result);
+
+ init_param(&param,"1013",0,8);
+ result=SendRecHack(&param,0,8);
+ result->return_data[8]=0;
+ printf("Production Date: %s\n",result->return_data);
+ free(result);
+
+ init_param(&param,"1014",0,8);
+ result=SendRecHack(&param,0,8);
+ result->return_data[8]=0;
+ printf("Part Number: %s\n",result->return_data);
+ free(result);
+
+ init_param(&param,"1015",0,12);
+ result=SendRecHack(&param,0,12);
+ result->return_data[12]=0;
+ printf("Serial Number: %s\n",result->return_data);
+ free(result);
+
+ init_param(&param,"1016",0,4);
+ result=SendRecHack(&param,0,4);
+ result->return_data[4]=0;
+ printf("Firmware Release: %s\n",result->return_data);
+ free(result);
+
+ init_param(&param,"1017",0,8);
+ result=SendRecHack(&param,0,8);
+ result->return_data[8]=0;
+ printf("Firmware Date: %s\n",result->return_data);
+ free(result);
+
+ return 0;
+}
+
+static int S_slotinfo(void) {
+ NSM_Result_T *result;
+ NSM_Param_T param;
+
+ if (!device)
+ Usage();
+
+ /* Okay, let's see what I can get from slotinfo: */
+ init_param(&param,"1020",0,6);
+ result=SendRecHack(&param,0,6);
+ result->return_data[6]=0;
+ printf("Layout: %s\n",result->return_data);
+ free(result);
+
+ return 0;
+}
+
+static int S_tongue_in(void) {
+ return 0;
+}
+
+/* okay, stick our tongue out. We need a slot ID to grab a caddy from. */
+static int S_tongue_out(void) {
+ int slotnum=arg1;
+ Inquiry_T *inquiry_info; /* needed by MoveMedium etc... */
+ RequestSense_T RequestSense;
+
+ /* see if we have element status: */
+ if (ElementStatus==NULL) {
+ inquiry_info=RequestInquiry(MediumChangerFD,&RequestSense);
+ if (!inquiry_info) {
+ PrintRequestSense(&RequestSense);
+ FatalError("INQUIRY Command Failed\n");
+ }
+ ElementStatus = ReadElementStatus(MediumChangerFD,&RequestSense,inquiry_info,&SCSI_Flags);
+ if (!ElementStatus) {
+ PrintRequestSense(&RequestSense);
+ FatalError("READ ELEMENT STATUS Command Failed\n");
+ }
+ }
+
+ /* Okay, we have element status, so now let's assume that */
+ return 0;
+}
+
+/* See parse_args for the scoop. parse_args does all. */
+int main(int argc, char **argv) {
+ argv0=argv[0];
+ parse_args(argc,argv);
+
+ if (device)
+ SCSI_CloseDevice(device,MediumChangerFD);
+
+ exit(0);
+}
diff --git a/scsi_aix.c b/scsi_aix.c
new file mode 100644
index 0000000..4b77fa6
--- /dev/null
+++ b/scsi_aix.c
@@ -0,0 +1,159 @@
+/* Changes 2003 Steve Heck <steve.heck@am.sony.com>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+*/
+
+
+/* This is the SCSI commands for AIX using GSC Generic SCSI Interface. */
+
+#define LONG_PRINT_REQUEST_SENSE /* sigh! */
+
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ int DeviceFD = open(DeviceName, 0);
+
+ if (DeviceFD < 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ if (close(DeviceFD) < 0)
+ FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
+}
+
+
+#define HAS_SCSI_TIMEOUT
+
+static int timeout = 9 * 60;
+
+void SCSI_Set_Timeout(int to)
+{
+ timeout = to;
+}
+
+void SCSI_Default_Timeout(void)
+{
+ timeout = 9 * 60; /* the default */
+}
+
+#ifdef DEBUG
+int SCSI_DumpBuffer(int DataBufferLength, unsigned char *DataBuffer)
+{
+ int i, j;
+ j = 0;
+
+ for (i = 0; i < DataBufferLength; i++)
+ {
+ if (j == 25)
+ {
+ fprintf(stderr, "\n");
+ j = 0;
+ }
+
+ if (j == 0)
+ {
+ fprintf(stderr, "%04x:", i);
+ }
+
+ if (j > 0)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "%02x", (int)DataBuffer[i]);
+ j++;
+ }
+ fprintf(stderr, "\n");
+}
+#endif
+
+
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ int ioctl_result;
+ char sbyte;
+ scmd_t scmd;
+
+#ifdef DEBUG_SCSI
+ fprintf(stderr,"------CDB--------\n");
+ SCSI_DumpBuffer(CDB_Length,(char *)CDB);
+#endif
+
+ /* memset(&scmd, 0, sizeof(struct scmd_t)); */
+ /* memset(RequestSense, 0, sizeof(RequestSense_T)); */
+ switch (Direction)
+ {
+ case Input:
+ scmd.rw = 1;
+ if (DataBufferLength > 0)
+ {
+ memset(DataBuffer, 0, DataBufferLength);
+ }
+ break;
+
+ case Output:
+ scmd.rw = 2;
+ break;
+ }
+ /* Set timeout to 5 minutes. */
+#ifdef DEBUG_TIMEOUT
+ fprintf(stderr,"timeout=%d\n",timeout);
+ fflush(stderr);
+#endif
+
+ scmd.timeval = timeout;
+
+ scmd.cdb = (caddr_t) CDB;
+ scmd.cdblen = CDB_Length;
+ scmd.data_buf = DataBuffer;
+ scmd.datalen = DataBufferLength;
+ scmd.sense_buf = (caddr_t) RequestSense;
+ scmd.senselen = sizeof(RequestSense_T);
+ scmd.statusp = &sbyte;
+ ioctl_result = ioctl(DeviceFD, GSC_CMD, (caddr_t) &scmd);
+
+ SCSI_Default_Timeout(); /* set it back to default, sigh. */
+
+ if (ioctl_result < 0)
+ {
+#ifdef DEBUG
+ perror("mtx");
+#endif
+ return ioctl_result;
+ }
+
+ if (sbyte != 0)
+ {
+ return -1;
+ }
+#ifdef DEBUG_SCSI
+ if (Direction==Input)
+ {
+ fprintf(stderr,"--------input data-----------\n");
+ SCSI_DumpBuffer(DataBufferLength,DataBuffer);
+ }
+#endif
+ return 0;
+}
diff --git a/scsi_freebsd.c b/scsi_freebsd.c
new file mode 100644
index 0000000..4a085ec
--- /dev/null
+++ b/scsi_freebsd.c
@@ -0,0 +1,116 @@
+/* Copyright 2000 Enhanced Software Technologies Inc. (http://www.estinc.com)
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+ Written by Eric Lee Green <eric@badtux.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+*/
+
+/* This is the SCSI commands for FreeBSD */
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ struct cam_device *DeviceFD = cam_open_pass(DeviceName, O_RDWR | O_EXCL, NULL);
+ if (DeviceFD == 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ cam_close_device((struct cam_device *) DeviceFD);
+}
+
+#define PASS_HZ 1000*60
+#define PASS_DEFAULT_TIMEOUT 5*PASS_HZ
+static int pass_timeout = PASS_DEFAULT_TIMEOUT;
+
+void SCSI_Set_Timeout(int secs)
+{
+ pass_timeout=secs*PASS_HZ;
+}
+
+void SCSI_Default_Timeout(void) {
+ pass_timeout=5*PASS_HZ;
+}
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ struct cam_device *dsp = (struct cam_device *) DeviceFD;
+ int retval;
+ union ccb *ccb;
+ CDB_T *cdb;
+ int Result;
+
+ ccb = cam_getccb(dsp);
+ cdb = (CDB_T *) &ccb->csio.cdb_io.cdb_bytes; /* pointer to actual cdb. */
+
+ /* cam_getccb() zeros the CCB header only. So now clear the
+ * payload portion of the ccb.
+ */
+ bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
+
+ /* copy the CDB... */
+ memcpy(cdb,CDB,CDB_Length);
+
+ /* set the command control block stuff.... the rather involved
+ * conditional expression sets the direction to NONE if there is no
+ * data to go in or out, and IN or OUT if we want data. Movement
+ * commands will have no data buffer, just a CDB, while INQUIRY and
+ * READ_ELEMENT_STATUS will have input data, and we don't have any
+ * stuff that outputs data -- yet -- but we may eventually.
+ */
+ cam_fill_csio( &ccb->csio,
+ 1, /* retries */
+ NULL, /* cbfcnp*/
+ (DataBufferLength ?
+ (Direction == Input ? CAM_DIR_IN : CAM_DIR_OUT) :
+ CAM_DIR_NONE), /* flags */
+ MSG_SIMPLE_Q_TAG, /* tag action */
+ DataBuffer, /* data ptr */
+ DataBufferLength, /* xfer_len */
+ SSD_FULL_SIZE, /* sense_len */
+ CDB_Length, /* cdb_len */
+ pass_timeout /* timeout */ /* should be 5 minutes or more?! */
+ );
+
+ pass_timeout = PASS_DEFAULT_TIMEOUT; /* make sure it gets reset. */
+ memset(RequestSense, 0, sizeof(RequestSense_T)); /* clear sense buffer... */
+
+ if (Direction == Input)
+ {
+ memset(DataBuffer, 0, DataBufferLength);
+ }
+
+ Result = cam_send_ccb(DeviceFD,ccb);
+ if (Result < 0 ||
+ (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ {
+ /* copy our sense data, sigh... */
+ memcpy(RequestSense,(void *) &ccb->csio.sense_data,
+ min(sizeof(RequestSense_T), sizeof(struct scsi_sense_data)));
+
+ cam_freeccb(ccb);
+ return -1; /* sorry! */
+ }
+
+ /* okay, we did good, maybe? */
+ cam_freeccb(ccb);
+ return 0; /* and done? */
+}
diff --git a/scsi_hpux.c b/scsi_hpux.c
new file mode 100644
index 0000000..880ce2c
--- /dev/null
+++ b/scsi_hpux.c
@@ -0,0 +1,134 @@
+/* Copyright 1997, 1998 Leonard Zubkoff <lnz@dandelion.com>
+ Changes copyright 2000 Eric Green <eric@badtux.org>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+struct sctl_io
+{
+ unsigned flags; // IN: SCTL_READ
+ unsigned cdb_length; // IN
+ unsigned char cdb[16]; // IN
+ void *data; // IN
+ unsigned data_length; // IN
+ unsigned max_msecs; // IN: milli-seconds before abort
+ unsigned data_xfer; // OUT
+ unsigned cdb_status; // OUT: SCSI status
+ unsigned char sense[256]; // OUT
+ unsigned sense_status; // OUT: SCSI status
+ unsigned sense_xfer; // OUT: bytes of sense data received
+ unsigned reserved[16]; // IN: Must be zero; OUT: undefined
+};
+
+*/
+
+
+/* Hockey Pux may define these. If so, *UN*define them. */
+#ifdef ILI
+#undef ILI
+#endif
+
+#ifdef EOM
+#undef EOM
+#endif
+
+/* This is the SCSI commands for HPUX. */
+
+#define LONG_PRINT_REQUEST_SENSE /* Sigh! */
+
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ int DeviceFD = open(DeviceName, O_RDWR | O_NDELAY);
+
+ if (DeviceFD < 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ if (close(DeviceFD) < 0)
+ FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
+}
+
+#define MTX_HZ 1000
+#define DEFAULT_HZ (5*60*MTX_HZ)
+
+static int sctl_io_timeout=DEFAULT_HZ; /* default timeout is 5 minutes. */
+
+
+void SCSI_Set_Timeout(int to)
+{
+ sctl_io_timeout=to*60*MTX_HZ;
+}
+
+void SCSI_Default_Timeout(void)
+{
+ sctl_io_timeout=DEFAULT_HZ;
+}
+
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ int ioctl_result;
+ struct sctl_io Command;
+
+ int i;
+
+ memset(&Command, 0, sizeof(struct sctl_io));
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+
+ switch (Direction)
+ {
+ case Input:
+ if (DataBufferLength > 0)
+ memset(DataBuffer, 0, DataBufferLength);
+ Command.flags = SCTL_READ | SCTL_INIT_SDTR;
+ break;
+
+ case Output:
+ Command.flags = SCTL_INIT_WDTR | SCTL_INIT_SDTR;
+ break;
+ }
+
+ Command.max_msecs = sctl_io_timeout; /* Set timeout to <n> minutes. */
+ memcpy(Command.cdb, CDB, CDB_Length);
+ Command.cdb_length = CDB_Length;
+ Command.data = DataBuffer;
+ Command.data_length = DataBufferLength;
+ ioctl_result=ioctl(DeviceFD, SIOC_IO, &Command);
+ SCSI_Default_Timeout(); /* change the default back to 5 minutes */
+
+ if (ioctl_result < 0)
+ {
+ perror("mtx");
+ return ioctl_result;
+ }
+
+ if (Command.sense_xfer > sizeof(RequestSense_T))
+ {
+ Command.sense_xfer=sizeof(RequestSense_T);
+ }
+
+ if (Command.sense_xfer)
+ {
+ memcpy(RequestSense, Command.sense, Command.sense_xfer);
+ }
+
+ return Command.sense_status;
+}
diff --git a/scsi_linux.c b/scsi_linux.c
new file mode 100644
index 0000000..cc14ebf
--- /dev/null
+++ b/scsi_linux.c
@@ -0,0 +1,491 @@
+/* Copyright 1997, 1998 Leonard Zubkoff <lnz@dandelion.com>
+ Changes in Feb 2000 Eric Green <eric@badtux.org>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+*/
+
+/* this is the SCSI commands for Linux. Note that <eric@badtux.org> changed
+ * it from using SCSI_IOCTL_SEND_COMMAND to using the SCSI generic interface.
+ */
+
+#ifndef HZ
+#warning "HZ is not defined, mtx might not work correctly!"
+#define HZ 100 /* Jiffys for SG_SET_TIMEOUT */
+#endif
+
+/* These are copied out of BRU 16.1, with all the boolean masks changed
+ * to our bitmasks.
+*/
+#define S_NO_SENSE(s) ((s)->SenseKey == 0x0)
+#define S_RECOVERED_ERROR(s) ((s)->SenseKey == 0x1)
+
+#define S_NOT_READY(s) ((s)->SenseKey == 0x2)
+#define S_MEDIUM_ERROR(s) ((s)->SenseKey == 0x3)
+#define S_HARDWARE_ERROR(s) ((s)->SenseKey == 0x4)
+#define S_UNIT_ATTENTION(s) ((s)->SenseKey == 0x6)
+#define S_BLANK_CHECK(s) ((s)->SenseKey == 0x8)
+#define S_VOLUME_OVERFLOW(s) ((s)->SenseKey == 0xd)
+
+#define DEFAULT_TIMEOUT 3*60 /* 3 minutes here */
+
+/* Sigh, the T-10 SSC spec says all of the following is needed to
+ * detect a short read while in variable block mode, and that even
+ * though we got a BLANK_CHECK or MEDIUM_ERROR, it's still a valid read.
+ */
+
+#define HIT_FILEMARK(s) (S_NO_SENSE((s)) && (s)->Filemark && (s)->Valid)
+#define SHORT_READ(s) (S_NO_SENSE((s)) && (s)->ILI && (s)->Valid && (s)->AdditionalSenseCode==0 && (s)->AdditionalSenseCodeQualifier==0)
+#define HIT_EOD(s) (S_BLANK_CHECK((s)) && (s)->Valid)
+#define HIT_EOP(s) (S_MEDIUM_ERROR((s)) && (s)->EOM && (s)->Valid)
+#define HIT_EOM(s) ((s)->EOM && (s)->Valid)
+
+#define STILL_A_VALID_READ(s) (HIT_FILEMARK(s) || SHORT_READ(s) || HIT_EOD(s) || HIT_EOP(s) || HIT_EOM(s))
+
+#define SG_SCSI_DEFAULT_TIMEOUT (HZ*60*5) /* 5 minutes? */
+
+static int pack_id;
+static int sg_timeout;
+
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ int timeout = SG_SCSI_DEFAULT_TIMEOUT;
+#ifdef SG_IO
+ int k; /* version */
+#endif
+ int DeviceFD = open(DeviceName, O_RDWR);
+
+ if (DeviceFD < 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+
+
+#ifdef SG_IO
+ /* It is prudent to check we have a sg device by trying an ioctl */
+ if ((ioctl(DeviceFD, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000))
+ {
+ FatalError("%s is not an sg device, or old sg driver\n", DeviceName);
+ }
+#endif
+
+ if (ioctl(DeviceFD, SG_SET_TIMEOUT, &timeout))
+ {
+ FatalError("failed to set sg timeout - %m\n");
+ }
+ pack_id = 1; /* used for SG v3 interface if possible. */
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+void SCSI_Set_Timeout(int secs)
+{
+ sg_timeout = secs * HZ;
+}
+
+void SCSI_Default_Timeout(void)
+{
+ sg_timeout = SG_SCSI_DEFAULT_TIMEOUT;
+}
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ if (close(DeviceFD) < 0)
+ FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
+}
+
+
+/* Added by Eric Green <eric@estinc.com> to deal with burping
+ * Seagate autoloader (hopefully!).
+ */
+/* Get the SCSI ID and LUN... */
+scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd)
+{
+ int status;
+ scsi_id_t *retval;
+
+ struct my_scsi_idlun
+ {
+ int word1;
+ int word2;
+ } idlun;
+
+ status = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
+ if (status)
+ {
+ return NULL; /* sorry! */
+ }
+
+ retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
+ retval->id = idlun.word1 & 0xff;
+ retval->lun = idlun.word1 >> 8 & 0xff;
+
+#ifdef DEBUG
+ fprintf(stderr, "SCSI:ID=%d LUN=%d\n", retval->id, retval->lun);
+#endif
+
+ return retval;
+}
+
+
+/* Changed January 2001 by Eric Green <eric@badtux.org> to
+ * use the Linux version 2.4 SCSI Generic facility if available.
+ * Liberally cribbed code from Doug Gilbert's sg3 utils.
+ */
+
+#ifdef SG_IO
+#include "sg_err.h" /* error stuff. */
+#include "sg_err.c" /* some of Doug Gilbert's routines */
+
+/* Use the new SG_IO structure */
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ unsigned int status;
+ sg_io_hdr_t io_hdr;
+
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+
+ /* Fill in the common stuff... */
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = CDB_Length;
+ io_hdr.mx_sb_len = sizeof(RequestSense_T);
+ io_hdr.dxfer_len = DataBufferLength;
+ io_hdr.cmdp = (unsigned char *) CDB;
+ io_hdr.sbp = (unsigned char *) RequestSense;
+ io_hdr.dxferp = DataBuffer;
+ io_hdr.timeout = sg_timeout * 10; /* Convert from Jiffys to milliseconds */
+
+ if (Direction==Input)
+ {
+ /* fprintf(stderr,"direction=input\n"); */
+ io_hdr.dxfer_direction=SG_DXFER_FROM_DEV;
+ }
+ else
+ {
+ /* fprintf(stderr,"direction=output\n"); */
+ io_hdr.dxfer_direction=SG_DXFER_TO_DEV;
+ }
+
+ /* Now do it: */
+ if ((status = ioctl(DeviceFD, SG_IO , &io_hdr)) || io_hdr.masked_status)
+ {
+ /* fprintf(stderr, "smt_scsi_cmd: Rval=%d Status=%d, errno=%d [%s]\n",status, io_hdr.masked_status,
+ errno,
+ strerror(errno)); */
+
+ switch (sg_err_category3(&io_hdr))
+ {
+ case SG_ERR_CAT_CLEAN:
+ case SG_ERR_CAT_RECOVERED:
+ break;
+
+ case SG_ERR_CAT_MEDIA_CHANGED:
+ return 2;
+
+ default:
+ return -1;
+ }
+
+ /* fprintf(stderr,"host_status=%d driver_status=%d residual=%d writelen=%d\n",io_hdr.host_status,io_hdr.driver_status,io_hdr.resid,io_hdr.sb_len_wr ); */
+
+ return -errno;
+ }
+
+ /* Now check the returned statuses: */
+ /* fprintf(stderr,"host_status=%d driver_status=%d residual=%d writelen=%d\n",io_hdr.host_status,io_hdr.driver_status,io_hdr.resid,io_hdr.sb_len_wr ); */
+
+ SCSI_Default_Timeout(); /* reset back to default timeout, sigh. */
+ return 0;
+}
+
+#else
+
+/* Changed February 2000 by Eric Green <eric@estinc.com> to
+ * use the SCSI generic interface rather than SCSI_IOCTL_SEND_COMMAND
+ * so that we can get more than PAGE_SIZE data....
+ *
+ * Note that the SCSI generic interface abuses READ and WRITE calls to serve
+ * the same purpose as IOCTL calls, i.e., for "writes", the contents of the
+ * buffer that you send as the argument to the write() call are actually
+ * altered to fill in result status and sense data (if needed).
+ * Also note that this brain-dead interface does not have any sort of
+ * provisions for expanding the sg_header struct in a backward-compatible
+ * manner. This sucks. But sucks less than SCSI_IOCTL_SEND_COMMAND, sigh.
+ */
+
+
+#ifndef OLD_EXECUTE_COMMAND_STUFF
+
+static void slow_memcopy(unsigned char *src, unsigned char *dest, int numbytes)
+{
+ while (numbytes--)
+ {
+ *dest++ = *src++;
+ }
+}
+
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ unsigned char *Command=NULL; /* the command data struct sent to them... */
+ unsigned char *ResultBuf=NULL; /* the data we read in return... */
+
+ unsigned char *src; /* for copying stuff, sigh. */
+ unsigned char *dest; /* for copy stuff, again, sigh. */
+
+ int write_length = sizeof(struct sg_header)+CDB_Length;
+ int i; /* a random index... */
+ int result; /* the result of the write... */
+
+ struct sg_header *Header; /* we actually point this into Command... */
+ struct sg_header *ResultHeader; /* we point this into ResultBuf... */
+
+ /* First, see if we need to set our SCSI timeout to something different */
+ if (sg_timeout != SG_SCSI_DEFAULT_TIMEOUT)
+ {
+ /* if not default, set it: */
+#ifdef DEBUG_TIMEOUT
+ fprintf(stderr,"Setting timeout to %d\n", sg_timeout);
+ fflush(stderr);
+#endif
+ if(ioctl(DeviceFD, SG_SET_TIMEOUT, &sg_timeout))
+ {
+ FatalError("failed to set sg timeout - %m\n");
+ }
+ }
+
+ if (Direction == Output)
+ {
+ /* if we're writing, our length is longer... */
+ write_length += DataBufferLength;
+ }
+
+ /* allocate some memory... enough for the command plus the header +
+ * any other data that we may need here...
+ */
+
+ Command = (unsigned char *)xmalloc(write_length);
+ Header = (struct sg_header *) Command; /* make it point to start of buf */
+
+ dest = Command; /* now to copy the CDB... from start of buffer,*/
+ dest += sizeof(struct sg_header); /* increment it past the header. */
+
+ slow_memcopy((char *)CDB, dest, CDB_Length);
+
+ /* if we are writing additional data, tack it on here! */
+ if (Direction == Output)
+ {
+ dest += CDB_Length;
+ slow_memcopy(DataBuffer, dest, DataBufferLength); /* copy to end of command */
+ }
+
+ /* Now to fill in the Header struct: */
+ Header->reply_len=DataBufferLength+sizeof(struct sg_header);
+#ifdef DEBUG
+ fprintf(stderr,"sg:reply_len(sent)=%d\n",Header->reply_len);
+#endif
+ Header->twelve_byte = CDB_Length == 12;
+ Header->result = 0;
+ Header->pack_len = write_length; /* # of bytes written... */
+ Header->pack_id = 0; /* not used */
+ Header->other_flags = 0; /* not used. */
+ Header->sense_buffer[0]=0; /* used? */
+
+ /* Now to do the write... */
+ result = write(DeviceFD,Command,write_length);
+
+ /* Now to check the result :-(. */
+ /* Note that we don't have any request sense here. So we have no
+ * idea what's going on.
+ */
+ if (result < 0 || result != write_length || Header->result || Header->sense_buffer[0])
+ {
+#ifdef DEBUG_SCSI
+ fprintf(stderr,"scsi:result=%d Header->result=%d Header->sense_buffer[0]=%d\n",
+ result,Header->result,Header->sense_buffer[0]);
+#endif
+ /* we don't have any real sense data, sigh :-(. */
+ if (Header->sense_buffer[0])
+ {
+ /* well, I guess we DID have some! eep! copy the sense data! */
+ slow_memcopy((char *)Header->sense_buffer,(char *)RequestSense,
+ sizeof(Header->sense_buffer));
+ }
+ else
+ {
+ dest=(unsigned char *)RequestSense;
+ *dest=(unsigned char)Header->result; /* may chop, sigh... */
+ }
+
+ /* okay, now, we may or may not need to find a non-zero value to return.
+ * For tape drives, we may get a BLANK_CHECK or MEDIUM_ERROR and find
+ * that it's *STILL* a good read! Use the STILL_A_VALID_READ macro
+ * that calls all those macros I cribbed from Richard.
+ */
+
+ if (!STILL_A_VALID_READ(RequestSense))
+ {
+ free(Command); /* zap memory leak, sigh */
+ /* okay, find us a non-zero value to return :-(. */
+ if (result)
+ {
+ return result;
+ }
+ else if (Header->result)
+ {
+ return Header->result;
+ }
+ else
+ {
+ return -1; /* sigh */
+ }
+ }
+ else
+ {
+ result=-1;
+ }
+ }
+ else
+ {
+ result=0; /* we're okay! */
+ }
+
+ /* now to allocate the new block.... */
+ ResultBuf=(unsigned char *)xmalloc(Header->reply_len);
+ /* now to clear ResultBuf... */
+ slow_bzero(ResultBuf,Header->reply_len);
+
+ ResultHeader=(struct sg_header *)ResultBuf;
+
+ /* copy the original Header... */
+ ResultHeader->result=0;
+ ResultHeader->pack_id=0;
+ ResultHeader->other_flags=0;
+ ResultHeader->reply_len=Header->reply_len;
+ ResultHeader->twelve_byte = CDB_Length == 12;
+ ResultHeader->pack_len = write_length; /* # of bytes written... */
+ ResultHeader->sense_buffer[0]=0; /* whoops! Zero that! */
+#ifdef DEBUG
+ fprintf(stderr,"sg:Reading %d bytes from DeviceFD\n",Header->reply_len);
+ fflush(stderr);
+#endif
+ result=read(DeviceFD,ResultBuf,Header->reply_len);
+#ifdef DEBUG
+ fprintf(stderr,"sg:result=%d ResultHeader->result=%d\n",
+ result,ResultHeader->result);
+ fflush(stderr);
+#endif
+ /* New: added check to see if the result block is still all zeros! */
+ if (result < 0 ||
+ result != Header->reply_len ||
+ ResultHeader->result ||
+ ResultHeader->sense_buffer[0])
+ {
+#ifdef DEBUG
+ fprintf(stderr,
+ "scsi: result=%d Header->reply_len=%d ResultHeader->result=%d ResultHeader->sense_buffer[0]=%d\n",
+ result,
+ Header->reply_len,
+ ResultHeader->result,
+ ResultHeader->sense_buffer[0]);
+#endif
+ /* eep! copy the sense data! */
+ slow_memcopy((char *)ResultHeader->sense_buffer,(char *)RequestSense,
+ sizeof(ResultHeader->sense_buffer));
+ /* sense data copied, now find us a non-zero value to return :-(. */
+ /* NOTE: Some commands return sense data even though they validly
+ * executed! We catch a few of those with the macro STILL_A_VALID_READ.
+ */
+
+ if (!STILL_A_VALID_READ(RequestSense))
+ {
+ free(Command);
+ if (result)
+ {
+ free(ResultBuf);
+ return result;
+ }
+ else if (ResultHeader->result)
+ {
+ free(ResultBuf);
+ return ResultHeader->result;
+ }
+ else
+ {
+ free(ResultBuf);
+ return -1; /* sigh! */
+ }
+ }
+ else
+ {
+ result=-1; /* if it was a valid read, still have -1 result. */
+ }
+ }
+ else
+ {
+ result=0;
+ }
+
+ /* See if we need to reset our SCSI timeout */
+ if (sg_timeout != SG_SCSI_DEFAULT_TIMEOUT)
+ {
+ sg_timeout = SG_SCSI_DEFAULT_TIMEOUT; /* reset it back to default */
+
+#ifdef DEBUG_TIMEOUT
+ fprintf(stderr,"Setting timeout to %d\n", sg_timeout);
+ fflush(stderr);
+#endif
+ /* if not default, set it: */
+ if (ioctl(DeviceFD, SG_SET_TIMEOUT, &sg_timeout))
+ {
+ FatalError("failed to set sg timeout - %m\n");
+ }
+ }
+
+ /* now for the crowning moment: copying any result into the DataBuffer! */
+ /* (but only if it were an input command and not an output command :-} */
+ if (Direction == Input)
+ {
+#ifdef DEBUG
+ fprintf(stderr,"Header->reply_len=%d,ResultHeader->reply_len=%d\n",
+ Header->reply_len,ResultHeader->reply_len);
+#endif
+ src=ResultBuf+sizeof(struct sg_header);
+ dest=DataBuffer;
+ for (i = 0; i < ResultHeader->reply_len; i++)
+ {
+ if (i >= DataBufferLength)
+ break; /* eep! */
+ *dest++ = *src++;
+ }
+ }
+
+ /* and return! */
+ free(Command); /* clean up memory leak... */
+ free(ResultBuf);
+ return result; /* good stuff ! */
+}
+
+#endif
+#endif /* #ifdef SG_IO */
diff --git a/scsi_sgi.c b/scsi_sgi.c
new file mode 100644
index 0000000..32c00a5
--- /dev/null
+++ b/scsi_sgi.c
@@ -0,0 +1,81 @@
+/* Copyright 1997, 1998 Leonard Zubkoff <lnz@dandelion.com>
+ Changes copyright 2000 Eric Green <eric@badtux.org>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+*/
+
+/* This is the SCSI commands for SGI Iris */
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ dsreq_t *DeviceFD = dsopen(DeviceName, O_RDWR | O_EXCL);
+ if (DeviceFD == 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ dsclose((dsreq_t *) DeviceFD);
+}
+
+#define MTX_HZ 1000
+#define MTX_DEFAULT_SCSI_TIMEOUT 60*5*MTX_HZ /* 5 minutes! */
+
+static int mtx_default_timeout = MTX_DEFAULT_SCSI_TIMEOUT ;
+void SCSI_Set_Timeout(int sec)
+{
+ mtx_default_timeout=sec*MTX_HZ;
+}
+
+void SCSI_Default_Timeout()
+{
+ mtx_default_timeout=MTX_DEFAULT_SCSI_TIMEOUT;
+}
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ dsreq_t *dsp = (dsreq_t *) DeviceFD;
+ int Result;
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+ memcpy(CMDBUF(dsp), CDB, CDB_Length);
+
+ if (Direction == Input)
+ {
+ memset(DataBuffer, 0, DataBufferLength);
+ filldsreq(dsp, (unsigned char *) DataBuffer, DataBufferLength, DSRQ_READ | DSRQ_SENSE);
+ }
+ else
+ filldsreq(dsp, (unsigned char *) DataBuffer, DataBufferLength, DSRQ_WRITE | DSRQ_SENSE);
+
+ /* Set 5 minute timeout. */
+ /* TIME(dsp) = 300 * 1000; */
+ TIME(dsp) = mtx_default_timeout;
+ Result = doscsireq(getfd((dsp)), dsp);
+
+ if (SENSESENT(dsp) > 0)
+ {
+ memcpy(RequestSense, SENSEBUF(dsp), min(sizeof(RequestSense_T), SENSESENT(dsp)));
+ }
+
+ SCSI_Default_Timeout(); /* reset the mtx default timeout */
+ return Result;
+}
diff --git a/scsi_sun.c b/scsi_sun.c
new file mode 100644
index 0000000..7197e62
--- /dev/null
+++ b/scsi_sun.c
@@ -0,0 +1,156 @@
+/* Copyright 1997, 1998 Leonard Zubkoff <lnz@dandelion.com>
+ Changes copyright 2000 Eric Green <eric@badtux.org>
+ Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+*/
+
+/* This is the SCSI commands for Sun Solaris. */
+
+#define LONG_PRINT_REQUEST_SENSE /* sigh! */
+
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ int DeviceFD = open(DeviceName, O_RDWR | O_NDELAY);
+ if (DeviceFD < 0)
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ return (DEVICE_TYPE) DeviceFD;
+}
+
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ if (close(DeviceFD) < 0)
+ FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
+}
+
+
+#define HAS_SCSI_TIMEOUT
+
+static int uscsi_timeout=5*60;
+
+void SCSI_Set_Timeout(int to)
+{
+ uscsi_timeout = to;
+}
+
+void SCSI_Default_Timeout(void)
+{
+ uscsi_timeout=5*60; /* the default */
+}
+
+#ifdef DEBUG
+int SCSI_DumpBuffer(int DataBufferLength, unsigned char *DataBuffer)
+{
+ int i,j;
+ j = 0;
+
+ for (i = 0; i < DataBufferLength; i++)
+ {
+ if (j == 25)
+ {
+ fprintf(stderr,"\n");
+ j = 0;
+ }
+
+ if (j == 0)
+ {
+ fprintf(stderr, "%04x:", i);
+ }
+
+ if (j > 0)
+ {
+ fprintf(stderr," ");
+ }
+
+ fprintf(stderr, "%02x", (int)DataBuffer[i]);
+ j++;
+ }
+ fprintf(stderr, "\n");
+}
+#endif
+
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ int ioctl_result;
+ struct uscsi_cmd Command;
+
+#ifdef DEBUG_SCSI
+ fprintf(stderr,"------CDB--------\n");
+ SCSI_DumpBuffer(CDB_Length,(char *)CDB);
+#endif
+
+ memset(&Command, 0, sizeof(struct uscsi_cmd));
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+ switch (Direction)
+ {
+ case Input:
+ Command.uscsi_flags = USCSI_DIAGNOSE | USCSI_ISOLATE | USCSI_RQENABLE;
+ if (DataBufferLength > 0)
+ {
+ memset(DataBuffer, 0, DataBufferLength);
+ Command.uscsi_flags |= USCSI_READ;
+ }
+ break;
+ case Output:
+ Command.uscsi_flags = USCSI_DIAGNOSE | USCSI_ISOLATE |
+ USCSI_WRITE | USCSI_RQENABLE;
+ break;
+ }
+ /* Set timeout to 5 minutes. */
+#ifdef DEBUG_TIMEOUT
+ fprintf(stderr,"uscsi_timeout=%d\n",uscsi_timeout);
+ fflush(stderr);
+#endif
+ Command.uscsi_timeout = uscsi_timeout;
+
+ Command.uscsi_cdb = (caddr_t) CDB;
+ Command.uscsi_cdblen = CDB_Length;
+ Command.uscsi_bufaddr = DataBuffer;
+ Command.uscsi_buflen = DataBufferLength;
+ Command.uscsi_rqbuf = (caddr_t) RequestSense;
+ Command.uscsi_rqlen = sizeof(RequestSense_T);
+ ioctl_result = ioctl(DeviceFD, USCSICMD, &Command);
+
+ SCSI_Default_Timeout(); /* set it back to default, sigh. */
+
+ if (ioctl_result < 0)
+ {
+#ifdef DEBUG
+ perror("mtx");
+#endif
+ return ioctl_result;
+ }
+
+ if (RequestSense->ErrorCode > 1)
+ {
+ return -1;
+ }
+
+#ifdef DEBUG_SCSI
+ if (Direction==Input)
+ {
+ fprintf(stderr,"--------input data-----------\n");
+ SCSI_DumpBuffer(DataBufferLength, DataBuffer);
+ }
+#endif
+ return 0;
+}
diff --git a/scsi_win32.c b/scsi_win32.c
new file mode 100644
index 0000000..b913fd1
--- /dev/null
+++ b/scsi_win32.c
@@ -0,0 +1,355 @@
+/* Copyright 2006-2008 Robert Nelson <robertn@the-nelsons.org>
+
+$Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+$Revision: 193 $
+
+ This program is free software; you may redistribute and/or modify it under
+ the terms of the GNU General Public License Version 2 as published by the
+ Free Software Foundation.
+
+ 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 complete details.
+
+*/
+
+/*
+ * This is the SCSI commands for Windows.
+ */
+
+#include <stdio.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifdef _MSC_VER
+#include <ntddscsi.h>
+#else
+#include <ddk/ntddscsi.h>
+#endif
+
+#define SCSI_DEFAULT_TIMEOUT 300 /* 1 minutes */
+#define SCSI_MAX_TIMEOUT 108000 /* 30 hours */
+
+typedef struct _HANDLE_ENTRY
+{
+ HANDLE hDevice;
+ UCHAR PortId;
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+} HANDLE_ENTRY, *PHANDLE_ENTRY;
+
+PHANDLE_ENTRY HandleTable = NULL;
+int nEntries = 0;
+
+DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
+{
+ int DeviceIndex;
+ TCHAR szDevicePath[256];
+
+ int nColons = 0;
+ int index;
+
+ int port, path, target, lun;
+
+ for (DeviceIndex = 0; DeviceIndex < nEntries; DeviceIndex++)
+ {
+ if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
+ break;
+ }
+
+ if (DeviceIndex >= nEntries)
+ {
+ PHANDLE_ENTRY pNewTable;
+
+ nEntries += 4;
+
+ if (HandleTable == NULL)
+ {
+ pNewTable = (PHANDLE_ENTRY)malloc(nEntries * sizeof(HANDLE_ENTRY));
+ }
+ else
+ {
+ pNewTable = (PHANDLE_ENTRY)realloc(HandleTable, nEntries * sizeof(HANDLE_ENTRY));
+ }
+
+ if (pNewTable == NULL)
+ {
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ }
+
+ HandleTable = pNewTable;
+ }
+
+ for (index = 0; DeviceName[index] != '\0'; index++)
+ {
+ if (DeviceName[index] == ':')
+ nColons++;
+ else if (DeviceName[index] < '0' || DeviceName[index] > '9')
+ break;
+ }
+
+ if (DeviceName[index] == '\0' && nColons == 3 &&
+ sscanf(DeviceName, "%d:%d:%d:%d", &port, &path, &target, &lun) == 4)
+ {
+ HandleTable[DeviceIndex].PortId = (UCHAR)port;
+ HandleTable[DeviceIndex].PathId = (UCHAR)path;
+ HandleTable[DeviceIndex].TargetId = (UCHAR)target;
+ HandleTable[DeviceIndex].Lun = (UCHAR)lun;
+
+ sprintf(szDevicePath, "\\\\.\\scsi%d:", port);
+ }
+ else
+ {
+ int nPrefixLength = 0;
+
+ if (DeviceName[0] != '\\') {
+ memcpy(szDevicePath, "\\\\.\\", 4 * sizeof(TCHAR));
+ nPrefixLength = 4;
+ }
+
+ HandleTable[DeviceIndex].PortId = 0;
+ HandleTable[DeviceIndex].PathId = 0;
+ HandleTable[DeviceIndex].TargetId = 0;
+ HandleTable[DeviceIndex].Lun = 0;
+
+ strncpy(&szDevicePath[nPrefixLength],
+ DeviceName,
+ sizeof(szDevicePath) / sizeof(TCHAR) - nPrefixLength - 1);
+
+ szDevicePath[sizeof(szDevicePath) / sizeof(TCHAR) - 1] = '\0';
+ }
+
+ HandleTable[DeviceIndex].hDevice = CreateFile(szDevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
+ {
+ DWORD dwError = GetLastError();
+
+#if DEBUG
+ LPSTR lpszMessage;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
+ fputs(lpszMessage, stderr);
+#endif
+
+ switch (dwError)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+
+ case ERROR_TOO_MANY_OPEN_FILES:
+ errno = EMFILE;
+ break;
+
+ default:
+ case ERROR_ACCESS_DENIED:
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_INVALID_NAME:
+ errno = EACCES;
+ break;
+
+ case ERROR_FILE_EXISTS:
+ errno = EEXIST;
+ break;
+
+ case ERROR_INVALID_PARAMETER:
+ errno = EINVAL;
+ break;
+ }
+
+ FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
+ }
+
+ return DeviceIndex;
+}
+
+static int scsi_timeout = SCSI_DEFAULT_TIMEOUT;
+
+void SCSI_Set_Timeout(int secs)
+{
+ if (secs > SCSI_MAX_TIMEOUT)
+ {
+ secs = SCSI_MAX_TIMEOUT;
+ }
+
+ scsi_timeout = secs;
+}
+
+void SCSI_Default_Timeout(void)
+{
+ scsi_timeout = SCSI_DEFAULT_TIMEOUT;
+}
+
+void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
+{
+ if (DeviceFD < nEntries)
+ {
+ CloseHandle(HandleTable[DeviceFD].hDevice);
+ HandleTable[DeviceFD].hDevice = INVALID_HANDLE_VALUE;
+ }
+ else
+ {
+ errno = EBADF;
+ FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
+ }
+}
+
+
+/* Get the SCSI ID and LUN... */
+scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd)
+{
+ scsi_id_t * retval;
+
+ SCSI_ADDRESS ScsiAddress;
+ BOOL bResult;
+ DWORD dwBytesReturned;
+
+ if (fd < nEntries)
+ {
+ retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
+ retval->id = HandleTable[fd].TargetId;
+ retval->lun = HandleTable[fd].Lun;
+
+#ifdef DEBUG
+ fprintf(stderr,"SCSI:ID=%d LUN=%d\n", retval->id, retval->lun);
+#endif
+ return retval;
+ }
+ else
+ {
+ errno = EBADF;
+ FatalError("cannot close SCSI device - %m\n");
+ }
+
+ memset(&ScsiAddress, 0, sizeof(ScsiAddress));
+
+ ScsiAddress.Length = sizeof(ScsiAddress);
+
+ bResult = DeviceIoControl( HandleTable[fd].hDevice,
+ IOCTL_SCSI_GET_ADDRESS,
+ &ScsiAddress, sizeof(ScsiAddress),
+ &ScsiAddress, sizeof(ScsiAddress),
+ &dwBytesReturned,
+ NULL);
+
+ if (!bResult)
+ {
+ return NULL;
+ }
+
+ retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
+ retval->id = ScsiAddress.TargetId;
+ retval->lun = ScsiAddress.Lun;
+
+#ifdef DEBUG
+ fprintf(stderr,"SCSI:ID=%d LUN=%d\n",retval->id,retval->lun);
+#endif
+ return retval;
+}
+
+int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ PSCSI_PASS_THROUGH ScsiPassThrough;
+
+ const DWORD dwDataBufferOffset = sizeof(SCSI_PASS_THROUGH) + (sizeof(RequestSense_T) + 3) / 4 * 4;
+ const DWORD dwBufferSize = dwDataBufferOffset + DataBufferLength;
+
+ BOOL bResult;
+ DWORD dwBytesReturned;
+ DWORD dwInputLength;
+ DWORD dwOutputLength;
+
+ if (DeviceFD >= nEntries || HandleTable[DeviceFD].hDevice == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ ScsiPassThrough = (PSCSI_PASS_THROUGH)malloc(dwBufferSize);
+
+ memset(ScsiPassThrough, 0, dwDataBufferOffset);
+
+ ScsiPassThrough->Length = sizeof(SCSI_PASS_THROUGH);
+
+ ScsiPassThrough->PathId = HandleTable[DeviceFD].PathId;
+ ScsiPassThrough->TargetId = HandleTable[DeviceFD].TargetId;
+ ScsiPassThrough->Lun = HandleTable[DeviceFD].Lun;
+ ScsiPassThrough->CdbLength = (UCHAR)CDB_Length;
+ ScsiPassThrough->DataIn = Direction == Input;
+ ScsiPassThrough->DataBufferOffset = dwDataBufferOffset;
+ ScsiPassThrough->DataTransferLength = DataBufferLength;
+ ScsiPassThrough->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH);
+ ScsiPassThrough->SenseInfoLength = sizeof(RequestSense_T);
+ ScsiPassThrough->TimeOutValue = scsi_timeout;
+
+ memcpy(ScsiPassThrough->Cdb, CDB, CDB_Length);
+ dwBytesReturned = 0;
+
+ if (Direction == Output)
+ {
+ memcpy((void *)(((char *)ScsiPassThrough) + dwDataBufferOffset), DataBuffer, DataBufferLength);
+ dwInputLength = dwBufferSize;
+ dwOutputLength = dwDataBufferOffset;
+ }
+ else
+ {
+ dwInputLength = sizeof(SCSI_PASS_THROUGH);
+ dwOutputLength = dwBufferSize;
+ }
+
+ bResult = DeviceIoControl( HandleTable[DeviceFD].hDevice,
+ IOCTL_SCSI_PASS_THROUGH,
+ ScsiPassThrough, dwInputLength,
+ ScsiPassThrough, dwOutputLength,
+ &dwBytesReturned,
+ NULL);
+ if (bResult)
+ {
+ if (ScsiPassThrough->ScsiStatus != 0)
+ {
+ memcpy(RequestSense, &ScsiPassThrough[1], sizeof(RequestSense_T));
+#if DEBUG
+ fprintf(stderr, "Command failed - ScsiStatus = %d\n", ScsiPassThrough->ScsiStatus);
+ PrintRequestSense(RequestSense);
+#endif
+ bResult = false;
+ }
+ else
+ {
+ if (Direction == Input)
+ {
+ memcpy( DataBuffer,
+ (void *)(((char *)ScsiPassThrough) + dwDataBufferOffset),
+ DataBufferLength);
+ }
+ }
+ }
+ else
+ {
+#if DEBUG
+ DWORD dwError = GetLastError();
+ LPSTR lpszMessage;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
+ fputs(lpszMessage, stderr);
+ LocalFree(lpszMessage);
+#endif
+
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+ }
+
+ free(ScsiPassThrough);
+
+ return bResult ? 0 : -1;
+}
diff --git a/scsieject.1 b/scsieject.1
new file mode 100644
index 0000000..52e309e
--- /dev/null
+++ b/scsieject.1
@@ -0,0 +1,116 @@
+.\" scsieject.1 Document Copyright 2007-2008 Robert Nelson
+.\"
+.\" This is free documentation; 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.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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 manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH scsieject 1 scsieject1.0
+.SH NAME
+scsieject \- control SCSI tape devices
+.SH SYNOPSIS
+scsieject [-f <scsi-generic-device>] commands
+.SH DESCRIPTION
+The
+.B scsieject
+command controls SCSI devices in a platform-independent
+manner. As long as 'mtx' works on the platform, so does 'scsieject'.
+.SH OPTIONS
+The first argument, given following
+.B -f
+, is the SCSI generic device corresponding to your tape drive.
+Consult your operating system's documentation for more information (for
+example, under Linux these are generally /dev/sg0 through /dev/sg15,
+under FreeBSD these are /dev/pass0 through /dev/passX. Under Solaris
+this is usually the same as your tape drive (Solaris has a SCSI passthrough
+ioctl). You can set the STAPE or TAPE environment variable rather
+than use -f.
+.P
+.SH COMMANDS
+.TP 10
+.B load
+Load the medium into the drive. When this command is issued to a CD/DVD drive
+and the tray is extended the tray will be retracted if the drive is capable of it.
+
+.TP 10
+.B unload
+Unload the medium from the drive (also known as eject). When this command is issued
+to a CD/DVD drive or a tape drive the media will be ejected if the device supports it.
+
+.TP 10
+.B start
+Start the device. Some devices require a start command after a media changer has
+loaded new media into the device.
+
+.TP 10
+.B stop
+Stop the device. Some devices require a stop command prior to unloading the medium
+from the device when using a media changer.
+
+.TP 10
+.B lock
+Lock the device. Locks the device so that the medium cannot be removed manually.
+
+.TP 10
+.B unlock
+Unlock the device. Unlocks the device so that the medium can be removed manually.
+
+.SH AUTHORS
+This program was written by Robert Nelson <robertnelson@users.sourceforge.net>
+based on the scsitape program written by Eric Lee Green <eric@badtux.org>.
+Major portions of the 'mtxl.c' library used herein were written by
+Leonard Zubkoff.
+.P
+
+.SH HINTS
+Under Linux,
+.B cat /proc/scsi/scsi
+will tell you what SCSI devices you have.
+You can then refer to them as
+.B /dev/sga,
+.B /dev/sgb,
+etc. by the order they
+are reported.
+.P
+Under FreeBSD,
+.B camcontrol devlist
+will tell you what SCSI devices you
+have, along with which
+.B pass
+device controls them.
+.P
+Under Solaris 7 and 8,
+.B /usr/sbin/devfsadm -C
+will clean up your /devices directory. Then
+.B find /devices -name 'st@*' -print
+will return a list of all tape drives. /dev on Solaris is apparently only
+of historical interest.
+
+.SH BUGS AND LIMITATIONS
+There are no known bugs or limitations.
+
+.SH AVAILABILITY
+This version of
+.B scsieject
+is currently being maintained by Robert Nelson <robertnelson@users.sourceforge.net>
+as part of the 'mtx' suite of programs. The 'mtx' home page is
+http://mtx.sourceforge.net and the actual code is currently available there and via
+SVN from http://sourceforge.net/projects/mtx.
+
+.SH SEE ALSO
+.BR loaderinfo (1), tapeinfo (1), mtx (1)
diff --git a/scsieject.c b/scsieject.c
new file mode 100644
index 0000000..c2c79b9
--- /dev/null
+++ b/scsieject.c
@@ -0,0 +1,255 @@
+/* Copyright 2007-2008, Robert Nelson <robertn@the-nelsons.org>
+ * Released under terms of the GNU General Public License as
+ * required by the license on 'mtxl.c'.
+ * $Date: 2007-01-28 19:23:33 -0800 (Sun, 28 Jan 2007) $
+ * $Revision: 125 $
+ */
+
+/* This is a generic SCSI device control program. It operates by
+ * directly sending commands to the device.
+ */
+
+/*
+ * Commands:
+ * load -- Load medium
+ * unload -- Unload medium
+ * start -- Start device
+ * stop -- Stop device
+ * lock -- Lock medium
+ * unlock -- Unlock medium
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mtx.h"
+#include "mtxl.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef _MSC_VER
+#include <io.h>
+#endif
+
+char *argv0;
+
+/* the device handle we're operating upon. */
+static char *device; /* the device name. */
+static DEVICE_TYPE DeviceFD = (DEVICE_TYPE) -1;
+
+static int S_load(void);
+static int S_unload(void);
+static int S_start(void);
+static int S_stop(void);
+static int S_lock(void);
+static int S_unlock(void);
+
+struct command_table_struct
+{
+ char *name;
+ int (*command)(void);
+}
+ command_table[] =
+{
+ { "load", S_load },
+ { "unload", S_unload },
+ { "start", S_start },
+ { "stop", S_stop },
+ { "lock", S_lock },
+ { "unlock", S_unlock },
+ { NULL, NULL } /* terminate list */
+};
+
+void Usage(void)
+{
+ FatalError("Usage: scsieject -f <generic-device> <command> where <command> is:\n load | unload | start | stop | lock | unlock\n");
+}
+
+/* open_device() -- set the 'DeviceFD' variable.... */
+void open_device(void)
+{
+ if (DeviceFD != -1)
+ {
+ SCSI_CloseDevice("Unknown", DeviceFD);
+ }
+
+ DeviceFD = SCSI_OpenDevice(device);
+}
+
+/* we see if we've got a file open. If not, we open one :-(. Then
+ * we execute the actual command. Or not :-(.
+ */
+int execute_command(struct command_table_struct *command)
+{
+ /*
+ * If the device is not already open, then open it from the
+ * environment.
+ */
+ if (DeviceFD == -1)
+ {
+ /* try to get it from STAPE or TAPE environment variable... */
+ if ((device = getenv("STAPE")) == NULL &&
+ (device = getenv("TAPE")) == NULL)
+ {
+ Usage(); /* Doesn't return */
+ }
+
+ open_device();
+ }
+
+ /* okay, now to execute the command... */
+ return command->command();
+}
+
+
+/* parse_args():
+ * Basically, we are parsing argv/argc. We can have multiple commands
+ * on a line, such as "load start" to load a tape and start the device.
+ * We execute these commands one at a time as we come to them. If we don't
+ * have a -f at the start and the default device isn't defined in a TAPE or
+ * STAPE environment variable, we exit.
+ */
+
+int parse_args(int argc, char **argv)
+{
+ int index, retval;
+ struct command_table_struct *command;
+
+ argv0 = argv[0];
+
+ for (index = 1; index < argc; index++)
+ {
+ if (strcmp(argv[index], "-f") == 0)
+ {
+ index++;
+ if (index >= argc)
+ {
+ Usage(); /* Doesn't return */
+ }
+ device = argv[index];
+ open_device();
+ }
+ else
+ {
+ for (command = &command_table[0]; command->name != NULL; command++)
+ {
+ if (strcmp(command->name, argv[index]) == 0)
+ {
+ break;
+ }
+ }
+
+ if (command->name == NULL)
+ {
+ Usage(); /* Doesn't return */
+ }
+
+ retval = execute_command(command);
+
+ if (retval < 0)
+ {
+ /* Command failed, we probably shouldn't continue */
+ return retval;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int S_load(void)
+{
+ int result = LoadUnload(DeviceFD, 1);
+
+ if (result < 0)
+ {
+ fputs("scsieject: load failed\n", stderr);
+ fflush(stderr);
+ }
+
+ return result;
+}
+
+int S_unload(void)
+{
+ int result = LoadUnload(DeviceFD, 0);
+
+ if (result < 0)
+ {
+ fputs("scsieject: unload failed\n", stderr);
+ fflush(stderr);
+ }
+
+ return result;
+}
+
+int S_start(void)
+{
+ int result = StartStop(DeviceFD, 1);
+
+ if (result < 0)
+ {
+ fputs("scsieject: start failed\n", stderr);
+ fflush(stderr);
+ }
+
+ return result;
+}
+
+int S_stop(void)
+{
+ int result = StartStop(DeviceFD, 0);
+
+ if (result < 0)
+ {
+ fputs("scsieject: stop failed\n", stderr);
+ fflush(stderr);
+ }
+
+ return result;
+}
+
+int S_lock(void)
+{
+ int result = LockUnlock(DeviceFD, 1);
+
+ if (result < 0)
+ {
+ fputs("scsieject: lock failed\n", stderr);
+ fflush(stderr);
+ }
+
+ return result;
+}
+
+int S_unlock(void)
+{
+ int result = LockUnlock(DeviceFD, 0);
+
+ if (result < 0)
+ {
+ fputs("scsieject: unlock failed\n", stderr);
+ fflush(stderr);
+ }
+
+ return result;
+}
+
+/* See parse_args for the scoop. parse_args does all. */
+int main(int argc, char **argv)
+{
+ parse_args(argc, argv);
+
+ if (device)
+ {
+ SCSI_CloseDevice(device, DeviceFD);
+ }
+
+ exit(0);
+}
diff --git a/scsitape.1 b/scsitape.1
new file mode 100644
index 0000000..46906bc
--- /dev/null
+++ b/scsitape.1
@@ -0,0 +1,179 @@
+.\" scsitape.1 Document Copyright 2001 Eric Lee Green
+.\" Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+.\"
+.\" This is free documentation; 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.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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 manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH SCSITAPE 1 SCSITAPE1.0
+.SH NAME
+scsitape \- control SCSI tape devices
+.SH SYNOPSIS
+scsitape [-f <scsi-generic-device>] commands
+.SH DESCRIPTION
+The
+.B scsitape
+command controls SCSI tape drives in a platform-independent
+manner. As long as 'mtx' works on the platform, so does 'scsitape'.
+.P
+Note that 'scsitape' and your OS's native tape driver may stomp on each
+other. In particular, if you use 'setblk' and your OS's native tape
+driver has a different notion of the block size, you may get evil results.
+It is recommended to use 'scsitape' only for software where you've written
+your own low-level READ and WRITE routines that use the SCSI command set
+to directly talk to tape drives (i.e., you do not use the OS's native tape
+driver at all).
+.SH OPTIONS
+The first argument, given following
+.B -f
+, is the SCSI generic device corresponding to your tape drive.
+Consult your operating system's documentation for more information (for
+example, under Linux these are generally /dev/sg0 through /dev/sg15,
+under FreeBSD these are /dev/pass0 through /dev/passX. Under Solaris
+this is usually the same as your tape drive (Solaris has a SCSI passthrough
+ioctl). You can set the STAPE or TAPE environment variable rather
+than use -f.
+.P
+.SH COMMANDS
+.TP 10
+.B setblk <n>
+Set the tape drive's SCSI block size to <n> bytes. (NOTE: if you are
+using your OS's native tape driver, THIS IS EVIL!).
+
+.TP 10
+.B fsf <n>
+Go forward by <n> tapemarks.
+.TP 10
+.B bsf <n>
+Go to immediately previous the <n>th previous tapemark. (WARNING: This
+probably doesn't do what you expect -- e.g. if you are immediately
+after a tapemark and type 'bfs 1', it moves to immediately *before*
+that tape mark, for a sum total of zero effective movement!).
+.TP 10
+.B eod
+Go to end of data.
+.TP 10
+.B rewind
+Rewind the tape drive.
+.TP 10
+.B eject
+Eject the tape currently in the drive.
+.TP 10
+.B erase
+Does a *short* erase (warning: does NOT work on all drives!).
+.TP 10
+.B mark <n>
+ write <n> filemarks ( 'mark 0' flushes the drive's buffers ).
+.TP 10
+.B seek <n>
+Seek to a logical position <n> that was reported by a previous 'tapeinfo'
+command.
+.TP 10
+.B write <blocksize>
+write blocks from stdin to the tape. Chunk the data into <blocksize>-sized
+chunks. *DOES NOT WRITE OUT A TAPEMARK!* (you will need to use a
+subsequent
+.B mark 1
+command to write out a tape mark).
+.TP 10
+.B read [<blocksize>] [ <#blocks/#bytes> ]
+read blocks from the tape, write them to stdout. If we are in variable
+block mode, <blocksize> should be zero (note: The maximum block size
+we currently support in variable block mode is 128K, MAX_READ_SIZE will
+need to be turned into a settable variable to allow bigger reads). If
+<blocksize> is ommitted, we assume that we're in variable block mode, and
+that we are going to read from tape until we hit a tapemark or end of
+partition or end of tape.
+
+
+.SH AUTHORS
+This program was written by Eric Lee Green <eric@badtux.org>.
+Major portions of the 'mtxl.c' library used herein were written by
+Leonard Zubkoff.
+.P
+
+The SCSI read and write routines are based upon those that Richard
+Fish wrote for Enhanced Software Technology's BRU 16.1 product,
+substantially modified to work in our particular environment (in
+particular, all the variable block stuff is new since BRU only does
+fixed block reads and writes, and the BRU code uses bitmasks rather
+than bitfields for the various flags and such in return values, as
+well as the BRU code having a different SCSI API and having variable
+names considerably shorter than the rather sesquipedalian 'mtx'
+identifiers). As required by 'mtxl.c', these routines are licensed
+under the GNU General Public License.
+
+.SH HINTS
+Under Linux,
+.B cat /proc/scsi/scsi
+will tell you what SCSI devices you have.
+You can then refer to them as
+.B /dev/sga,
+.B /dev/sgb,
+etc. by the order they
+are reported.
+.P
+Under FreeBSD,
+.B camcontrol devlist
+will tell you what SCSI devices you
+have, along with which
+.B pass
+device controls them.
+.P
+Under Solaris 7 and 8,
+.B /usr/sbin/devfsadm -C
+will clean up your /devices directory. Then
+.B find /devices -name 'st@*' -print
+will return a list of all tape drives. /dev on Solaris is apparently only
+of historical interest.
+
+.SH BUGS AND LIMITATIONS
+
+for
+.B scsitape read 0 <n>
+where you are doing variable-block-size reads and wish for <n> bytes,
+it instead reads one and exactly one block from tape and prints that
+(no matter what its size). Use 'dd' on the output of scsitape if you
+want finer control.
+.P
+.B scsitape read 0
+attempts reads of MAX_READ_SIZE, which is currently 128K. If blocks on tape
+are larger than 128K, only the first 128K will be read -- the remainder
+will be silently dumped in the toilet.
+.P
+This program does not interact well (or at all :-) with your OS's
+native tape driver. You will likely see weird things happen if you
+attempt to intermingle scsitape commands with native tape driver
+operations. Note that BRU 16.1 for Solaris (and possibly others, but
+Solaris I know about) will have a 'scsi' keyword to bypass the
+native tape driver and write via direct uscsi commands, so if you use
+\'scsitape\' to bypass the flaws of the native Solaris driver, you can use
+BRU 16.1 to write your actual tape archives. (Assuming that BRU 16.1
+has been released at the time that you read this).
+
+.SH AVAILABILITY
+This version of
+.B scsitape
+is currently being maintained by Robert Nelson <robertnelson@users.sourceforge.net>
+as part of the 'mtx' suite of programs. The 'mtx' home page is
+http://mtx.sourceforge.net and the actual code is currently available there and via
+SVN from http://sourceforge.net/projects/mtx.
+
+.SH SEE ALSO
+.BR loaderinfo (1), tapeinfo (1), mtx (1)
diff --git a/scsitape.c b/scsitape.c
new file mode 100644
index 0000000..dd52dd5
--- /dev/null
+++ b/scsitape.c
@@ -0,0 +1,941 @@
+/* Copyright 2001 Enhanced Software Technologies Inc.
+ * Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+ * Released under terms of the GNU General Public License as
+ * required by the license on 'mtxl.c'.
+ * $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+ * $Revision: 193 $
+ */
+
+/* This is a generic SCSI tape control program. It operates by
+ * directly sending commands to the tape drive. If you are going
+ * through your operating system's SCSI tape driver, do *NOT* use
+ * this program! If, on the other hand, you are using raw READ and WRITE
+ * commands through your operating system's generic SCSI interface (or
+ * through our built-in 'read' and 'write'), this is the place for you.
+ */
+
+/*#define DEBUG_PARTITION */
+/*#define DEBUG 1 */
+
+/*
+ Commands:
+ setblk <n> -- set the block size to <n>
+ fsf <n> -- go forward by <n> filemarks
+ bsf <n> -- go backward by <n> filemarks
+ eod -- go to end of data
+ rewind -- rewind back to start of data
+ eject -- rewind, then eject the tape.
+ erase -- (short) erase the tape (we have no long erase)
+ mark <n> -- write <n> filemarks.
+ seek <n> -- seek to position <n>.
+
+ write <blksize> <-- write blocks from stdin to the tape
+ read [<blksize>] [<#blocks/#bytes>] -- read blocks from tape, write to stdout.
+
+ See the 'tapeinfo' program for status info about the tape drive.
+
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mtx.h"
+#include "mtxl.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if HAVE_SYS_MTIO_H
+#include <sys/mtio.h> /* will try issuing some ioctls for Solaris, sigh. */
+#endif
+
+#ifdef _MSC_VER
+#include <io.h>
+#endif
+
+void Usage(void) {
+ FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | mark <n> |\n seek <n> | read [<blksize> [<numblocks]] | write [<blocksize>] \n");
+}
+
+#define arg1 (arg[0]) /* for backward compatibility, sigh */
+static int arg[4]; /* the argument for the command, sigh. */
+
+/* the device handle we're operating upon, sigh. */
+static char *device; /* the text of the device thingy. */
+static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) -1;
+
+
+
+static int S_setblk(void);
+static int S_fsf(void);
+static int S_bsf(void);
+static int S_eod(void);
+static int S_rewind(void);
+static int S_eject(void);
+static int S_mark(void);
+static int S_seek(void);
+static int S_reten(void);
+static int S_erase(void);
+
+static int S_read(void);
+static int S_write(void);
+
+
+struct command_table_struct {
+ int num_args;
+ char *name;
+ int (*command)(void);
+} command_table[] = {
+ { 1, "setblk", S_setblk },
+ { 1, "fsf", S_fsf },
+ { 1, "bsf", S_bsf },
+ { 0, "eod", S_eod },
+ { 0, "rewind", S_rewind },
+ { 0, "eject", S_eject },
+ { 0, "reten", S_reten },
+ { 0, "erase", S_erase },
+ { 1, "mark", S_mark },
+ { 1, "seek", S_seek },
+ { 2, "read", S_read },
+ { 2, "write",S_write },
+ { 0, NULL, NULL } /* terminate list */
+};
+
+char *argv0;
+
+
+/* open_device() -- set the 'fh' variable.... */
+void open_device(void)
+{
+ if (MediumChangerFD != -1)
+ {
+ SCSI_CloseDevice("Unknown",MediumChangerFD); /* close it, sigh... new device now! */
+ }
+
+ MediumChangerFD = SCSI_OpenDevice(device);
+}
+
+static int get_arg(char *arg)
+{
+ int retval=-1;
+
+ if (*arg < '0' || *arg > '9')
+ {
+ return -1; /* sorry! */
+ }
+
+ retval=atoi(arg);
+ return retval;
+}
+
+
+/* we see if we've got a file open. If not, we open one :-(. Then
+ * we execute the actual command. Or not :-(.
+ */
+int execute_command(struct command_table_struct *command)
+{
+ /* if the device is not already open, then open it from the
+ * environment.
+ */
+ if (!MediumChangerFD == -1)
+ {
+ /* try to get it from STAPE or TAPE environment variable... */
+ device = getenv("STAPE");
+ if (device == NULL)
+ {
+ device = getenv("TAPE");
+ if (device == NULL)
+ {
+ Usage();
+ }
+ }
+ open_device();
+ }
+
+ /* okay, now to execute the command... */
+ return command->command();
+}
+
+
+/* parse_args():
+ * Basically, we are parsing argv/argc. We can have multiple commands
+ * on a line now, such as "unload 3 0 load 4 0" to unload one tape and
+ * load in another tape into drive 0, and we execute these commands one
+ * at a time as we come to them. If we don't have a -f at the start, we
+ * barf. If we leave out a drive #, we default to drive 0 (the first drive
+ * in the cabinet).
+ */
+
+int parse_args(int argc, char **argv)
+{
+ int i, cmd_tbl_idx,retval,arg_idx;
+ struct command_table_struct *command;
+
+ i=1;
+ arg_idx = 0;
+ while (i < argc)
+ {
+ if (strcmp(argv[i],"-f") == 0)
+ {
+ i++;
+ if (i >= argc)
+ {
+ Usage();
+ }
+ device = argv[i++];
+ open_device(); /* open the device and do a status scan on it... */
+ }
+ else
+ {
+ cmd_tbl_idx=0;
+ command = &command_table[0]; /* default to the first command... */
+ command = &command_table[cmd_tbl_idx];
+ while (command->name)
+ {
+ if (strcmp(command->name,argv[i]) == 0)
+ {
+ /* we have a match... */
+ break;
+ }
+ /* otherwise we don't have a match... */
+ cmd_tbl_idx++;
+ command = &command_table[cmd_tbl_idx];
+ }
+ /* if it's not a command, exit.... */
+ if (command->name == NULL)
+ {
+ Usage();
+ }
+ i++; /* go to the next argument, if possible... */
+ /* see if we need to gather arguments, though! */
+ arg1 = -1; /* default it to something */
+ for (arg_idx=0;arg_idx < command->num_args ; arg_idx++)
+ {
+ if (i < argc)
+ {
+ arg[arg_idx] = get_arg(argv[i]);
+ if (arg[arg_idx] != -1)
+ {
+ i++; /* increment i over the next cmd. */
+ }
+ }
+ else
+ {
+ arg[arg_idx] = 0; /* default to 0 setmarks or whatever */
+ }
+ }
+ retval=execute_command(command); /* execute_command handles 'stuff' */
+ exit(retval);
+ }
+ }
+ return 0; /* should never get here */
+}
+
+/* For Linux, this allows us to do a short erase on a tape (sigh!).
+ * Note that you'll need to do a 'mt status' on the tape afterwards in
+ * order to get the tape driver in sync with the tape drive again. Also
+ * note that on other OS's, this might do other evil things to the tape
+ * driver. Note that to do an erase, you must first rewind!
+
+ */
+static int S_erase(void)
+{
+ int retval;
+ RequestSense_T *RequestSense;
+
+ retval=S_rewind();
+ if (retval)
+ {
+ return retval; /* we have an exit status :-(. */
+ }
+
+ RequestSense=Erase(MediumChangerFD);
+ if (RequestSense)
+ {
+ PrintRequestSense(RequestSense);
+ exit(1); /* exit with an error status. */
+ }
+ return 0;
+}
+
+/* This should eject a tape or magazine, depending upon the device sent
+ * to.
+ */
+static int S_eject(void)
+{
+ int i;
+ i = LoadUnload(MediumChangerFD, 0);
+ if ( i < 0)
+ {
+ fprintf(stderr,"scsitape:eject failed\n");
+ fflush(stderr);
+ }
+ return i;
+}
+
+
+
+/* We write a filemarks of 0 before going to grab position, in order
+ * to insure that data in the buffer is not a problem.
+ */
+
+static int S_mark(void)
+{
+ RequestSense_T RequestSense; /* for result of ReadElementStatus */
+ CDB_T CDB;
+ unsigned char buffer[6];
+ int count = arg1; /* voila! */
+
+ CDB[0] = 0x10; /* SET_MARK */
+ CDB[1] = 0;
+ CDB[2] = (unsigned char)(count >> 16);
+ CDB[3] = (unsigned char)(count >> 8);
+ CDB[4] = (unsigned char)count;
+ CDB[5] = 0;
+
+ /* we really don't care if this command works or not, sigh. */
+ slow_bzero((char *)&RequestSense, sizeof(RequestSense_T));
+
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 6, buffer, 0, &RequestSense)!= 0)
+ {
+ PrintRequestSense(&RequestSense);
+ return 1;
+ }
+ return 0;
+}
+/* let's rewind to bod!
+ */
+
+static int S_rewind(void)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+
+ CDB[0] = 0x01; /* REWIND */
+ CDB[1] = 0;
+ CDB[2] = 0;
+ CDB[3] = 0;
+ CDB[4] = 0;
+ CDB[5] = 0;
+
+ /* we really don't care if this command works or not, sigh. */
+ slow_bzero((char *)&sense,sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0)
+ {
+ PrintRequestSense(&sense);
+ return 1;
+ }
+ return 0;
+}
+
+
+
+
+/* This is used for fsf and bsf. */
+static int Space(int count, char code)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+
+ CDB[0] = 0x11; /* SET_MARK */
+ CDB[1] = code;
+ CDB[2] = (unsigned char)(count >> 16);
+ CDB[3] = (unsigned char)(count >> 8);
+ CDB[4] = (unsigned char)count;
+ CDB[5] = 0;
+
+ /* we really don't care if this command works or not, sigh. */
+ slow_bzero((char *)&sense,sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 6, buffer, 0, &sense) != 0)
+ {
+ PrintRequestSense(&sense);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Let's try a fsf: */
+/* We write a filemarks of 0 before going to grab position, in order
+ * to insure that data in the buffer is not a problem.
+ */
+
+static int S_fsf(void)
+{
+ return Space(arg1,1); /* go forward! */
+}
+
+static int S_bsf(void)
+{
+ return Space(-arg1,1); /* go backward! */
+}
+
+static int S_eod(void)
+{
+ return Space(0,3); /* go to eod! */
+}
+
+/* sigh, abuse of the LOAD command...
+
+ */
+static int S_reten(void)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+
+ CDB[0] = 0x1B; /* START_STOP */
+ CDB[1] = 0; /* wait */
+ CDB[2] = 0;
+ CDB[3] = 0;
+ CDB[4] = 3; /* reten. */
+ CDB[5] = 0;
+
+ /* we really don't care if this command works or not, sigh. */
+ slow_bzero((char *)&sense, sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 6, buffer, 0, &sense) != 0)
+ {
+ PrintRequestSense(&sense);
+ return 1;
+ }
+ return 0;
+}
+
+/* seek a position on the tape (sigh!) */
+static int S_seek(void)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+ int count = arg1;
+
+ /* printf("count=%d\n",arg1); */
+
+ CDB[0] = 0x2B; /* LOCATE */
+ CDB[1] = 0; /* Logical */
+ CDB[2] = 0; /* padding */
+ CDB[3] = (unsigned char)(count >> 24);
+ CDB[4] = (unsigned char)(count >> 16);
+ CDB[5] = (unsigned char)(count >> 8);
+ CDB[6] = (unsigned char)count;
+ CDB[7] = 0;
+ CDB[8] = 0;
+ CDB[9] = 0;
+
+ /* we really don't care if this command works or not, sigh. */
+ slow_bzero((char *)&sense,sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 10, buffer, 0, &sense) != 0)
+ {
+ PrintRequestSense(&sense);
+ return 1;
+ }
+ return 0;
+}
+
+#ifdef MTSRSZ
+static int Solaris_setblk(int fh,int count)
+{
+ /* we get here only if we have a MTSRSZ, which means Solaris. */
+ struct mtop mt_com; /* the struct used for the MTIOCTOP ioctl */
+ int result;
+
+ /* okay, we have fh and count.... */
+
+ /* Now to try the ioctl: */
+ mt_com.mt_op=MTSRSZ;
+ mt_com.mt_count=count;
+
+ /* surround the actual ioctl to enable threading, since fsf/etc. can be
+ * big time consumers and we want other threads to be able to run too.
+ */
+
+ result=ioctl(fh, MTIOCTOP, (char *)&mt_com);
+
+ if (result < 0)
+ {
+ return errno;
+ }
+
+ /* okay, we did okay. Return a value of None... */
+ return 0;
+}
+#endif
+
+
+/* okay, this is a write: we need to set the block size to something: */
+static int S_setblk(void)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ char buffer[12];
+ unsigned int count = (unsigned int) arg1;
+
+ CDB[0] = 0x15; /* MODE SELECT */
+ CDB[1] = 0x10; /* scsi2 */
+ CDB[2] = 0;
+ CDB[3] = 0;
+ CDB[4] = 12; /* length of data */
+ CDB[5] = 0;
+
+ slow_bzero((char *)&sense, sizeof(RequestSense_T));
+ slow_bzero(buffer, 12);
+
+ /* Now to set the mode page header: */
+ buffer[0] = 0;
+ buffer[1] = 0;
+ buffer[2] = 0x10; /* we are in buffered mode now, people! */
+ buffer[3] = 8; /* block descriptor length. */
+ buffer[4] = 0; /* reset to default density, sigh. */ /* 0 */
+ buffer[5] = 0; /* 1 */
+ buffer[6] = 0; /* 2 */
+ buffer[7] = 0; /* 3 */
+ buffer[8] = 0; /* 4 */
+ buffer[9] = (unsigned char)(count >> 16); /* 5 */
+ buffer[10] = (unsigned char)(count >> 8); /* 6 */
+ buffer[11] = (unsigned char)count; /* 7 */
+
+ if (SCSI_ExecuteCommand(MediumChangerFD,Output,&CDB,6,buffer,12,&sense)!=0)
+ {
+ PrintRequestSense(&sense);
+ return 1;
+ }
+#ifdef MTSRSZ
+ /* Solaris_setblk(MediumChangerFD,count); */
+#endif
+
+ return 0;
+}
+
+/*************************************************************************/
+/* SCSI read/write calls. These are mostly pulled out of BRU 16.1,
+ * modified to work within the mtxl.h framework rather than the
+ * scsi_lowlevel.h framework.
+ *************************************************************************/
+
+#define MAX_READ_SIZE 128*1024 /* max size of a variable-block read */
+
+#define READ_OK 0
+#define READ_FILEMARK 1
+#define READ_EOD 2
+#define READ_EOP 3
+#define READ_SHORT 5
+#define READ_ERROR 255
+
+#define WRITE_OK 0
+#define WRITE_ERROR 1
+#define WRITE_EOM 2
+#define WRITE_EOV 3
+
+
+/* These are copied out of BRU 16.1, with all the boolean masks changed
+ * to our bitmasks.
+*/
+#define S_NO_SENSE(s) ((s).SenseKey == 0x0)
+#define S_RECOVERED_ERROR(s) ((s).SenseKey == 0x1)
+
+#define S_NOT_READY(s) ((s).SenseKey == 0x2)
+#define S_MEDIUM_ERROR(s) ((s).SenseKey == 0x3)
+#define S_HARDWARE_ERROR(s) ((s).SenseKey == 0x4)
+#define S_UNIT_ATTENTION(s) ((s).SenseKey == 0x6)
+#define S_BLANK_CHECK(s) ((s).SenseKey == 0x8)
+#define S_VOLUME_OVERFLOW(s) ((s).SenseKey == 0xd)
+
+#define DEFAULT_TIMEOUT 3*60 /* 3 minutes here */
+
+#define HIT_FILEMARK(s) (S_NO_SENSE((s)) && (s).Filemark && (s).Valid)
+/* Sigh, the T-10 SSC spec says all of the following is needed to
+ * detect a short read while in variable block mode. We'll see.
+ */
+#define SHORT_READ(s) (S_NO_SENSE((s)) && (s).ILI && (s).Valid && (s).AdditionalSenseCode==0 && (s).AdditionalSenseCodeQualifier==0)
+
+#define HIT_EOD(s) (S_BLANK_CHECK((s)) && (s).Valid)
+#define HIT_EOP(s) (S_MEDIUM_ERROR((s)) && (s).EOM && (s).Valid)
+#define HIT_EOM(s) ((s).EOM && (s).Valid)
+#define BECOMING_READY(s) (S_UNIT_ATTENTION((s)) && (s).AdditionalSenseCode == 0x28 && (s).AdditionalSenseCodeQualifier == 0)
+
+/* Reading is a problem. We can hit a filemark, hit an EOD, or hit an
+ * EOP. Our caller may do something about that. Note that we assume that
+ * our caller has already put us into fixed block mode. If he has not, then
+ * we are in trouble anyhow.
+ */
+int SCSI_readt(DEVICE_TYPE fd, char * buf, unsigned int bufsize, unsigned int *len, unsigned int timeout) {
+ int rtnval;
+ CDB_T cmd;
+
+ int blockCount;
+ int info;
+
+ RequestSense_T RequestSense;
+
+ if (bufsize==0)
+ {
+ /* we are in variable block mode */
+ blockCount=MAX_READ_SIZE; /* variable block size. */
+ }
+ else
+ {
+ blockCount= *len / bufsize;
+ if ((*len % bufsize) != 0)
+ {
+ fprintf(stderr,"Error: Data (%d bytes) not even multiple of block size (%d bytes).\n",*len,bufsize);
+ exit(1); /* we're finished, sigh. */
+ }
+ }
+
+ if (timeout == 0)
+ {
+ timeout = 1 * 60; /* 1 minutes */
+ }
+
+ memset(&cmd, 0, sizeof(CDB_T));
+ cmd[0] = 0x08; /* READ */
+ cmd[1] = (bufsize) ? 1 : 0; /* fixed length or var length blocks */
+ cmd[2] = (unsigned char)(blockCount >> 16); /* MSB */
+ cmd[3] = (unsigned char)(blockCount >> 8);
+ cmd[4] = (unsigned char)blockCount; /* LSB */
+
+ /* okay, let's read, look @ the result code: */
+ rtnval=READ_OK;
+ if (SCSI_ExecuteCommand(fd,Input,&cmd,6,buf,(bufsize) ? *len : MAX_READ_SIZE,&RequestSense))
+ {
+ rtnval=READ_ERROR;
+ if (HIT_EOP(RequestSense))
+ {
+ cmd[0]=0x08;
+ rtnval=READ_EOP;
+ }
+
+ if (HIT_FILEMARK(RequestSense))
+ {
+ rtnval=READ_FILEMARK;
+ }
+
+ if (HIT_EOD(RequestSense))
+ {
+ rtnval=READ_EOD;
+ }
+
+ if ( (bufsize==0) && SHORT_READ(RequestSense))
+ {
+ rtnval=READ_SHORT; /* we only do short reads for variable block mode */
+ }
+
+ if (rtnval != READ_ERROR)
+ {
+ /* info contains number of blocks or bytes *not* read. May be
+ negative if the block we were trying to read was too big. So
+ we will have to account for that and set it to zero if so, so that
+ we return the proper # of blocks read.
+ */
+ info = ((RequestSense.Information[0] << 24) +
+ (RequestSense.Information[1] << 16) +
+ (RequestSense.Information[2] << 8) +
+ RequestSense.Information[3]);
+
+ /* on 64-bit platforms, we may need to turn 'info' into a negative # */
+ if (info > 0x7fffffff)
+ info = 0;
+
+ if (info < 0)
+ info=0; /* make sure we don't return too big len read. */
+
+ /* Now set *len to # of bytes read. */
+ *len= bufsize ? (blockCount-info) * bufsize : MAX_READ_SIZE-info ;
+ }
+ else
+ {
+ PrintRequestSense(&RequestSense);
+ exit(1); /* foo. */
+ }
+ }
+
+ return rtnval;
+}
+
+/* Low level SCSI write. Modified from BRU 16.1, with much BRU smarts
+ * taken out and with the various types changed to mtx types rather than
+ * BRU types.
+ */
+int SCSI_write(DEVICE_TYPE fd, char * buf, unsigned int blocksize,
+ unsigned int *len)
+{
+ CDB_T cmd;
+
+ int blockCount;
+ int rtnval=0;
+ RequestSense_T RequestSense;
+
+ if (blocksize == 0)
+ {
+ /* we are in variable block mode */
+ blockCount = *len; /* variable block size. */
+ }
+ else
+ {
+ blockCount= *len / blocksize ;
+ if ((*len % blocksize) != 0)
+ {
+ fprintf(stderr,"Error: Data (%d bytes) not even multiple of block size (%d bytes).\n",*len,blocksize);
+ exit(1); /* we're finished, sigh. */
+ }
+ }
+
+ fprintf(stderr,"Writing %d blocks\n",blockCount);
+
+ memset(&cmd, 0, sizeof(CDB_T));
+ cmd[0] = 0x0a; /* WRITE */
+ cmd[1] = (blocksize) ? 1 : 0; /* fixed length or var length blocks */
+ cmd[2] = (unsigned char)(blockCount >> 16); /* MSB */
+ cmd[3] = (unsigned char)(blockCount >> 8);
+ cmd[4] = (unsigned char)blockCount; /* LSB */
+
+
+ if (SCSI_ExecuteCommand(fd,Output,&cmd,6,buf, *len, &RequestSense))
+ {
+ if (HIT_EOM(RequestSense))
+ {
+ /* we hit end of media. Return -1. */
+ if (S_VOLUME_OVERFLOW(RequestSense))
+ {
+ exit(WRITE_EOV);
+ }
+ exit(WRITE_EOM); /* end of media! */
+ }
+ else
+ {
+ /* it was plain old write error: */
+ PrintRequestSense(&RequestSense);
+ exit(WRITE_ERROR);
+ }
+ }
+ else
+ {
+ rtnval = *len; /* worked! */
+ }
+ return rtnval;
+}
+
+/* S_write is not implemented yet! */
+static int S_write(void)
+{
+ char *buffer; /* the buffer we're gonna read/write out of. */
+ int buffersize;
+ int len; /* the length of the data in the buffer */
+ int blocksize = arg[0];
+ int numblocks = arg[1];
+ int varsize=0; /* variable size block flag */
+ int result;
+ int eof_input;
+ int infile=fileno(stdin); /* sigh */
+
+ if (blocksize == 0)
+ {
+ varsize = 1;
+ buffersize = MAX_READ_SIZE;
+ len = MAX_READ_SIZE;
+ }
+ else
+ {
+ varsize = 0; /* fixed block mode */
+ buffersize = blocksize;
+ len = blocksize;
+ }
+
+ /* sigh, make it oversized just to have some */
+ buffer = malloc(buffersize+8);
+
+ eof_input = 0;
+ while (!eof_input)
+ {
+ /* size_t could be 64 bit on a 32 bit platform, so do casts. */
+ len=0;
+ /* If it is a pipe, we could read 4096 bytes rather than the full
+ * 128K bytes or whatever, so we must gather multiple reads into
+ * the buffer.
+ */
+ while (len < buffersize)
+ {
+ result=(int)read(infile, buffer + len, (size_t)(buffersize - len));
+ if (!result)
+ {
+ eof_input = 1;
+ if (!len)
+ {
+ /* if we have no deata in our buffer, exit */
+ return 0; /* we're at end of file! */
+ }
+ break; /* otherwise, break and write the data */
+ }
+ len += result; /* add the result input to our length. */
+ }
+
+ result = SCSI_write(MediumChangerFD, buffer, blocksize, (unsigned int *)&len);
+ if (!result)
+ {
+ return 1; /* at end of tape! */
+ }
+
+ /* Now see if we have numbytes or numblocks. If so, we may wish to exit
+ this loop.
+ */
+ if (arg[1])
+ {
+ if (varsize)
+ {
+ /***BUG***/
+ return 0; /* we will only write one block in variable size mode :-( */
+ }
+ else
+ {
+ if (numblocks)
+ {
+ numblocks--;
+ }
+ else
+ {
+ return 0; /* we're done. */
+ }
+ }
+ }
+ }
+ /* and done! */
+ return 0;
+}
+
+/* Okay, the read thingy: */
+
+/* We have a device opened (we hope!) by the parser.
+ * we will have arg[0] and arg[1] being the blocksize and # of blocks
+ * (respectively).
+ */
+
+
+static int S_read(void)
+{
+ char *buffer; /* the buffer we're going to be reading out of */
+ int buffersize;
+ unsigned int len; /* the length of the data in the buffer */
+ int blocksize = arg[0];
+ int numblocks = arg[1];
+ int varsize = 0; /* variable size block flag. */
+
+ int result;
+
+ int outfile=fileno(stdout); /* sigh. */
+
+ if (blocksize == 0)
+ {
+ varsize=1;
+ buffersize=MAX_READ_SIZE;
+ len=MAX_READ_SIZE;
+ }
+ else
+ {
+ varsize=0; /* fixed block mode */
+ buffersize=blocksize;
+ len=blocksize;
+ }
+
+ /* sigh, make it oversized just to have some */
+ buffer = malloc(buffersize + 8);
+
+ for ( ; ; )
+ {
+ if (varsize)
+ {
+ /* it could have gotten reset by prior short read... */
+ len=MAX_READ_SIZE;
+ }
+ result=SCSI_readt(MediumChangerFD,buffer,blocksize, &len, DEFAULT_TIMEOUT);
+
+ if (result==READ_FILEMARK || result==READ_EOD || result==READ_EOP)
+ {
+ /* okay, normal end of file? */
+ if (len > 0)
+ {
+ write(outfile,buffer,len);
+ }
+
+#ifdef NEED_TO_GO_PAST_FILEMARK
+ /* Now, let's try to go past the filemark if that's what we hit: */
+ if (result==READ_FILEMARK)
+ {
+ arg1 = 1; /* arg for S_fsf. */
+ S_fsf(); /* and go forward 1 filemark, we hope! */
+ }
+#endif
+ return 0; /* hit normal end of file. */
+ }
+ else if (result == READ_SHORT)
+ {
+ /* short reads are only valid in variable block mode. */
+ if (varsize)
+ {
+ if (len > 0)
+ {
+ write(outfile,buffer,len);
+ }
+ }
+ else
+ {
+ fprintf(stderr,"scsitape:Short Read encountered on input. Aborting.\n");
+ fflush(stderr);
+ exit(1); /* error exit! */
+ }
+ }
+ else if (result == READ_OK)
+ {
+ write(outfile,buffer,len);
+ }
+ else
+ {
+ fprintf(stderr,"scsitape:Read Error\n");
+ fflush(stderr);
+ exit(1);
+ }
+
+ /* Now see if we have numbytes or numblocks: if so, we may wish to
+ * exit this loop.
+ */
+ if (arg[1])
+ {
+ if (varsize)
+ {
+ /****BUG****/
+ return 0; /* we're only reading one block in var size mode! */
+ }
+ else if (numblocks)
+ {
+ numblocks--;
+ }
+ else
+ {
+ return 0; /* we're done. */
+ }
+ }
+ }
+}
+
+
+/* See parse_args for the scoop. parse_args does all. */
+int main(int argc, char **argv)
+{
+ argv0 = argv[0];
+ parse_args(argc, argv);
+
+ if (device)
+ SCSI_CloseDevice(device,MediumChangerFD);
+
+ exit(0);
+}
diff --git a/sg_err.c b/sg_err.c
new file mode 100644
index 0000000..6c1570e
--- /dev/null
+++ b/sg_err.c
@@ -0,0 +1,645 @@
+
+/* This file is a huge cut, paste and hack from linux/drivers/scsi/constant.c
+* which I guess was written by:
+* Copyright (C) 1993, 1994, 1995 Eric Youngdale
+
+* The rest of this is:
+* Copyright (C) 1999 - 2001 D. Gilbert
+* Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+*
+* 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, or (at your option)
+* any later version.
+*
+* ASCII values for a number of symbolic constants, printing functions, etc.
+*
+* Some of the tables have been updated for SCSI 2.
+*
+* Version 0.84 (20010115)
+* Change output from stdout to stderr
+*/
+
+#define OUTP stderr
+
+static const unsigned char scsi_command_size[8] = { 6, 10, 10, 12,
+ 12, 12, 10, 10 };
+
+#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
+
+static const char unknown[] = "UNKNOWN";
+
+static const char * group_0_commands[] = {
+/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
+/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks",
+/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown,
+/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
+/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve",
+/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
+/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic",
+/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
+};
+
+
+static const char *group_1_commands[] = {
+/* 20-22 */ unknown, unknown, unknown,
+/* 23-28 */ unknown, "Define window parameters", "Read Capacity",
+ unknown, unknown, "Read (10)",
+/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase",
+ "Read updated block",
+/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal",
+/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position",
+/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data",
+/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
+ "Read Buffer",
+/* 3d-3f */ "Update Block", "Read Long", "Write Long",
+};
+
+static const char *group_2_commands[] = {
+/* 40-41 */ "Change Definition", "Write Same",
+/* 42-48 */ "Read sub-channel", "Read TOC", "Read header",
+ "Play audio (10)", unknown, "Play audio msf",
+ "Play audio track/index",
+/* 49-4f */ "Play track relative (10)", unknown, "Pause/resume",
+ "Log Select", "Log Sense", unknown, unknown,
+/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)",
+/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown,
+/* 5c-5f */ unknown, unknown, unknown,
+};
+
+
+/* The following are 12 byte commands in group 5 */
+static const char *group_5_commands[] = {
+/* a0-a5 */ unknown, unknown, unknown, unknown, unknown,
+ "Move medium/play audio(12)",
+/* a6-a9 */ "Exchange medium", unknown, "Read(12)", "Play track relative(12)",
+/* aa-ae */ "Write(12)", unknown, "Erase(12)", unknown,
+ "Write and verify(12)",
+/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
+/* b2-b4 */ "Search data low(12)", "Set limits(12)", unknown,
+/* b5-b6 */ "Request volume element address", "Send volume tag",
+/* b7-b9 */ "Read defect data(12)", "Read element status", unknown,
+/* ba-bf */ unknown, unknown, unknown, unknown, unknown, unknown,
+};
+
+
+
+
+#define group(opcode) (((opcode) >> 5) & 7)
+
+#define RESERVED_GROUP 0
+#define VENDOR_GROUP 1
+
+static const char **commands[] = {
+ group_0_commands, group_1_commands, group_2_commands,
+ (const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP,
+ group_5_commands, (const char **) VENDOR_GROUP,
+ (const char **) VENDOR_GROUP
+};
+
+static const char reserved[] = "RESERVED";
+static const char vendor[] = "VENDOR SPECIFIC";
+
+static void print_opcode(int opcode) {
+ const char **table = commands[ group(opcode) ];
+ switch ((unsigned long) table) {
+ case RESERVED_GROUP:
+ fprintf(OUTP, "%s(0x%02x) ", reserved, opcode);
+ break;
+ case VENDOR_GROUP:
+ fprintf(OUTP, "%s(0x%02x) ", vendor, opcode);
+ break;
+ default:
+ if (table[opcode & 0x1f] != unknown)
+ fprintf(OUTP, "%s ",table[opcode & 0x1f]);
+ else
+ fprintf(OUTP, "%s(0x%02x) ", unknown, opcode);
+ break;
+ }
+}
+
+void sg_print_command (const unsigned char * command) {
+ int i,s;
+ print_opcode(command[0]);
+ for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+ fprintf(OUTP, "%02x ", command[i]);
+ fprintf(OUTP, "\n");
+}
+
+static const char * statuses[] = {
+/* 0-4 */ "Good", "Check Condition", "Condition Met", unknown, "Busy",
+/* 5-9 */ unknown, unknown, unknown, "Intermediate", unknown,
+/* a-c */ "Intermediate-Condition Met", unknown, "Reservation Conflict",
+/* d-10 */ unknown, unknown, unknown, unknown,
+/* 11-14 */ "Command Terminated", unknown, unknown, "Queue Full",
+/* 15-1a */ unknown, unknown, unknown, unknown, unknown, unknown,
+/* 1b-1f */ unknown, unknown, unknown, unknown, unknown,
+};
+
+void sg_print_status (int masked_status) {
+ /* status = (status >> 1) & 0xf; */ /* already done */
+ fprintf(OUTP, "%s ",statuses[masked_status]);
+}
+
+#define D 0x001 /* DIRECT ACCESS DEVICE (disk) */
+#define T 0x002 /* SEQUENTIAL ACCESS DEVICE (tape) */
+#define L 0x004 /* PRINTER DEVICE */
+#define P 0x008 /* PROCESSOR DEVICE */
+#define W 0x010 /* WRITE ONCE READ MULTIPLE DEVICE */
+#define R 0x020 /* READ ONLY (CD-ROM) DEVICE */
+#define S 0x040 /* SCANNER DEVICE */
+#define O 0x080 /* OPTICAL MEMORY DEVICE */
+#define M 0x100 /* MEDIA CHANGER DEVICE */
+#define C 0x200 /* COMMUNICATION DEVICE */
+
+struct error_info{
+ unsigned char code1, code2;
+ unsigned short int devices;
+ const char * text;
+};
+
+struct error_info2{
+ unsigned char code1, code2_min, code2_max;
+ unsigned short int devices;
+ const char * text;
+};
+
+static struct error_info2 additional2[] =
+{
+ {0x40,0x00,0x7f,D,"Ram failure (%x)"},
+ {0x40,0x80,0xff,D|T|L|P|W|R|S|O|M|C,"Diagnostic failure on component (%x)"},
+ {0x41,0x00,0xff,D,"Data path failure (%x)"},
+ {0x42,0x00,0xff,D,"Power-on or self-test failure (%x)"},
+ {0, 0, 0, 0, NULL}
+};
+
+static struct error_info additional[] =
+{
+ {0x00,0x01,T,"Filemark detected"},
+ {0x00,0x02,T|S,"End-of-partition/medium detected"},
+ {0x00,0x03,T,"Setmark detected"},
+ {0x00,0x04,T|S,"Beginning-of-partition/medium detected"},
+ {0x00,0x05,T|S,"End-of-data detected"},
+ {0x00,0x06,D|T|L|P|W|R|S|O|M|C,"I/O process terminated"},
+ {0x00,0x11,R,"Audio play operation in progress"},
+ {0x00,0x12,R,"Audio play operation paused"},
+ {0x00,0x13,R,"Audio play operation successfully completed"},
+ {0x00,0x14,R,"Audio play operation stopped due to error"},
+ {0x00,0x15,R,"No current audio status to return"},
+ {0x01,0x00,D|W|O,"No index/sector signal"},
+ {0x02,0x00,D|W|R|O|M,"No seek complete"},
+ {0x03,0x00,D|T|L|W|S|O,"Peripheral device write fault"},
+ {0x03,0x01,T,"No write current"},
+ {0x03,0x02,T,"Excessive write errors"},
+ {0x04,0x00,D|T|L|P|W|R|S|O|M|C,
+ "Logical unit not ready, cause not reportable"},
+ {0x04,0x01,D|T|L|P|W|R|S|O|M|C,
+ "Logical unit is in process of becoming ready"},
+ {0x04,0x02,D|T|L|P|W|R|S|O|M|C,
+ "Logical unit not ready, initializing command required"},
+ {0x04,0x03,D|T|L|P|W|R|S|O|M|C,
+ "Logical unit not ready, manual intervention required"},
+ {0x04,0x04,D|T|L|O,"Logical unit not ready, format in progress"},
+ {0x05,0x00,D|T|L|W|R|S|O|M|C,"Logical unit does not respond to selection"},
+ {0x06,0x00,D|W|R|O|M,"No reference position found"},
+ {0x07,0x00,D|T|L|W|R|S|O|M,"Multiple peripheral devices selected"},
+ {0x08,0x00,D|T|L|W|R|S|O|M|C,"Logical unit communication failure"},
+ {0x08,0x01,D|T|L|W|R|S|O|M|C,"Logical unit communication time-out"},
+ {0x08,0x02,D|T|L|W|R|S|O|M|C,"Logical unit communication parity error"},
+ {0x09,0x00,D|T|W|R|O,"Track following error"},
+ {0x09,0x01,W|R|O,"Tracking servo failure"},
+ {0x09,0x02,W|R|O,"Focus servo failure"},
+ {0x09,0x03,W|R|O,"Spindle servo failure"},
+ {0x0A,0x00,D|T|L|P|W|R|S|O|M|C,"Error log overflow"},
+ {0x0C,0x00,T|S,"Write error"},
+ {0x0C,0x01,D|W|O,"Write error recovered with auto reallocation"},
+ {0x0C,0x02,D|W|O,"Write error - auto reallocation failed"},
+ {0x10,0x00,D|W|O,"Id crc or ecc error"},
+ {0x11,0x00,D|T|W|R|S|O,"Unrecovered read error"},
+ {0x11,0x01,D|T|W|S|O,"Read retries exhausted"},
+ {0x11,0x02,D|T|W|S|O,"Error too long to correct"},
+ {0x11,0x03,D|T|W|S|O,"Multiple read errors"},
+ {0x11,0x04,D|W|O,"Unrecovered read error - auto reallocate failed"},
+ {0x11,0x05,W|R|O,"L-ec uncorrectable error"},
+ {0x11,0x06,W|R|O,"Circ unrecovered error"},
+ {0x11,0x07,W|O,"Data resynchronization error"},
+ {0x11,0x08,T,"Incomplete block read"},
+ {0x11,0x09,T,"No gap found"},
+ {0x11,0x0A,D|T|O,"Miscorrected error"},
+ {0x11,0x0B,D|W|O,"Unrecovered read error - recommend reassignment"},
+ {0x11,0x0C,D|W|O,"Unrecovered read error - recommend rewrite the data"},
+ {0x12,0x00,D|W|O,"Address mark not found for id field"},
+ {0x13,0x00,D|W|O,"Address mark not found for data field"},
+ {0x14,0x00,D|T|L|W|R|S|O,"Recorded entity not found"},
+ {0x14,0x01,D|T|W|R|O,"Record not found"},
+ {0x14,0x02,T,"Filemark or setmark not found"},
+ {0x14,0x03,T,"End-of-data not found"},
+ {0x14,0x04,T,"Block sequence error"},
+ {0x15,0x00,D|T|L|W|R|S|O|M,"Random positioning error"},
+ {0x15,0x01,D|T|L|W|R|S|O|M,"Mechanical positioning error"},
+ {0x15,0x02,D|T|W|R|O,"Positioning error detected by read of medium"},
+ {0x16,0x00,D|W|O,"Data synchronization mark error"},
+ {0x17,0x00,D|T|W|R|S|O,"Recovered data with no error correction applied"},
+ {0x17,0x01,D|T|W|R|S|O,"Recovered data with retries"},
+ {0x17,0x02,D|T|W|R|O,"Recovered data with positive head offset"},
+ {0x17,0x03,D|T|W|R|O,"Recovered data with negative head offset"},
+ {0x17,0x04,W|R|O,"Recovered data with retries and/or circ applied"},
+ {0x17,0x05,D|W|R|O,"Recovered data using previous sector id"},
+ {0x17,0x06,D|W|O,"Recovered data without ecc - data auto-reallocated"},
+ {0x17,0x07,D|W|O,"Recovered data without ecc - recommend reassignment"},
+ {0x18,0x00,D|T|W|R|O,"Recovered data with error correction applied"},
+ {0x18,0x01,D|W|R|O,"Recovered data with error correction and retries applied"},
+ {0x18,0x02,D|W|R|O,"Recovered data - data auto-reallocated"},
+ {0x18,0x03,R,"Recovered data with circ"},
+ {0x18,0x04,R,"Recovered data with lec"},
+ {0x18,0x05,D|W|R|O,"Recovered data - recommend reassignment"},
+ {0x19,0x00,D|O,"Defect list error"},
+ {0x19,0x01,D|O,"Defect list not available"},
+ {0x19,0x02,D|O,"Defect list error in primary list"},
+ {0x19,0x03,D|O,"Defect list error in grown list"},
+ {0x1A,0x00,D|T|L|P|W|R|S|O|M|C,"Parameter list length error"},
+ {0x1B,0x00,D|T|L|P|W|R|S|O|M|C,"Synchronous data transfer error"},
+ {0x1C,0x00,D|O,"Defect list not found"},
+ {0x1C,0x01,D|O,"Primary defect list not found"},
+ {0x1C,0x02,D|O,"Grown defect list not found"},
+ {0x1D,0x00,D|W|O,"Miscompare during verify operation"},
+ {0x1E,0x00,D|W|O,"Recovered id with ecc correction"},
+ {0x20,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid command operation code"},
+ {0x21,0x00,D|T|W|R|O|M,"Logical block address out of range"},
+ {0x21,0x01,M,"Invalid element address"},
+ {0x22,0x00,D,"Illegal function (should use 20 00, 24 00, or 26 00)"},
+ {0x24,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid field in cdb"},
+ {0x25,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit not supported"},
+ {0x26,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid field in parameter list"},
+ {0x26,0x01,D|T|L|P|W|R|S|O|M|C,"Parameter not supported"},
+ {0x26,0x02,D|T|L|P|W|R|S|O|M|C,"Parameter value invalid"},
+ {0x26,0x03,D|T|L|P|W|R|S|O|M|C,"Threshold parameters not supported"},
+ {0x27,0x00,D|T|W|O,"Write protected"},
+ {0x28,0x00,D|T|L|P|W|R|S|O|M|C,"Not ready to ready transition (medium may have changed)"},
+ {0x28,0x01,M,"Import or export element accessed"},
+ {0x29,0x00,D|T|L|P|W|R|S|O|M|C,"Power on, reset, or bus device reset occurred"},
+ {0x2A,0x00,D|T|L|W|R|S|O|M|C,"Parameters changed"},
+ {0x2A,0x01,D|T|L|W|R|S|O|M|C,"Mode parameters changed"},
+ {0x2A,0x02,D|T|L|W|R|S|O|M|C,"Log parameters changed"},
+ {0x2B,0x00,D|T|L|P|W|R|S|O|C,"Copy cannot execute since host cannot disconnect"},
+ {0x2C,0x00,D|T|L|P|W|R|S|O|M|C,"Command sequence error"},
+ {0x2C,0x01,S,"Too many windows specified"},
+ {0x2C,0x02,S,"Invalid combination of windows specified"},
+ {0x2D,0x00,T,"Overwrite error on update in place"},
+ {0x2F,0x00,D|T|L|P|W|R|S|O|M|C,"Commands cleared by another initiator"},
+ {0x30,0x00,D|T|W|R|O|M,"Incompatible medium installed"},
+ {0x30,0x01,D|T|W|R|O,"Cannot read medium - unknown format"},
+ {0x30,0x02,D|T|W|R|O,"Cannot read medium - incompatible format"},
+ {0x30,0x03,D|T,"Cleaning cartridge installed"},
+ {0x31,0x00,D|T|W|O,"Medium format corrupted"},
+ {0x31,0x01,D|L|O,"Format command failed"},
+ {0x32,0x00,D|W|O,"No defect spare location available"},
+ {0x32,0x01,D|W|O,"Defect list update failure"},
+ {0x33,0x00,T,"Tape length error"},
+ {0x36,0x00,L,"Ribbon, ink, or toner failure"},
+ {0x37,0x00,D|T|L|W|R|S|O|M|C,"Rounded parameter"},
+ {0x39,0x00,D|T|L|W|R|S|O|M|C,"Saving parameters not supported"},
+ {0x3A,0x00,D|T|L|W|R|S|O|M,"Medium not present"},
+ {0x3B,0x00,T|L,"Sequential positioning error"},
+ {0x3B,0x01,T,"Tape position error at beginning-of-medium"},
+ {0x3B,0x02,T,"Tape position error at end-of-medium"},
+ {0x3B,0x03,L,"Tape or electronic vertical forms unit not ready"},
+ {0x3B,0x04,L,"Slew failure"},
+ {0x3B,0x05,L,"Paper jam"},
+ {0x3B,0x06,L,"Failed to sense top-of-form"},
+ {0x3B,0x07,L,"Failed to sense bottom-of-form"},
+ {0x3B,0x08,T,"Reposition error"},
+ {0x3B,0x09,S,"Read past end of medium"},
+ {0x3B,0x0A,S,"Read past beginning of medium"},
+ {0x3B,0x0B,S,"Position past end of medium"},
+ {0x3B,0x0C,S,"Position past beginning of medium"},
+ {0x3B,0x0D,M,"Medium destination element full"},
+ {0x3B,0x0E,M,"Medium source element empty"},
+ {0x3D,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid bits in identify message"},
+ {0x3E,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit has not self-configured yet"},
+ {0x3F,0x00,D|T|L|P|W|R|S|O|M|C,"Target operating conditions have changed"},
+ {0x3F,0x01,D|T|L|P|W|R|S|O|M|C,"Microcode has been changed"},
+ {0x3F,0x02,D|T|L|P|W|R|S|O|M|C,"Changed operating definition"},
+ {0x3F,0x03,D|T|L|P|W|R|S|O|M|C,"Inquiry data has changed"},
+ {0x43,0x00,D|T|L|P|W|R|S|O|M|C,"Message error"},
+ {0x44,0x00,D|T|L|P|W|R|S|O|M|C,"Internal target failure"},
+ {0x45,0x00,D|T|L|P|W|R|S|O|M|C,"Select or reselect failure"},
+ {0x46,0x00,D|T|L|P|W|R|S|O|M|C,"Unsuccessful soft reset"},
+ {0x47,0x00,D|T|L|P|W|R|S|O|M|C,"Scsi parity error"},
+ {0x48,0x00,D|T|L|P|W|R|S|O|M|C,"Initiator detected error message received"},
+ {0x49,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid message error"},
+ {0x4A,0x00,D|T|L|P|W|R|S|O|M|C,"Command phase error"},
+ {0x4B,0x00,D|T|L|P|W|R|S|O|M|C,"Data phase error"},
+ {0x4C,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit failed self-configuration"},
+ {0x4E,0x00,D|T|L|P|W|R|S|O|M|C,"Overlapped commands attempted"},
+ {0x50,0x00,T,"Write append error"},
+ {0x50,0x01,T,"Write append position error"},
+ {0x50,0x02,T,"Position error related to timing"},
+ {0x51,0x00,T|O,"Erase failure"},
+ {0x52,0x00,T,"Cartridge fault"},
+ {0x53,0x00,D|T|L|W|R|S|O|M,"Media load or eject failed"},
+ {0x53,0x01,T,"Unload tape failure"},
+ {0x53,0x02,D|T|W|R|O|M,"Medium removal prevented"},
+ {0x54,0x00,P,"Scsi to host system interface failure"},
+ {0x55,0x00,P,"System resource failure"},
+ {0x57,0x00,R,"Unable to recover table-of-contents"},
+ {0x58,0x00,O,"Generation does not exist"},
+ {0x59,0x00,O,"Updated block read"},
+ {0x5A,0x00,D|T|L|P|W|R|S|O|M,"Operator request or state change input (unspecified)"},
+ {0x5A,0x01,D|T|W|R|O|M,"Operator medium removal request"},
+ {0x5A,0x02,D|T|W|O,"Operator selected write protect"},
+ {0x5A,0x03,D|T|W|O,"Operator selected write permit"},
+ {0x5B,0x00,D|T|L|P|W|R|S|O|M,"Log exception"},
+ {0x5B,0x01,D|T|L|P|W|R|S|O|M,"Threshold condition met"},
+ {0x5B,0x02,D|T|L|P|W|R|S|O|M,"Log counter at maximum"},
+ {0x5B,0x03,D|T|L|P|W|R|S|O|M,"Log list codes exhausted"},
+ {0x5C,0x00,D|O,"Rpl status change"},
+ {0x5C,0x01,D|O,"Spindles synchronized"},
+ {0x5C,0x02,D|O,"Spindles not synchronized"},
+ {0x60,0x00,S,"Lamp failure"},
+ {0x61,0x00,S,"Video acquisition error"},
+ {0x61,0x01,S,"Unable to acquire video"},
+ {0x61,0x02,S,"Out of focus"},
+ {0x62,0x00,S,"Scan head positioning error"},
+ {0x63,0x00,R,"End of user area encountered on this track"},
+ {0x64,0x00,R,"Illegal mode for this track"},
+ {0, 0, 0, NULL}
+};
+
+static const char *snstext[] = {
+ "None", /* There is no sense information */
+ "Recovered Error", /* The last command completed successfully
+ but used error correction */
+ "Not Ready", /* The addressed target is not ready */
+ "Medium Error", /* Data error detected on the medium */
+ "Hardware Error", /* Controller or device failure */
+ "Illegal Request",
+ "Unit Attention", /* Removable medium was changed, or
+ the target has been reset */
+ "Data Protect", /* Access to the data is blocked */
+ "Blank Check", /* Reached unexpected written or unwritten
+ region of the medium */
+ "Key=9", /* Vendor specific */
+ "Copy Aborted", /* COPY or COMPARE was aborted */
+ "Aborted Command", /* The target aborted the command */
+ "Equal", /* A SEARCH DATA command found data equal */
+ "Volume Overflow", /* Medium full with still data to be written */
+ "Miscompare", /* Source data and data on the medium
+ do not agree */
+ "Key=15" /* Reserved */
+};
+
+/* Print sense information */
+void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
+ int sb_len)
+{
+ int i, s;
+ int sense_class, valid, code;
+ const char * error = NULL;
+
+ sense_class = (sense_buffer[0] >> 4) & 0x07;
+ code = sense_buffer[0] & 0xf;
+ valid = sense_buffer[0] & 0x80;
+
+ if (sense_class == 7) { /* extended sense data */
+ s = sense_buffer[7] + 8;
+ if(s > sb_len)
+ s = sb_len;
+
+ if (!valid)
+ fprintf(OUTP, "[valid=0] ");
+ fprintf(OUTP, "Info fld=0x%x, ", (int)((sense_buffer[3] << 24) |
+ (sense_buffer[4] << 16) | (sense_buffer[5] << 8) |
+ sense_buffer[6]));
+
+ if (sense_buffer[2] & 0x80)
+ fprintf(OUTP, "FMK "); /* current command has read a filemark */
+ if (sense_buffer[2] & 0x40)
+ fprintf(OUTP, "EOM "); /* end-of-medium condition exists */
+ if (sense_buffer[2] & 0x20)
+ fprintf(OUTP, "ILI "); /* incorrect block length requested */
+
+ switch (code) {
+ case 0x0:
+ error = "Current"; /* error concerns current command */
+ break;
+ case 0x1:
+ error = "Deferred"; /* error concerns some earlier command */
+ /* e.g., an earlier write to disk cache succeeded, but
+ now the disk discovers that it cannot write the data */
+ break;
+ default:
+ error = "Invalid";
+ }
+
+ fprintf(OUTP, "%s ", error);
+
+ if (leadin)
+ fprintf(OUTP, "%s: ", leadin);
+ fprintf(OUTP, "sense key: %s\n", snstext[sense_buffer[2] & 0x0f]);
+
+ /* Check to see if additional sense information is available */
+ if(sense_buffer[7] + 7 < 13 ||
+ (sense_buffer[12] == 0 && sense_buffer[13] == 0)) goto done;
+
+ for(i=0; additional[i].text; i++)
+ if(additional[i].code1 == sense_buffer[12] &&
+ additional[i].code2 == sense_buffer[13])
+ fprintf(OUTP, "Additional sense indicates: %s\n",
+ additional[i].text);
+
+ for(i=0; additional2[i].text; i++)
+ if(additional2[i].code1 == sense_buffer[12] &&
+ additional2[i].code2_min >= sense_buffer[13] &&
+ additional2[i].code2_max <= sense_buffer[13]) {
+ fprintf(OUTP, "Additional sense indicates: ");
+ fprintf(OUTP, additional2[i].text, sense_buffer[13]);
+ fprintf(OUTP, "\n");
+ };
+ } else { /* non-extended sense data */
+
+ /*
+ * Standard says:
+ * sense_buffer[0] & 0200 : address valid
+ * sense_buffer[0] & 0177 : vendor-specific error code
+ * sense_buffer[1] & 0340 : vendor-specific
+ * sense_buffer[1..3] : 21-bit logical block address
+ */
+
+ if (leadin)
+ fprintf(OUTP, "%s: ", leadin);
+ if (sense_buffer[0] < 15)
+ fprintf(OUTP,
+ "old sense: key %s\n", snstext[sense_buffer[0] & 0x0f]);
+ else
+ fprintf(OUTP, "sns = %2x %2x\n", sense_buffer[0], sense_buffer[2]);
+
+ fprintf(OUTP, "Non-extended sense class %d code 0x%0x ",
+ sense_class, code);
+ s = 4;
+ }
+
+ done:
+ fprintf(OUTP, "Raw sense data (in hex):\n ");
+ for (i = 0; i < s; ++i) {
+ if ((i > 0) && (0 == (i % 24)))
+ fprintf(OUTP, "\n ");
+ fprintf(OUTP, "%02x ", sense_buffer[i]);
+ }
+ fprintf(OUTP, "\n");
+ return;
+}
+
+static const char * hostbyte_table[]={
+"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
+"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
+"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL};
+
+void sg_print_host_status(int host_status)
+{ static int maxcode=0;
+ int i;
+
+ if(! maxcode) {
+ for(i = 0; hostbyte_table[i]; i++) ;
+ maxcode = i-1;
+ }
+ fprintf(OUTP, "Host_status=0x%02x", host_status);
+ if(host_status > maxcode) {
+ fprintf(OUTP, "is invalid ");
+ return;
+ }
+ fprintf(OUTP, "(%s) ",hostbyte_table[host_status]);
+}
+
+static const char * driverbyte_table[]={
+"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
+"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE", NULL};
+
+static const char * driversuggest_table[]={"SUGGEST_OK",
+"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
+unknown,unknown,unknown, "SUGGEST_SENSE",NULL};
+
+
+void sg_print_driver_status(int driver_status)
+{
+ static int driver_max =0 , suggest_max=0;
+ int i;
+ int dr = driver_status & SG_ERR_DRIVER_MASK;
+ int su = (driver_status & SG_ERR_SUGGEST_MASK) >> 4;
+
+ if(! driver_max) {
+ for(i = 0; driverbyte_table[i]; i++) ;
+ driver_max = i;
+ for(i = 0; driversuggest_table[i]; i++) ;
+ suggest_max = i;
+ }
+ fprintf(OUTP, "Driver_status=0x%02x",driver_status);
+ fprintf(OUTP, " (%s,%s) ",
+ dr < driver_max ? driverbyte_table[dr]:"invalid",
+ su < suggest_max ? driversuggest_table[su]:"invalid");
+}
+
+#ifdef SG_IO
+int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp)
+{
+ return sg_chk_n_print(leadin, hp->masked_status, hp->host_status,
+ hp->driver_status, hp->sbp, hp->sb_len_wr);
+}
+#endif
+
+int sg_chk_n_print(const char * leadin, int masked_status,
+ int host_status, int driver_status,
+ const unsigned char * sense_buffer, int sb_len)
+{
+ int done_leadin = 0;
+ int done_sense = 0;
+
+ if ((0 == masked_status) && (0 == host_status) &&
+ (0 == driver_status))
+ return 1; /* No problems */
+ if (0 != masked_status) {
+ if (leadin)
+ fprintf(OUTP, "%s: ", leadin);
+ done_leadin = 1;
+ sg_print_status(masked_status);
+ fprintf(OUTP, "\n");
+ if (sense_buffer && ((masked_status == CHECK_CONDITION) ||
+ (masked_status == COMMAND_TERMINATED))) {
+ sg_print_sense(0, sense_buffer, sb_len);
+ done_sense = 1;
+ }
+ }
+ if (0 != host_status) {
+ if (leadin && (! done_leadin))
+ fprintf(OUTP, "%s: ", leadin);
+ if (done_leadin)
+ fprintf(OUTP, "plus...: ");
+ else
+ done_leadin = 1;
+ sg_print_host_status(host_status);
+ fprintf(OUTP, "\n");
+ }
+ if (0 != driver_status) {
+ if (leadin && (! done_leadin))
+ fprintf(OUTP, "%s: ", leadin);
+ if (done_leadin)
+ fprintf(OUTP, "plus...: ");
+ else
+ done_leadin = 1;
+ sg_print_driver_status(driver_status);
+ fprintf(OUTP, "\n");
+ if (sense_buffer && (! done_sense) &&
+ (SG_ERR_DRIVER_SENSE & driver_status))
+ sg_print_sense(0, sense_buffer, sb_len);
+ }
+ return 0;
+}
+
+#ifdef SG_IO
+int sg_err_category3(struct sg_io_hdr * hp)
+{
+ return sg_err_category(hp->masked_status, hp->host_status,
+ hp->driver_status, hp->sbp, hp->sb_len_wr);
+}
+#endif
+
+int sg_err_category(int masked_status, int host_status,
+ int driver_status, const unsigned char * sense_buffer,
+ int sb_len)
+{
+ if ((0 == masked_status) && (0 == host_status) &&
+ (0 == driver_status))
+ return SG_ERR_CAT_CLEAN;
+ if ((CHECK_CONDITION == masked_status) ||
+ (COMMAND_TERMINATED == masked_status) ||
+ (SG_ERR_DRIVER_SENSE & driver_status)) {
+ if (sense_buffer && (sb_len > 2)) {
+ if(RECOVERED_ERROR == sense_buffer[2])
+ return SG_ERR_CAT_RECOVERED;
+ else if ((UNIT_ATTENTION == (0x0f & sense_buffer[2])) &&
+ (sb_len > 12)) {
+ if (0x28 == sense_buffer[12])
+ return SG_ERR_CAT_MEDIA_CHANGED;
+ if (0x29 == sense_buffer[12])
+ return SG_ERR_CAT_RESET;
+ }
+ }
+ return SG_ERR_CAT_SENSE;
+ }
+ if (0 != host_status) {
+ if ((SG_ERR_DID_NO_CONNECT == host_status) ||
+ (SG_ERR_DID_BUS_BUSY == host_status) ||
+ (SG_ERR_DID_TIME_OUT == host_status))
+ return SG_ERR_CAT_TIMEOUT;
+ }
+ if (0 != driver_status) {
+ if (SG_ERR_DRIVER_TIMEOUT == driver_status)
+ return SG_ERR_CAT_TIMEOUT;
+ }
+ return SG_ERR_CAT_OTHER;
+}
+
+int sg_get_command_size(unsigned char opcode)
+{
+ return COMMAND_SIZE(opcode);
+}
diff --git a/sg_err.h b/sg_err.h
new file mode 100644
index 0000000..fd59e3b
--- /dev/null
+++ b/sg_err.h
@@ -0,0 +1,140 @@
+#ifndef SG_ERR_H
+#define SG_ERR_H
+
+/* Feel free to copy and modify this GPL-ed code into your applications. */
+
+/* Version 0.84 (20010115)
+ - all output now sent to stderr rather thatn stdout
+ - remove header files included in this file
+*/
+
+
+/* Some of the following error/status codes are exchanged between the
+ various layers of the SCSI sub-system in Linux and should never
+ reach the user. They are placed here for completeness. What appears
+ here is copied from drivers/scsi/scsi.h which is not visible in
+ the user space. */
+
+/* The following are 'host_status' codes */
+#ifndef DID_OK
+#define DID_OK 0x00
+#endif
+#ifndef DID_NO_CONNECT
+#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */
+#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */
+#define DID_TIME_OUT 0x03 /* Timed out for some other reason */
+#define DID_BAD_TARGET 0x04 /* Bad target (id?) */
+#define DID_ABORT 0x05 /* Told to abort for some other reason */
+#define DID_PARITY 0x06 /* Parity error (on SCSI bus) */
+#define DID_ERROR 0x07 /* Internal error */
+#define DID_RESET 0x08 /* Reset by somebody */
+#define DID_BAD_INTR 0x09 /* Received an unexpected interrupt */
+#define DID_PASSTHROUGH 0x0a /* Force command past mid-level */
+#define DID_SOFT_ERROR 0x0b /* The low-level driver wants a retry */
+#endif
+
+/* These defines are to isolate applictaions from kernel define changes */
+#define SG_ERR_DID_OK DID_OK
+#define SG_ERR_DID_NO_CONNECT DID_NO_CONNECT
+#define SG_ERR_DID_BUS_BUSY DID_BUS_BUSY
+#define SG_ERR_DID_TIME_OUT DID_TIME_OUT
+#define SG_ERR_DID_BAD_TARGET DID_BAD_TARGET
+#define SG_ERR_DID_ABORT DID_ABORT
+#define SG_ERR_DID_PARITY DID_PARITY
+#define SG_ERR_DID_ERROR DID_ERROR
+#define SG_ERR_DID_RESET DID_RESET
+#define SG_ERR_DID_BAD_INTR DID_BAD_INTR
+#define SG_ERR_DID_PASSTHROUGH DID_PASSTHROUGH
+#define SG_ERR_DID_SOFT_ERROR DID_SOFT_ERROR
+
+/* The following are 'driver_status' codes */
+#ifndef DRIVER_OK
+#define DRIVER_OK 0x00
+#endif
+#ifndef DRIVER_BUSY
+#define DRIVER_BUSY 0x01
+#define DRIVER_SOFT 0x02
+#define DRIVER_MEDIA 0x03
+#define DRIVER_ERROR 0x04
+#define DRIVER_INVALID 0x05
+#define DRIVER_TIMEOUT 0x06
+#define DRIVER_HARD 0x07
+#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */
+
+/* Following "suggests" are "or-ed" with one of previous 8 entries */
+#define SUGGEST_RETRY 0x10
+#define SUGGEST_ABORT 0x20
+#define SUGGEST_REMAP 0x30
+#define SUGGEST_DIE 0x40
+#define SUGGEST_SENSE 0x80
+#define SUGGEST_IS_OK 0xff
+#endif
+#ifndef DRIVER_MASK
+#define DRIVER_MASK 0x0f
+#endif
+#ifndef SUGGEST_MASK
+#define SUGGEST_MASK 0xf0
+#endif
+
+/* These defines are to isolate applictaions from kernel define changes */
+#define SG_ERR_DRIVER_OK DRIVER_OK
+#define SG_ERR_DRIVER_BUSY DRIVER_BUSY
+#define SG_ERR_DRIVER_SOFT DRIVER_SOFT
+#define SG_ERR_DRIVER_MEDIA DRIVER_MEDIA
+#define SG_ERR_DRIVER_ERROR DRIVER_ERROR
+#define SG_ERR_DRIVER_INVALID DRIVER_INVALID
+#define SG_ERR_DRIVER_TIMEOUT DRIVER_TIMEOUT
+#define SG_ERR_DRIVER_HARD DRIVER_HARD
+#define SG_ERR_DRIVER_SENSE DRIVER_SENSE
+#define SG_ERR_SUGGEST_RETRY SUGGEST_RETRY
+#define SG_ERR_SUGGEST_ABORT SUGGEST_ABORT
+#define SG_ERR_SUGGEST_REMAP SUGGEST_REMAP
+#define SG_ERR_SUGGEST_DIE SUGGEST_DIE
+#define SG_ERR_SUGGEST_SENSE SUGGEST_SENSE
+#define SG_ERR_SUGGEST_IS_OK SUGGEST_IS_OK
+#define SG_ERR_DRIVER_MASK DRIVER_MASK
+#define SG_ERR_SUGGEST_MASK SUGGEST_MASK
+
+
+
+/* The following "print" functions send ACSII to stdout */
+extern void sg_print_command(const unsigned char * command);
+extern void sg_print_sense(const char * leadin,
+ const unsigned char * sense_buffer, int sb_len);
+extern void sg_print_status(int masked_status);
+extern void sg_print_host_status(int host_status);
+extern void sg_print_driver_status(int driver_status);
+
+/* sg_chk_n_print() returns 1 quietly if there are no errors/warnings
+ else it prints to standard output and returns 0. */
+extern int sg_chk_n_print(const char * leadin, int masked_status,
+ int host_status, int driver_status,
+ const unsigned char * sense_buffer, int sb_len);
+
+/* The following function declaration is for the sg version 3 driver.
+ Only version 3 sg_err.c defines it. */
+struct sg_io_hdr;
+extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp);
+
+
+/* The following "category" function returns one of the following */
+#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */
+#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */
+#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */
+#define SG_ERR_CAT_TIMEOUT 3
+#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */
+#define SG_ERR_CAT_SENSE 98 /* Something else is in the sense buffer */
+#define SG_ERR_CAT_OTHER 99 /* Some other error/warning has occurred */
+
+extern int sg_err_category(int masked_status, int host_status,
+ int driver_status, const unsigned char * sense_buffer,
+ int sb_len);
+
+/* The following function declaration is for the sg version 3 driver.
+ Only version 3 sg_err.c defines it. */
+extern int sg_err_category3(struct sg_io_hdr * hp);
+
+/* Returns length of SCSI command given the opcode (first byte) */
+int sg_get_command_size(unsigned char opcode);
+
+#endif
diff --git a/tapeinfo.1 b/tapeinfo.1
new file mode 100644
index 0000000..653042f
--- /dev/null
+++ b/tapeinfo.1
@@ -0,0 +1,72 @@
+.\" tapeinfo.1 Document copyright 2000 Eric Lee Green
+.\" Program Copyright 2000 Eric Lee Green <eric@badtux.org>
+.\" Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+.\"
+.\" This is free documentation; 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.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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 manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH TAPEINFO 1 TAPEINFO1.0
+.SH NAME
+tapeinfo \- report SCSI tape device info
+.SH SYNOPSIS
+tapeinfo -f <scsi-generic-device>
+.SH DESCRIPTION
+The
+.B tapeinfo
+command reads various information from SCSI tape drives that is not
+generally available via most vendors' tape drivers. It issues raw
+commands directly to the tape drive, using either the operating system's
+SCSI generic device ( e.g. /dev/sg0 on Linux, /dev/pass0 on FreeBSD) or
+the raw SCSI I/O ioctl on a tape device on some operating systems.
+.P
+One good time to use 'tapeinfo' is immediately after a tape i/o operation has
+failed. On tape drives that support HP's 'tapealert' API, 'tapeinfo' will
+report a more exact description of what went wrong.
+.P
+Do be aware that 'tapeinfo' is not a substitute for your operating system's
+own 'mt' or similar tape driver control program. It is intended to supplement,
+not replace, programs like 'mt' that access your operating system's tape
+driver in order to report or set information.
+.SH OPTIONS
+The first argument, given following
+.B -f
+, is the SCSI generic device corresponding to your tape drive.
+Consult your operating system's documentation for more information (for
+example, under Linux these are generally start at /dev/sg0
+under FreeBSD these start at /dev/pass0).
+.P
+Under FreeBSD, 'camcontrol devlist' will tell you what SCSI devices you
+have, along with which 'pass' device controls them. Under Linux,
+"cat /proc/scsi/scsi" will tell you what SCSI devices you have.
+
+.SH BUGS AND LIMITATIONS
+.P
+This program has only been tested on Linux with a limited number of
+tape drives (HP DDS4, Seagate AIT).
+.P
+.SH AVAILABILITY
+.B tapeinfo
+is currently being maintained by Robert Nelson <robertnelson@users.sourceforge.net>
+as part of the 'mtx' suite of programs. The 'mtx' home page is
+http://mtx.sourceforge.net and the actual code is currently available there and via
+SVN from http://sourceforge.net/projects/mtx.
+
+.SH SEE ALSO
+.BR mt (1), mtx (1), scsitape (1), scsieject (1), loaderinfo (1)
diff --git a/tapeinfo.c b/tapeinfo.c
new file mode 100644
index 0000000..1a5a0cb
--- /dev/null
+++ b/tapeinfo.c
@@ -0,0 +1,969 @@
+/* Copyright 2000 Enhanced Software Technologies Inc.
+ * Copyright 2007-2008 by Robert Nelson <robertn@the-nelsons.org>
+ * Released under terms of the GNU General Public License as
+ * required by the license on 'mtxl.c'.
+ * $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $
+ * $Revision: 193 $
+ */
+
+/*#define DEBUG_PARTITION */
+/*#define DEBUG 1 */
+
+/* What this does: This basically dumps out the contents of the following
+ * pages:
+ *
+ * Inquiry -- prints full inquiry info. If it's not a tape drive, this is
+ * the end of things.
+ * DeviceType:
+ * Manufacturer:
+ * ProdID:
+ * ProdRevision:
+ *
+ * Log Sense: TapeAlert Page (if supported):
+ * TapeAlert:[message#]<Message> e.g. "TapeAlert:[22]Cleaning Cartridge Worn Out"
+ *
+ * Mode Sense:
+ * Data Compression Page:
+ * DataCompEnabled:<yes|no>
+ * DataCompCapable:<yes|no>
+ * DataDeCompEnabled:<yes|no>
+ * CompType:<number>
+ * DeCompType:<number>
+ *
+ * Device Configuration Page:
+ * ActivePartition:<#>
+ * DevConfigComp:<#> -- the compression byte in device config page.
+ * EarlyWarningSize:<#> -- size of early warning buffer?
+ *
+ * Medium Partition Page:
+ * NumPartitions:<#>
+ * MaxPartitions:<#>
+ * Partition[0]:<size>
+ * Partition[1]:<size>...
+ *
+ * Read Block Limits command:
+ * MinBlock:<#> -- Minimum block size.
+ * MaxBlock:<#> -- Maximum block size.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "mtx.h"
+#include "mtxl.h"
+
+char *argv0;
+
+void usage(void)
+{
+ FatalError("Usage: tapeinfo -f <generic-device>\n");
+}
+
+/* A table for printing out the peripheral device type as ASCII. */
+static char *PeripheralDeviceType[32] =
+{
+ "Disk Drive",
+ "Tape Drive",
+ "Printer",
+ "Processor",
+ "Write-once",
+ "CD-ROM",
+ "Scanner",
+ "Optical",
+ "Medium Changer",
+ "Communications",
+ "ASC IT8",
+ "ASC IT8",
+ "RAID Array",
+ "Enclosure Services",
+ "OCR/W",
+ "Bridging Expander", /* 0x10 */
+ "Reserved", /* 0x11 */
+ "Reserved", /* 0x12 */
+ "Reserved", /* 0x13 */
+ "Reserved", /* 0x14 */
+ "Reserved", /* 0x15 */
+ "Reserved", /* 0x16 */
+ "Reserved", /* 0x17 */
+ "Reserved", /* 0x18 */
+ "Reserved", /* 0x19 */
+ "Reserved", /* 0x1a */
+ "Reserved", /* 0x1b */
+ "Reserved", /* 0x1c */
+ "Reserved", /* 0x1d */
+ "Reserved", /* 0x1e */
+ "Unknown" /* 0x1f */
+};
+
+
+
+/* we call it MediumChangerFD for history reasons, sigh. */
+
+/* now to print inquiry information: Copied from other one.... */
+
+static void ReportInquiry(DEVICE_TYPE MediumChangerFD)
+{
+ RequestSense_T RequestSense;
+ Inquiry_T *Inquiry;
+ int i;
+
+ Inquiry = RequestInquiry(MediumChangerFD, &RequestSense);
+ if (Inquiry == NULL)
+ {
+ PrintRequestSense(&RequestSense);
+ FatalError("INQUIRY Command Failed\n");
+ }
+
+ printf("Product Type: %s\n", PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
+
+ printf("Vendor ID: '");
+ for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
+ printf("%c", Inquiry->VendorIdentification[i]);
+
+ printf("'\nProduct ID: '");
+ for (i = 0; i < sizeof(Inquiry->ProductIdentification); i++)
+ printf("%c", Inquiry->ProductIdentification[i]);
+
+ printf("'\nRevision: '");
+ for (i = 0; i < sizeof(Inquiry->ProductRevisionLevel); i++)
+ printf("%c", Inquiry->ProductRevisionLevel[i]);
+ printf("'\n");
+
+ if (Inquiry->MChngr)
+ {
+ /* check the attached-media-changer bit... */
+ printf("Attached Changer API: Yes\n");
+ }
+ else
+ {
+ printf("Attached Changer API: No\n");
+ }
+
+ free(Inquiry); /* well, we're about to exit, but ... */
+}
+
+
+
+
+/* Okay, now for the Log Sense Tape Alert Page (if supported): */
+#define TAPEALERT_SIZE 2048 /* max size of tapealert buffer. */
+#define MAX_TAPE_ALERT 0x41
+
+static char *tapealert_messages[] =
+{
+ "Undefined", /* 0 */
+ " Read: Having problems reading (slowing down)", /* 1 */
+ " Write: Having problems writing (losing capacity)", /* 2 */
+ " Hard Error: Uncorrectable read/write error", /* 3 */
+ " Media: Media Performance Degraded, Data Is At Risk", /* 4 */
+ " Read Failure: Tape faulty or tape drive broken", /* 5 */
+ "Write Failure: Tape faulty or tape drive broken", /* 6 */
+ " Media Life: The tape has reached the end of its useful life", /* 7 */
+ "Not Data Grade:Replace cartridge with one containing data grade tape",/*8*/
+ "Write Protect: Attempted to write to a write-protected cartridge",/*9 */
+ " No Removal: Cannot unload, initiator is preventing media removal", /*a*/
+ "Cleaning Media:Cannot back up or restore to a cleaning cartridge", /* b */
+ " Bad Format: The loaded tape contains data in an unsupported format", /*c */
+ " Snapped Tape: The data cartridge contains a broken tape", /* d */
+ "Undefined", /* e */
+ "Undefined", /* f */
+ "Undefined", /* 10 */
+ "Undefined", /* 11 */
+ "Undefined", /* 12 */
+ "Undefined", /* 13 */
+ " Clean Now: The tape drive neads cleaning NOW", /* 0x14 */
+ "Clean Periodic:The tape drive needs to be cleaned at next opportunity", /* 0x15 */
+ "Cleaning Media:Cannot clean because cleaning cartridge used up, insert new cleaning cartridge to clean the drive", /* 0x16 */
+ "Undefined", /* 0x17 */
+ "Undefined", /* 0x18 */
+ "Undefined", /* 0x19 */
+ "Undefined", /* 0x1a */
+ "Undefined", /* 0x1b */
+ "Undefined", /* 0x1c */
+ "Undefined", /* 0x1d */
+ " Hardware A: Tape drive has a problem not read/write related", /* 0x1e */
+ " Hardware B: Tape drive has a problem not read/write related", /* 0x1f */
+ " Interface: Problem with SCSI interface between tape drive and initiator", /* 0x20 */
+ " Eject Media: The current operation has failed. Eject and reload media", /* 0x21 */
+ "Download Fail: Attempt to download new firmware failed", /* 0x22 */
+ "Undefined", /* 0x23 */
+ "Undefined", /* 0x24 */
+ "Undefined", /* 0x25 */
+ "Undefined", /* 0x26 */
+ "Undefined", /* 0x27 */
+ "Loader Hardware A: Changer having problems communicating with tape drive", /* 0x28 40 */
+ "Loader Stray Tape: Stray tape left in drive from prior error", /* 0x29 41 */
+ "Loader Hardware B: Autoloader mechanism has a fault", /* 0x2a 42 */
+ " Loader Door: Loader door is open, please close it", /* 0x2b 43 */
+ "Undefined", /* 0x2c */
+ "Undefined", /* 0x2d */
+ "Undefined", /* 0x2e */
+ "Undefined", /* 0x2f */
+ "Undefined", /* 0x30 */
+ "Undefined", /* 0x31 */
+ "Undefined", /* 0x32 */
+ "Undefined", /* 0x33 */
+ "Undefined", /* 0x34 */
+ "Undefined", /* 0x35 */
+ "Undefined", /* 0x36 */
+ "Undefined", /* 0x37 */
+ "Undefined", /* 0x38 */
+ "Undefined", /* 0x39 */
+ "Undefined", /* 0x3a */
+ "Undefined", /* 0x3b */
+ "Undefined", /* 0x3c */
+ "Undefined", /* 0x3d */
+ "Undefined", /* 0x3e */
+ "Undefined", /* 0x3f */
+ "Undefined" /* 0x40 */
+};
+
+typedef struct TapeCapacityStruct
+{
+ unsigned int partition0_remaining;
+ unsigned int partition1_remaining;
+ unsigned int partition0_size;
+ unsigned int partition1_size;
+} TapeCapacity;
+
+#if defined(DEBUG)
+/* DEBUG */
+static void dump_data(unsigned char *data, int len)
+{
+ if (len != 0)
+ {
+ fprintf(stderr,"DATA:");
+ PrintHex(1, data, len);
+ }
+ else
+ {
+ fprintf(stderr, "**NO DATA**\n");
+ }
+}
+#endif
+
+
+/* Request the tape capacity page defined by some DAT autoloaders. */
+
+static TapeCapacity *RequestTapeCapacity(DEVICE_TYPE fd, RequestSense_T *sense)
+{
+ CDB_T CDB;
+ TapeCapacity *result;
+ int result_len;
+
+ unsigned char buffer[TAPEALERT_SIZE]; /* Overkill, but ... */
+
+ slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
+
+ /* now to create the CDB block: */
+ CDB[0] = 0x4d; /* Log Sense */
+ CDB[1] = 0;
+ CDB[2] = 0x31; /* Tape Capacity Page. */
+ CDB[3] = 0;
+ CDB[4] = 0;
+ CDB[5] = 0;
+ CDB[6] = 0;
+ CDB[7] = TAPEALERT_SIZE >> 8 & 0xff; /* hi byte, allocation size */
+ CDB[8] = TAPEALERT_SIZE & 0xff; /* lo byte, allocation size */
+ CDB[9] = 0; /* reserved */
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 10, buffer, TAPEALERT_SIZE, sense) != 0)
+ {
+ /* fprintf(stderr,"RequestTapeCapacity: Command failed: Log Sense\n"); */
+ return NULL;
+ }
+
+ /* dump_data(buffer,64); */
+
+ /* okay, we have stuff in the result buffer: the first 4 bytes are a header:
+ * byte 0 should be 0x31, byte 1 == 0, bytes 2,3 tell how long the
+ * log page is.
+ */
+ if ((buffer[0]&0x3f) != 0x31)
+ {
+ /* fprintf(stderr,"RequestTapeCapacity: Invalid header for page (not 0x31).\n"); */
+ return NULL;
+ }
+
+ result_len = ((int)buffer[2] << 8) + buffer[3];
+
+ if (result_len != 32)
+ {
+ /* fprintf(stderr,"RequestTapeCapacity: Page was %d bytes long, not 32 bytes\n",result_len); */
+ return NULL; /* This Is Not The Page You're Looking For */
+ }
+
+ result = xmalloc(sizeof(TapeCapacity));
+
+ /* okay, now allocate data and move the buffer over there: */
+
+ /* 0 1 2 3 4 5 6 7 8 9
+ DATA: 31 00 00 20 00 01 4c 04 01 3a
+ 10 11 12 13 14 15 16 17 18 19
+ DATA: 81 0c 00 02 4c 04 00 00 00 00
+ 20 21 22 23 24 25 26 27 28 29
+ DATA: 00 03 4c 04 01 3f 4b 1f 00 04
+ 30 31 32 33 34 35
+ DATA: 4c 04 00 00 00 00 00 00 00 00
+ DATA: 00 00 00 00 00 00 00 00 00 00
+ DATA: 00 00 00 00 00 00 00 00 00 00
+ DATA: 00 00 00 00
+ */
+
+ result->partition0_remaining =
+ ((unsigned int)buffer[8] << 24) +
+ ((unsigned int)buffer[9] << 16) +
+ ((unsigned int)buffer[10] << 8) +
+ buffer[11];
+
+ result->partition1_remaining =
+ ((unsigned int)buffer[16] << 24) +
+ ((unsigned int)buffer[17] << 16) +
+ ((unsigned int)buffer[18] << 8) +
+ buffer[19];
+
+ result->partition0_size =
+ ((unsigned int)buffer[24] << 24) +
+ ((unsigned int)buffer[25] << 16) +
+ ((unsigned int)buffer[26] << 8) +
+ buffer[27];
+
+ result->partition1_size =
+ ((unsigned int)buffer[32] << 24) +
+ ((unsigned int)buffer[33] << 16) +
+ ((unsigned int)buffer[34] << 8) +
+ buffer[35];
+
+ return result;
+}
+
+
+
+struct tapealert_struct
+{
+ int length;
+ unsigned char *data;
+};
+
+static struct tapealert_struct *RequestTapeAlert(DEVICE_TYPE fd, RequestSense_T *sense)
+{
+ CDB_T CDB;
+
+ struct tapealert_struct *result;
+ int i, tapealert_len, result_idx;
+
+ unsigned char buffer[TAPEALERT_SIZE];
+ unsigned char *walkptr;
+
+ slow_bzero((char *)buffer, TAPEALERT_SIZE); /*zero it... */
+
+ /* now to create the CDB block: */
+ CDB[0] = 0x4d; /* Log Sense */
+ CDB[1] = 0;
+ CDB[2] = 0x2e; /* Tape Alert Page. */
+ CDB[3] = 0;
+ CDB[4] = 0;
+ CDB[5] = 0;
+ CDB[6] = 0;
+ CDB[7] = TAPEALERT_SIZE >> 8 & 0xff; /* hi byte, allocation size */
+ CDB[8] = TAPEALERT_SIZE & 0xff; /* lo byte, allocation size */
+ CDB[9] = 0; /* reserved */
+
+ if (SCSI_ExecuteCommand(fd,Input,&CDB,10,buffer,TAPEALERT_SIZE,sense)!=0)
+ {
+ return NULL;
+ }
+
+ result = xmalloc(sizeof(struct tapealert_struct));
+
+ /* okay, we have stuff in the result buffer: the first 4 bytes are a header:
+ * byte 0 should be 0x2e, byte 1 == 0, bytes 2,3 tell how long the
+ * tapealert page is.
+ */
+ if ((buffer[0]&0x3f) != 0x2e)
+ {
+ result->data = NULL;
+ result->length = 0;
+ return result;
+ }
+
+ tapealert_len = ((int)buffer[2] << 8) + buffer[3];
+
+ if (!tapealert_len)
+ {
+ result->length = 0;
+ result->data = NULL;
+ return result;
+ }
+
+ /* okay, now allocate data and move the buffer over there: */
+ result->length = MAX_TAPE_ALERT;
+ result->data = xzmalloc(MAX_TAPE_ALERT); /* alloc & zero. */
+
+ walkptr = &buffer[4];
+ i = 0;
+
+ while (i < tapealert_len)
+ {
+ result_idx=(((int)walkptr[0])<<8) + walkptr[1]; /* the parameter #. */
+ if (result_idx > 0 && result_idx < MAX_TAPE_ALERT)
+ {
+ if (walkptr[4])
+ {
+ result->data[result_idx] = 1;
+ }
+ else
+ {
+ result->data[result_idx] = 0;
+ }
+#ifdef DEBUGOLD1
+ fprintf(stderr,"Alert[0x%x]=%d\n",result_idx,result->data[result_idx]);
+ fflush(stderr);
+#endif
+ }
+ else
+ {
+ FatalError("Invalid tapealert page: %d\n",result_idx);
+ }
+
+ i = i + 4 + walkptr[3]; /* length byte! */
+ walkptr = walkptr + 4 + walkptr[3]; /* next! */
+ }
+ return result;
+}
+
+static void ReportTapeCapacity(DEVICE_TYPE fd)
+{
+ /* we actually ignore a bad sense reading, like might happen if the
+ * tape drive does not support the tape capacity page.
+ */
+
+ RequestSense_T RequestSense;
+
+ TapeCapacity *result;
+
+ result=RequestTapeCapacity(fd,&RequestSense);
+
+ if (!result)
+ return;
+
+ printf("Partition 0 Remaining Kbytes: %d\n", result->partition0_remaining);
+ printf("Partition 0 Size in Kbytes: %d\n", result->partition0_size);
+
+ if (result->partition1_size)
+ {
+ printf("Partition 1 Remaining Kbytes: %d\n", result->partition1_remaining);
+ printf("Partition 1 Size in Kbytes: %d\n", result->partition1_size);
+ }
+
+ free(result);
+}
+
+
+
+static void ReportTapeAlert(DEVICE_TYPE fd)
+{
+ /* we actually ignore a bad sense reading, like might happen if the
+ * tape drive does not support the tapealert page.
+ */
+
+ RequestSense_T RequestSense;
+
+ struct tapealert_struct *result;
+ int i;
+
+ result=RequestTapeAlert(fd,&RequestSense);
+
+ if (!result)
+ return; /* sorry. Don't print sense here. */
+
+ if (!result->length)
+ return; /* sorry, no alerts valid. */
+
+ for (i = 0; i < result->length; i++)
+ {
+ if (result->data[i])
+ {
+ printf("TapeAlert[%d]: %s.\n", i, tapealert_messages[i]);
+ }
+ }
+
+ free(result->data);
+ free(result);
+}
+
+static unsigned char
+*mode_sense(DEVICE_TYPE fd, char pagenum, int alloc_len, RequestSense_T *RequestSense)
+{
+ CDB_T CDB;
+
+ unsigned char *input_buffer;
+ unsigned char *tmp;
+ unsigned char *retval;
+ int i, pagelen;
+
+ if (alloc_len > 255)
+ {
+ FatalError("mode_sense(6) can only read up to 255 characters!\n");
+ }
+
+ input_buffer = (unsigned char *)xzmalloc(256); /* overdo it, eh? */
+
+ /* clear the sense buffer: */
+ slow_bzero((char *)RequestSense, sizeof(RequestSense_T));
+
+ /* returns an array of bytes in the page, or, if not possible, NULL. */
+ CDB[0] = 0x1a; /* Mode Sense(6) */
+ CDB[1] = 0;
+ CDB[2] = pagenum; /* the page to read. */
+ CDB[3] = 0;
+ CDB[4] = 255; /* allocation length. This does max of 256 bytes! */
+ CDB[5] = 0;
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, input_buffer, 255, RequestSense) != 0)
+ {
+#ifdef DEBUG_MODE_SENSE
+ fprintf(stderr,"Could not execute mode sense...\n");
+ fflush(stderr);
+#endif
+ return NULL; /* sorry, couldn't do it. */
+ }
+
+ /* Oh hell, write protect is the only thing I have: always print
+ * it if our mode page was 0x0fh, before skipping past buffer:
+ * if the media is *NOT* write protected, just skip, sigh.
+ *
+ * Oh poops, the blocksize is reported in the block descriptor header
+ * < * too. Again, just print if our mode page was 0x0f...
+ */
+ if (pagenum == 0x0f)
+ {
+ int blocklen;
+
+ if (input_buffer[2] & 0x80)
+ {
+ printf("WriteProtect: yes\n");
+ }
+
+ if (input_buffer[2] & 0x70)
+ {
+ printf("BufferedMode: yes\n");
+ }
+
+ if (input_buffer[1] )
+ {
+ printf("Medium Type: 0x%x\n", input_buffer[1]);
+ }
+ else
+ {
+ printf("Medium Type: Not Loaded\n");
+ }
+
+ printf("Density Code: 0x%x\n", input_buffer[4]);
+ /* Put out the block size: */
+
+ blocklen = ((int)input_buffer[9] << 16)+
+ ((int)input_buffer[10] << 8)+
+ input_buffer[11];
+
+ printf("BlockSize: %d\n", blocklen);
+ }
+
+ /* First skip past any header.... */
+ tmp = input_buffer + 4 + input_buffer[3];
+
+ /* now find out real length of page... */
+ pagelen = tmp[1] + 2;
+ retval = xmalloc(pagelen);
+
+ /* and copy our data to the new page. */
+ for (i=0;i<pagelen;i++)
+ {
+ retval[i]=tmp[i];
+ }
+
+ /* okay, free our input buffer: */
+ free(input_buffer);
+ return retval;
+}
+
+
+#define DCE_MASK 0x80
+#define DCC_MASK 0x40
+#define DDE_MASK 0x80
+
+static void ReportCompressionPage(DEVICE_TYPE fd)
+{
+ /* actually ignore a bad sense reading, like might happen if the tape
+ * drive does not support the mode sense compression page.
+ */
+
+ RequestSense_T RequestSense;
+
+ unsigned char *compression_page;
+
+ compression_page=mode_sense(fd,0x0f,16,&RequestSense);
+
+ if (!compression_page)
+ {
+ return; /* sorry! */
+ }
+
+ /* Okay, we now have the compression page. Now print stuff from it: */
+ printf("DataCompEnabled: %s\n", (compression_page[2] & DCE_MASK)? "yes" : "no");
+ printf("DataCompCapable: %s\n", (compression_page[2] & DCC_MASK)? "yes" : "no");
+ printf("DataDeCompEnabled: %s\n", (compression_page[3] & DDE_MASK)? "yes" : "no");
+ printf("CompType: 0x%x\n",
+ (compression_page[4] << 24) +
+ (compression_page[5] << 16) +
+ (compression_page[6] << 8) +
+ compression_page[7]);
+
+ printf("DeCompType: 0x%x\n",
+ (compression_page[8] << 24) +
+ (compression_page[9] << 16) +
+ (compression_page[10] << 8) +
+ compression_page[11]);
+
+ free(compression_page);
+}
+
+/* Now for the device configuration mode page: */
+
+static void ReportConfigPage(DEVICE_TYPE fd)
+{
+ RequestSense_T RequestSense;
+ unsigned char *config_page;
+
+ config_page = mode_sense(fd, 0x10, 16, &RequestSense);
+ if (!config_page)
+ return;
+
+ /* Now to print the stuff: */
+ printf("ActivePartition: %d\n", config_page[3]);
+
+ /* The following does NOT work accurately on any tape drive I know of... */
+ /* printf("DevConfigComp: %s\n", config_page[14] ? "yes" : "no"); */
+ printf("EarlyWarningSize: %d\n",
+ (config_page[11] << 16) +
+ (config_page[12] << 8) +
+ config_page[13]);
+}
+
+/* ***************************************
+ * Medium Partition Page:
+ *
+ * The problem here, as we oh so graphically demonstrated during debugging
+ * of the Linux 'st' driver :-), is that there are actually *TWO* formats for
+ * the Medium Partition Page: There is the "long" format, where there is a
+ * partition size word for each partition on the page, and there is a "short"
+ * format, beloved of DAT drives, which only has a partition size word for
+ * partition #1 (and no partition size word for partition #0, and no
+ * provisions for any more partitions). So we must look at the size and
+ * # of partitions defined to know what to report as what.
+ *
+ ********************************************/
+
+static void ReportPartitionPage(DEVICE_TYPE fd)
+{
+ RequestSense_T RequestSense;
+ unsigned char *partition_page;
+
+ int num_parts,max_parts;
+ int i;
+
+ partition_page=mode_sense(fd,0x11,255,&RequestSense);
+ if (!partition_page)
+ return;
+
+ /* Okay, now we have either old format or new format: */
+ num_parts = partition_page[3];
+ max_parts = partition_page[2];
+
+ printf("NumPartitions: %d\n", num_parts);
+ printf("MaxPartitions: %d\n", max_parts);
+
+ if (!num_parts)
+ {
+ /* if no additional partitions, then ... */
+ free(partition_page);
+ return;
+ }
+
+ /* we know we have at least one partition if we got here. Check the
+ * page size field. If it is 8 or below, then we are the old format....
+ */
+
+#ifdef DEBUG_PARTITION
+ fprintf(stderr,"partition_page[1]=%d\n",partition_page[1]);
+ fflush(stderr);
+#endif
+ if (partition_page[1]==8)
+ {
+ /* old-style! */
+ printf("Partition1: %d\n",(partition_page[8]<<8)+partition_page[9]);
+ }
+ else
+ {
+ /* new-style! */
+ for (i=0;i<=max_parts;i++)
+ {
+#ifdef DEBUG_PARTITION
+ fprintf(stderr,"partition%d:[%d]%d [%d]%d\n", i, 8 + i * 2,
+ partition_page[8+i*2]<<8, 9+i*2,partition_page[9 + i * 2]);
+ fflush(stderr);
+#endif
+ printf("Partition%d: %d\n", i,
+ (partition_page[8 + i * 2] << 8) + partition_page[9 + i * 2]);
+ }
+ }
+ free(partition_page);
+}
+
+static void ReportSerialNumber(DEVICE_TYPE fd)
+{
+ /* Actually ignore a bad sense reading, like might happen if the
+ tape drive does not support the inquiry page 0x80.
+ */
+
+ RequestSense_T sense;
+ CDB_T CDB;
+
+#define WILD_SER_SIZE 30
+unsigned char buffer[WILD_SER_SIZE]; /* just wildly overestimate serial# length! */
+
+ int i, lim;
+ char *bufptr;
+
+ CDB[0] = 0x12; /* INQUIRY */
+ CDB[1] = 1; /* EVPD = 1 */
+ CDB[2] = 0x80; /* The serial # page, hopefully. */
+ CDB[3] = 0; /* reserved */
+ CDB[4] = WILD_SER_SIZE;
+ CDB[5] = 0;
+
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, &buffer, sizeof(buffer), &sense) != 0)
+ {
+ /* PrintRequestSense(&sense); */ /* zap debugging output :-) */
+ /* printf("No Serial Number: None\n"); */
+ return;
+ }
+
+ /* okay, we have something in our buffer. Byte 3 should be the length of
+ the sernum field, and bytes 4 onward are the serial #. */
+
+ lim = (int)buffer[3];
+ bufptr = (char *)&(buffer[4]);
+
+ printf("SerialNumber: '");
+ for (i=0;i<lim;i++)
+ {
+ putchar(*bufptr++);
+ }
+ printf("'\n");
+}
+
+/* Read Block Limits! */
+
+void ReportBlockLimits(DEVICE_TYPE fd)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+
+ CDB[0] = 0x05; /* READ_BLOCK_LIMITS */
+ CDB[1] = 0;
+ CDB[2] = 0;
+ CDB[3] = 0; /* 1-5 all unused. */
+ CDB[4] = 0;
+ CDB[5] = 0;
+
+ slow_bzero((char *)&sense,sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, buffer, 6, &sense) != 0)
+ {
+ return;
+ }
+
+ /* okay, but if we did get a result, print it: */
+ printf("MinBlock: %d\n", (buffer[4] << 8) + buffer[5]);
+ printf("MaxBlock: %d\n", (buffer[1] << 16) + (buffer[2]<<8) + buffer[3]);
+}
+
+/* Do a READ_POSITION. This may not be always valid, but (shrug). */
+void ReadPosition(DEVICE_TYPE fd)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[20];
+ unsigned int position;
+
+ CDB[0] = 0x34; /* READ_POSITION */
+ CDB[1] = 0;
+ CDB[2] = 0;
+ CDB[3] = 0; /* 1-9 all unused. */
+ CDB[4] = 0;
+ CDB[5] = 0;
+ CDB[6] = 0;
+ CDB[7] = 0;
+ CDB[8] = 0;
+ CDB[9] = 0;
+
+ slow_bzero((char *)&sense, sizeof(RequestSense_T));
+
+ SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */
+
+ /* if we don't get a result (e.g. we issue this to a disk drive), punt. */
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 10, buffer, 20, &sense) != 0)
+ {
+ return;
+ }
+
+ SCSI_Default_Timeout(); /* reset it to 5 minutes, sigh! */
+ /* okay, but if we did get a result, print it: */
+
+#define RBL_BOP 0x80
+#define RBL_EOP 0x40
+#define RBL_BCU 0x20
+#define RBL_BYCU 0x10
+#define RBL_R1 0x08
+#define RBL_BPU 0x04
+#define RBL_PERR 0x02
+
+ /* If we have BOP, go ahead and print that. */
+ if (buffer[0]&RBL_BOP)
+ {
+ printf("BOP: yes\n");
+ }
+
+ /* if we have valid data, print it: */
+ if (buffer[0]&RBL_BPU)
+ {
+ printf("Block Position: -1");
+ }
+ else
+ {
+ position = (unsigned int)(((unsigned int)buffer[4] << 24) +
+ ((unsigned int)buffer[5] << 16) +
+ ((unsigned int)buffer[6] << 8) +
+ buffer[7]);
+
+ printf("Block Position: %d\n",position);
+ }
+}
+
+/* Test unit ready: This will tell us whether the tape drive
+ * is currently ready to read or write.
+ */
+
+int TestUnitReady(DEVICE_TYPE fd)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+
+ CDB[0] = 0x00; /* TEST_UNIT_READY */
+ CDB[1] = 0;
+ CDB[2] = 0;
+ CDB[3] = 0; /* 1-5 all unused. */
+ CDB[4] = 0;
+ CDB[5] = 0;
+
+ slow_bzero((char *)&sense,sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0)
+ {
+ printf("Ready: no\n");
+ return 0;
+ }
+
+ printf("Ready: yes\n");
+ return 1;
+}
+
+/* We write a filemarks of 0 before going to grab position, in order
+ * to insure that data in the buffer is not a problem.
+ */
+
+int WriteFileMarks(DEVICE_TYPE fd,int count)
+{
+ RequestSense_T sense;
+ CDB_T CDB;
+ unsigned char buffer[6];
+
+ CDB[0] = 0x10; /* WRITE_FILE_MARKS */
+ CDB[1] = 0;
+ CDB[2] = (unsigned char)(count >> 16);
+ CDB[3] = (unsigned char)(count >> 8);
+ CDB[4] = (unsigned char)count;
+ CDB[5] = 0;
+
+ /* we really don't care if this command works or not, sigh. */
+ slow_bzero((char *)&sense, sizeof(RequestSense_T));
+ if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, buffer, 0, &sense) != 0)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* This will get the SCSI ID and LUN of the target device, if such
+ * is available from the OS. Currently only Linux supports this,
+ * but other drivers could, if someone wants to write a
+ * SCSI_GetIDLun function for them.
+ */
+#ifdef HAVE_GET_ID_LUN
+
+static void ReportIDLun(DEVICE_TYPE fd)
+{
+ scsi_id_t *scsi_id;
+
+ scsi_id = SCSI_GetIDLun(fd);
+ printf("SCSI ID: %d\nSCSI LUN: %d\n", scsi_id->id, scsi_id->lun);
+}
+
+#endif
+
+/* we only have one argument: "-f <device>". */
+int main(int argc, char **argv)
+{
+ DEVICE_TYPE fd;
+ char *filename;
+
+ argv0=argv[0];
+
+ if (argc != 3)
+ {
+ fprintf(stderr,"argc=%d",argc);
+ usage();
+ }
+
+ if (strcmp(argv[1],"-f")!=0)
+ {
+ usage();
+ }
+ filename=argv[2];
+
+ fd=SCSI_OpenDevice(filename);
+
+ /* Now to call the various routines: */
+ ReportInquiry(fd);
+ ReportSerialNumber(fd);
+ ReportTapeAlert(fd);
+ ReportBlockLimits(fd);
+
+#ifdef HAVE_GET_ID_LUN
+ ReportIDLun(fd);
+#endif
+
+ /* okay, we should only report position if the unit is ready :-(. */
+ if (TestUnitReady(fd))
+ {
+ ReportCompressionPage(fd);
+ ReadPosition(fd);
+ ReportTapeCapacity(fd); /* only if we have it */
+ ReportConfigPage(fd); /* only valid if unit is ready. */
+ ReportPartitionPage(fd);
+ }
+
+ exit(0);
+}
diff --git a/vms/000readme b/vms/000readme
new file mode 100644
index 0000000..854d58a
--- /dev/null
+++ b/vms/000readme
@@ -0,0 +1,175 @@
+MTX -- SCSI Tape Attached Medium Changer Control Program
+
+Copyright 1997 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+VMS port, April 1998, by TECSys Development, Inc.
+
+SECTION I - Disclaimer
+
+ These programs / ports are distributed in the hopes that they
+ will be useful, but WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ While a significant amount of testing has been performed, and while
+ TDI believes that this utility is safe, ONLY YOU can make that
+ determination with respect to your environment. There are NO
+ GUARANTEES WHATSOEVER that use of this program will not CRASH
+ YOUR SYSTEM or worse. TDI disclaims any responsibility for any
+ losses or damages from the use of this program.
+
+SECTION II - MTX program
+
+***CAUTIONS***
+ * Attempting to check the status of the drive with 1 tape manually
+ inserted in the drive, and no magazine results in an unexpected
+ SCSI status message. During porting of this program on a VS4000/90a,
+ it is believed that the handling of this status message caused
+ some sort of scsi state problem wherein subsequent accesses to
+ the changer from normal MKDRIVER activity resulted in SCSI bus
+ phase errors and an ultimate system failure. Power cycles of both
+ the drive and the host were required to rectify the problem.
+
+Instructions:
+ Read instructions (particularly section III below on the LDRSET utility).
+ Compile (DEC C) and link image, copy to an appropriate install location
+ Define a foreign symbol to access the program
+ Use UNIX syntax to operate program per documentation (MTX.DOC)
+
+ A descrip.mms file is provided if you have MMS or MMK installed.
+ You can build everything from scratch by doing a MMK/FROM_SOURCE. This
+ includes the LDRSET utility described below. You should be in the mtx
+ root directory before you do this, NOT [.vms].
+
+ If you do not have or use MMS or MMK, I can highly recommend MMK as
+ a great tool. It is available from www.madgoat.com. If you still do
+ not have mmk or mms, a build.com is provided. Again, you should be in
+ the mtx root directory before you do this, NOT [.vms].
+
+ Note: If you are on an alpha, the mms[k]-built exe files will be called
+ .alpha_exe, not .exe. Adjust following instructions accordingly.
+
+Example:
+ $ MMS/DESCRIP=[.VMS] !Or MMK, or @[.VMS]BUILD
+ $ copy mtx.exe DISK$USERDISK:[USERS.FRED.UTILS]MTX
+ $ MTX:==$DISK$USERDISK:[USERS.FRED.UTILS]MTX.EXE
+ $ MTX -f MKA500 status
+ --or--
+ $ DEFINE TAPE MKA500
+ $ MTX status
+
+Notes:
+ * This code does NOT compile under VAX C... the only issue is VAX C's
+ incorrect assertion that a 'boolean' is not an acceptable "expression"
+ on either side of a || operator. If you are on VAX C - upgrade. If you
+ really must... then use a ((int)...) around the left-hand-side
+ of the lines where the compiler complains.... like so:
+ if (((int)StorageElementFull[FirstStorageElementNumber]) ||
+
+ * The following symbols result from 'status' or element movement commands:
+ MTX_DTE (Data Transfer Element)
+ FULL:n (Full, with element 'n'... if n=0, then unknown ele)
+ EMPTY
+ MTX_MSZ (Magazine SiZe)
+ n (Number of magazine slots)
+ MTX_STE01 thru MTX_STExx (STorage Element, Max is MTX_MSZ)
+ FULL
+ EMPTY
+ These will allow a DCL program to process the results
+ of the status command
+
+ * PHY_IO and DIAGNOSE are required to run the program as it stands
+ today. Yes, the GKdriver dox say PHY_IO or LOG_IO.... MKdriver
+ thinks otherwise. It wins.
+
+ * The program IS equipped to handle being installed with DIAGNOSE
+ and PHY_IO. A certain level of checking is done to see that the
+ right type of device is being targeted for the autoloader manipulation
+ SCSI commands. [see next item]
+
+ * There is an indicator bit in DEVCHAR2 that indicates the presence of
+ a loader on a tape. Unfortunately, it appears that the "knowledge" of
+ whether a loader is present or not is hard-coded into mkdriver. This
+ means that if you don't have the magic DEC rom's in your Archive
+ loader, then the LDR bit is not set. This makes the LDR bit effectively
+ useless unless you want to write a kernel dinker program you could
+ run from startup to "fix" the DEVCHAR2 longword. (Incidentally,
+ if you ship the autoloader commands at a TZ30 (a non-loader drive),
+ the tz30 blows it off w/o any adverse side-effects - I would hope
+ that other drives are as tolerant.)
+
+ Because of this misfeature, the code to check the LDR flag in DEVCHAR2
+ is commented out.
+
+ *See section below on LDRSET utility if you want to use this
+ feature anyway (recommended).
+
+ * This program has been tested under:
+ VAX C V2.2, VAX/VMS 6.1, VS 4000/90A **with code modifications
+ DEC C V5.2, VAX/VMS 6.1, VS 4000/90A
+ DEC C V5.3, AXP/VMS 6.2, DEC3000-300X
+
+
+SECTION III - LDRSET Utility
+
+Description:
+ This is a small KERNEL MODE utility program to go set or reset
+ the DEV$M_LDR flag in UCB$L_DEVCHAR2 for a specified device. While
+ a certain amount of checking is performed, and while the author
+ believes that this utility is safe, ONLY YOU can make that
+ determination with respect to your environment. There are NO
+ GUARANTEES WHATSOEVER that use of this program will not CRASH
+ YOUR SYSTEM or worse. TDI disclaims any responsibility for any
+ losses or damages from the use of this program.
+
+ With all that said... this utility can be used [example: system
+ startup] to set the LDR flag for the autoloader tape device.
+ With the loader flag properly set, you can re-enable the LDR
+ check section in MTX and be fairly well certain that the MTX
+ utility will not be used against a drive that is not a SCSI
+ MAGTAPE with a LOADER attached.
+
+Instructions:
+ Compile (DEC C ***ONLY***) the LDRSET C program
+
+ Alpha:
+ MACRO/MIGRATE the LDRUTIL.MAR program
+ LINK LDRSET,LDRUTIL/SYSEXE to generate the image
+
+ Vax
+ MACRO the LDRUTIL.MAR program
+ LINK LDRSET,LDRUTIL to generate the image
+
+ [NOTE!!! ---> DO NOT USE RESULTING IMAGE IF THERE ARE ANY COMPILE OR LINK
+ ERRORS!!!]
+
+ Copy to an appropriate install location.
+
+ Edit provided CLD file to reflect the installed location
+
+ Use the following syntax:
+ $ SET COMMAND LDRSET
+ $ LDRSET MKA500: /SET !Sets the loader present flag on MKA500
+ $ LDRSET MKA500: /RESET !Clears the loader present flag on MKA500
+
+Alpha example:
+ $ CC/DECC/DEBUG/NOOPT LDRSET
+ $ MACRO/MIGRATE LDRUTIL
+ $ LINK LDRSET,LDRUTIL/SYSEXE
+
+Vax example:
+ $ CC/DECC/DEBUG/NOOPT LDRSET
+ $ MACRO LDRUTIL
+ $ LINK LDRSET,LDRUTIL
+
+Common:
+ $ copy LDRSET.EXE DISK$USERDISK:[USERS.FRED.UTILS]LDRSET.EXE
+ $ copy LDRSET.CLD DISK$USERDISK:[USERS.FRED.UTILS]LDRSET.CLD
+ $ EDIT DISK$USERDISK:[USERS.FRED.UTILS]LDRSET.CLD
+ ...change image sys$disk:[]ldrset line to :
+ image DISK$USERDISK:[USERS.FRED.UTILS]LDRSET.EXE
+ $ LDRSET MKA500 /SET
+
+ * This program has been tested under:
+ DEC C V5.2, VAX/VMS 6.1, VS 4000/90A
+ DEC C V5.6, AXP/VMS 7.1, AS 1000A
+
diff --git a/vms/build.com b/vms/build.com
new file mode 100644
index 0000000..2f6308d
--- /dev/null
+++ b/vms/build.com
@@ -0,0 +1,34 @@
+$!x='f$ver(0)
+$ if f$parse("[.VMS]A.A").eqs.""
+$ then
+$ write sys$output "?Error: Use $ @[.VMS]BUILD from the mtx directory"
+$ exit 44
+$ endif
+$ alpha = f$getsyi("hw_model").ge.1024
+$ vax = .not.alpha
+$ exe = "EXE"
+$ obj = "OBJ"
+$ sysexe=""
+$ migrate=""
+$ if alpha then exe="ALPHA_EXE"
+$ if alpha then obj="ALPHA_OBJ"
+$ if alpha then sysexe="/SYSEXE"
+$ if alpha then migrate="/MIGRATION/NOOPT"
+$ set verify
+$ if "''p1'".eqs."LINK" then goto do_link
+$ CC /DECC/DEB/NOOP MTX.C/DEB/NOOP/OBJECT=MTX.'obj'
+$ if f$search("MTX.''obj';-1").nes."" then -
+ purge/log MTX.'obj'
+$ CC /DECC/DEB/NOOP [.VMS]LDRSET.C/DEB/NOOP/OBJECT=[.VMS]LDRSET.'obj'
+$ if f$search("[.VMS]LDRSET.''obj';-1").nes."" then -
+ purge/log [.VMS]LDRSET.'obj'
+$ MACRO'migrate' /DEB [.VMS]LDRUTIL.MAR -
+ /OBJECT=[.VMS]LDRUTIL.'obj'
+$ if f$search("[.VMS]LDRUTIL.''obj';-1").nes."" then -
+ purge/log [.VMS]LDRUTIL.'obj'
+$!
+$ do_link:
+$ link/notrace mtx.'obj'/exe=mtx.'exe'
+$ link [.vms]ldrset.'obj',[.vms]ldrutil.'obj' -
+ /exe=ldrset.'exe' 'sysexe'
+$ exit
diff --git a/vms/defs.h b/vms/defs.h
new file mode 100644
index 0000000..68dd7d7
--- /dev/null
+++ b/vms/defs.h
@@ -0,0 +1,42 @@
+#ifdef __DECC
+#pragma module MTX "V01-00"
+#else
+#module MTX "V01-00"
+#endif
+
+typedef int DEVICE_TYPE;
+
+#include <ssdef.h>
+#include <lib$routines.h>
+#include <ots$routines.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <iodef.h>
+#include <descrip.h>
+#include <dcdef.h>
+#include <devdef.h>
+#include <dvidef.h>
+#include <starlet.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <prvdef.h>
+
+#if defined(__DECC)
+#pragma member_alignment save
+#pragma nomember_alignment
+#endif
+
+/*
+ Define either of the following symbols as 1 to enable checking of
+ the LDR flag for specified devices. DO NOT set these bits if you
+ do not 1) have a DEC-recognized autoloader, or 2) use the LDRSET
+ utility to set the LDR flag for the target devices.
+*/
+
+#define USING_DEC_DRIVE 0
+#define USING_LDRSET 0
+
+static unsigned long VMS_ExitCode = SS$_ABORT;
diff --git a/vms/descrip.mms b/vms/descrip.mms
new file mode 100644
index 0000000..fb08467
--- /dev/null
+++ b/vms/descrip.mms
@@ -0,0 +1,77 @@
+!
+! MMS System build for MTX and LDRSET utility
+!
+!Global build flag macros
+!
+CDEBUG = /DEB/NOOP
+MDEBUG = /DEB
+
+CFLAGS = /DECC$(CDEBUG)
+MFLAGS = $(MDEBUG)
+
+.IFDEF __AXP__
+.SUFFIXES .ALPHA_OBJ
+MFLAGS = /MIGRATE$(MFLAGS)/NOOP
+DBG = .ALPHA_DBG
+EXE = .ALPHA_EXE
+OBJ = .ALPHA_OBJ
+OPT = .ALPHA_OPT
+SYSEXE=/SYSEXE
+
+.ELSE
+DBG = .DBG
+EXE = .EXE
+OPT = .OPT
+OBJ = .OBJ
+SYSEXE=
+
+.ENDIF
+
+PURGEOBJ = if f$search("$(MMS$TARGET_NAME)$(OBJ);-1").nes."" then purge/log $(MMS$TARGET_NAME)$(OBJ)
+
+!
+!Bend the default build rules for C, MACRO, and MESSAGE
+!
+.C$(OBJ) :
+ $(CC) $(CFLAGS) $(MMS$SOURCE)$(CDEBUG)/OBJECT=$(MMS$TARGET_NAME)$(OBJ)
+ $(PURGEOBJ)
+.MAR$(OBJ) :
+ $(MACRO) $(MFLAGS) $(MMS$SOURCE)$(MDEBUG)/OBJECT=$(MMS$TARGET_NAME)$(OBJ)
+ $(PURGEOBJ)
+.CLD$(OBJ) :
+ SET COMMAND/OBJECT=$(MMS$TARGET_NAME)$(OBJ) $(MMS$SOURCE)
+ $(PURGEOBJ)
+.MSG$(OBJ) :
+ MESSAGE $(MMS$SOURCE)/OBJECT=$(MMS$TARGET_NAME)$(OBJ)
+ $(PURGEOBJ)
+
+
+DEFAULT : ERROR,-
+ MTX,-
+ LDRSET
+ @ !
+
+ERROR :
+ @ if f$parse("[.VMS]A.A").eqs."" then write sys$output "?Error: Use $ MMS/DESCRIP=[.VMS] from the mtx directory"
+
+MTX : mtx$(EXE)
+ @ !
+
+mtx$(EXE) : mtx$(OBJ)
+ $ link/notrace mtx$(OBJ)/exe=mtx$(EXE)
+
+mtx$(OBJ) : mtx.c,[.vms]scsi.c,[.vms]defs.h
+
+LDRSET : ldrset$(EXE),ldrset.cld
+ @ !
+
+ldrset.cld : [.vms]ldrset.cld
+ $ copy [.vms]ldrset.cld []/log
+
+ldrset$(EXE) : [.vms]ldrset$(OBJ),[.vms]ldrutil$(OBJ)
+ $ link [.vms]ldrset$(OBJ),[.vms]ldrutil$(OBJ)/exe=ldrset$(EXE)$(SYSEXE)
+
+[.vms]ldrset$(OBJ) : [.vms]ldrset.c
+
+[.vms]ldrutil$(OBJ) : [.vms]ldrutil.mar
+
diff --git a/vms/ldrset.c b/vms/ldrset.c
new file mode 100644
index 0000000..c0efd0c
--- /dev/null
+++ b/vms/ldrset.c
@@ -0,0 +1,183 @@
+/* LDRSET - Set the state of the LDR flag in UCB$L_DEVCHAR2 for a
+** SCSI magtape. REQUIRES CMKRNL privilege.
+**
+** Copyright 1999 by TECSys Development, Inc. http://www.tditx.com
+**
+** This program is free software; you may redistribute and/or modify it under
+** the terms of the GNU General Public License Version 2 as published by the
+** Free Software Foundation.
+**
+** 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 complete details.
+**
+** Description:
+** This is a small KERNEL MODE utility program to go set or reset
+** the DEV$M_LDR flag in UCB$L_DEVCHAR2 for a specified device. While
+** a certain amount of checking is performed, and while the author
+** believes that this utility is safe, ONLY YOU can make that
+** determination with respect to your environment. There are NO
+** GUARANTEES WHATSOEVER that use of this program will not CRASH
+** YOUR SYSTEM or worse. TDI disclaims any responsibility for any
+** losses or damages from the use of this program.
+**
+** With all that said... this utility can be used [example: system
+** startup] to set the LDR flag for the autoloader tape device.
+** With the loader flag properly set, you can re-enable the LDR
+** check section in MTX and be fairly well certain that the MTX
+** utility will not be used against a drive that is not a SCSI
+** MAGTAPE with a LOADER attached.
+**
+**
+** LDRSET.CLD:
+** define verb LDRSET
+** image sys$disk:[]ldrset.exe
+** parameter p1, label=device,
+** prompt="Device",
+** value(required,type=$FILE)
+** qualifier SET, nonnegatable
+** qualifier RESET, nonnegatable
+** disallow any2 (SET, RESET)
+** disallow NOT SET AND NOT RESET
+*/
+#ifdef __DECC
+#pragma module LDRSET "V01-00"
+#else
+#module LDRSET "V01-00"
+#endif
+
+#include <ssdef.h>
+#include <dcdef.h>
+#include <devdef.h>
+#include <dvidef.h>
+#include <descrip.h>
+#include <stdio.h>
+#include <string.h>
+#include <lib$routines.h>
+#include <starlet.h>
+
+#ifndef DESCR_CNT
+#define DESCR_CNT 16
+/* MUST BE of the form 2^N!, big enough for max concurrent usage */
+#endif
+
+static struct dsc$descriptor_s *
+descr(
+ char *str)
+{
+static struct dsc$descriptor_s d_descrtbl[DESCR_CNT]; /* MAX usage! */
+static unsigned short int descridx=0;
+ struct dsc$descriptor_s *d_ret = &d_descrtbl[descridx];
+
+ descridx = (descridx+1)&(DESCR_CNT-1);
+
+ d_ret->dsc$w_length = strlen((const char *)str);
+ d_ret->dsc$a_pointer = (char *)str;
+
+ d_ret->dsc$b_class =
+ d_ret->dsc$b_dtype = 0;
+ return(d_ret);
+}
+
+extern unsigned long int finducb();
+extern unsigned long int _setldr();
+extern unsigned long int _clrldr();
+
+unsigned long int
+set_ldrstate(
+ int devch,
+ int setstate)
+{
+ unsigned long int ret;
+ struct ucbdef *ucb;
+
+ if (~(ret=finducb(devch,&ucb))&1)
+ return(ret);
+
+ if (setstate)
+ return(_setldr(ucb));
+ else
+ return(_clrldr(ucb));
+}
+
+extern unsigned long int CLI$PRESENT();
+extern unsigned long int CLI$GET_VALUE();
+
+static unsigned long int
+cld_special(
+ char *kwd_name)
+{
+ lib$establish(lib$sig_to_ret);
+ return(CLI$PRESENT(descr(kwd_name)));
+}
+
+int
+main(){
+ unsigned long int ret;
+ unsigned long int ismnt = 0;
+ unsigned long int dvcls = 0;
+ unsigned long int dchr2 = 0;
+ struct itmlst_3 {
+ unsigned short int ilen;
+ unsigned short int code;
+ unsigned long int *returnP;
+ unsigned long int ignored;
+ } dvi_itmlst[] = {
+ {4, DVI$_MNT, 0/*&ismnt*/, 0},
+ {4, DVI$_DEVCLASS, 0/*&dvcls*/, 0},
+ {4, DVI$_DEVCHAR2, 0/*&dchr2*/, 0},
+ {0,0,0,0} };
+ unsigned long int iosb[2];
+ struct dsc$descriptor_s *dp_tmp;
+ struct dsc$descriptor_d dy_devn = { 0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0 };
+ unsigned long int devch=0;
+
+ dvi_itmlst[0].returnP = &ismnt;
+ dvi_itmlst[1].returnP = &dvcls;
+ dvi_itmlst[2].returnP = &dchr2;
+
+ if (~(ret=CLI$PRESENT(dp_tmp=descr("DEVICE")))&1) {
+ printf("?Error obtaining CLD DEVICE parameter\n");
+ return(ret); }
+ if (~(ret=CLI$GET_VALUE(dp_tmp,&dy_devn,0))&1) {
+ printf("?Error obtaining CLD DEVICE value\n");
+ return(ret); }
+
+ if (~(ret=sys$alloc(&dy_devn,0,0,0,0))&1) {
+ printf("?Error allocating specified device\n");
+ return(ret); }
+
+ if (~(ret=sys$assign(&dy_devn,&devch,0,0))&1) {
+ printf("?Error assigning a channel to specified device\n");
+ return(ret); }
+
+ if (~(ret=sys$getdviw(0,devch,0,&dvi_itmlst,&iosb,0,0,0))&1) {
+ printf("?Error obtaining device information(1)\n");
+ return(ret); }
+ if (~(ret=iosb[0])&1) {
+ printf("?Error obtaining device information(2)\n");
+ return(ret); }
+
+ if (dvcls != DC$_TAPE) {
+ printf("?Device is not a tape drive\n");
+ return(SS$_IVDEVNAM); }
+
+ if (~dchr2 & DEV$M_SCSI) {
+ printf("?Device is not a SCSI device\n");
+ return(SS$_IVDEVNAM); }
+
+ if (ismnt) {
+ printf("?Device is mounted\n");
+ return(SS$_DEVMOUNT); }
+
+ if (cld_special("SET")&1)
+ return(set_ldrstate(devch,1));
+
+ if (cld_special("RESET")&1)
+ return(set_ldrstate(devch,0));
+
+ /* Either SET or RESET above must be present to win */
+ printf("?CLD structural error - see source\n");
+ return(SS$_BADPARAM);
+}
diff --git a/vms/ldrset.cld b/vms/ldrset.cld
new file mode 100644
index 0000000..0dfc543
--- /dev/null
+++ b/vms/ldrset.cld
@@ -0,0 +1,9 @@
+define verb LDRSET
+ image sys$disk:[]ldrset.exe
+ parameter p1, label=device,
+ prompt="Device",
+ value(required,type=$FILE)
+ qualifier SET, nonnegatable
+ qualifier RESET, nonnegatable
+ disallow any2 (SET, RESET)
+ disallow NOT SET AND NOT RESET
diff --git a/vms/ldrutil.mar b/vms/ldrutil.mar
new file mode 100644
index 0000000..9d0ea31
--- /dev/null
+++ b/vms/ldrutil.mar
@@ -0,0 +1,104 @@
+ .title LDRUTIL - Obtain ucb for assigned channel
+ .ident /LDRUTIL V1.0/
+; LDRUTIL - VMS UCB LDR bit utility library
+;
+; TECSys Development, Inc., April 1998
+;
+; This file may be copied under the terms and conditions of version 2
+; of the GNU General Public License, as published by the Free
+; Software Foundation (Cambridge, Massachusetts).
+;
+; 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+;
+;
+ .link "sys$system:sys.stb"/selective_search
+ .library /sys$share:lib/
+
+ .NTYPE ...IS_IT_ALPHA,R22 ;Get the type of R22
+ ...IS_IT_ALPHA = <...IS_IT_ALPHA@-4&^XF>-5
+ .IIF EQ,...IS_IT_ALPHA, ALPHA=1
+
+ $ssdef
+ $ucbdef
+ $ccbdef
+ $chfdef
+ $dcdef
+ $devdef
+ $pcbdef
+
+ .psect $$code,exe,rd,nowrt,shr
+.IF NDF,ALPHA
+.entry finducb,^m<r2,r3,r4,r5,r6,r7,r8,r9> ;Find UCB address from channel
+.IFF
+.call_entry, 2,home_args=TRUE,-
+ preserve=<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>,-
+ output=<r0,r1>,-
+ label=finducb
+.endc
+ movzwl 4(AP),r0 ;prep to find UCB
+ jsb g^IOC$VERIFYCHAN ;callable from user mode!
+ blbc r0,20$
+ movl CCB$L_UCB(r1),@8(AP) ;save UCB address
+ movzbl #1,r0
+20$: ret
+
+.IF NDF,ALPHA
+.entry __setldr,^m<r2,r3,r4,r5,r6,r7,r8,r9> ;Find UCB address from channel
+.IFF
+.call_entry, 2,home_args=TRUE,-
+ preserve=<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>,-
+ output=<r0,r1>,-
+ label=__setldr
+.endc
+ movl 4(AP),r1
+ bisl #DEV$M_LDR,UCB$L_DEVCHAR2(r1)
+ movzbl #1,r0
+ ret
+
+.IF NDF,ALPHA
+.entry _setldr,^m<r2,r3,r4,r5,r6,r7,r8,r9> ;Find UCB address from channel
+.IFF
+.call_entry, 2,home_args=TRUE,-
+ preserve=<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>,-
+ output=<r0,r1>,-
+ label=_setldr
+.endc
+ $cmkrnl_s -
+ routin = __setldr,-
+ arglst = (AP)
+ ret
+
+.IF NDF,ALPHA
+.entry __clrldr,^m<r2,r3,r4,r5,r6,r7,r8,r9> ;Find UCB address from channel
+.IFF
+.call_entry, 2,home_args=TRUE,-
+ preserve=<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>,-
+ output=<r0,r1>,-
+ label=__clrldr
+.endc
+ movl 4(AP),r1
+ bicl #DEV$M_LDR,UCB$L_DEVCHAR2(r1)
+ movzbl #1,r0
+ ret
+
+.IF NDF,ALPHA
+.entry _clrldr,^m<r2,r3,r4,r5,r6,r7,r8,r9> ;Find UCB address from channel
+.IFF
+.call_entry, 2,home_args=TRUE,-
+ preserve=<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>,-
+ output=<r0,r1>,-
+ label=_clrldr
+.endc
+ $cmkrnl_s -
+ routin = __clrldr,-
+ arglst = (AP)
+ ret
+
+ .end
diff --git a/vms/scsi.c b/vms/scsi.c
new file mode 100644
index 0000000..5b32572
--- /dev/null
+++ b/vms/scsi.c
@@ -0,0 +1,400 @@
+/* SCSI.C - VMS-specific SCSI routines.
+**
+** TECSys Development, Inc., April 1998
+**
+** This module began life as a program called CDWRITE20, a CD-R control
+** program for VMS. No real functionality from the original CDWRITE20
+** is present in this module, but in the interest of making certain that
+** proper credit is given where it may be due, the copyrights and inclusions
+** from the CDWRITE20 program are included below.
+**
+** The portions of coding in this module ascribable to TECSys Development
+** are hereby also released under the terms and conditions of version 2
+** of the GNU General Public License as described below....
+*/
+
+/* The remainder of these credits are included directly from the CDWRITE20
+** sources. */
+
+/* Copyright 1994 Yggdrasil Computing, Inc. */
+/* Written by Adam J. Richter (adam@yggdrasil.com) */
+
+/* Rewritten February 1997 by Eberhard Heuser-Hofmann*/
+/* using the OpenVMS generic scsi-interface */
+/* see the README-file, how to setup your machine */
+
+/*
+** Modified March 1997 by John Vottero to use overlapped, async I/O
+** and lots of buffers to help prevent buffer underruns.
+** Also improved error reporting.
+*/
+
+/* This file may be copied under the terms and conditions of version 2
+ of the GNU General Public License, as published by the Free
+ Software Foundation (Cambridge, Massachusetts).
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The second notice comes from sys$examples:gktest.c (OpenVMS 7.0)*/
+
+/*
+** COPYRIGHT (c) 1993 BY
+** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.
+** ALL RIGHTS RESERVED.
+**
+** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
+** ONLY IN ACCORDANCE OF THE TERMS OF SUCH LICENSE AND WITH THE
+** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
+** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
+** OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
+** TRANSFERRED.
+**
+** THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
+** AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
+** CORPORATION.
+**
+** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
+** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
+*/
+
+/*
+ Define the Generic SCSI Command Descriptor.
+*/
+
+typedef struct scsi$desc
+{
+ unsigned int SCSI$L_OPCODE; /* SCSI Operation Code */
+ unsigned int SCSI$L_FLAGS; /* SCSI Flags Bit Map */
+ unsigned char *SCSI$A_CMD_ADDR; /* ->SCSI Command Buffer */
+ unsigned int SCSI$L_CMD_LEN; /* SCSI Command Length (bytes) */
+ unsigned char *SCSI$A_DATA_ADDR; /* ->SCSI Data Buffer */
+ unsigned int SCSI$L_DATA_LEN; /* SCSI Data Length (bytes) */
+ unsigned int SCSI$L_PAD_LEN; /* SCSI Pad Length (bytes) */
+ unsigned int SCSI$L_PH_CH_TMOUT; /* SCSI Phase Change Timeout (seconds) */
+ unsigned int SCSI$L_DISCON_TMOUT; /* SCSI Disconnect Timeout (seconds) */
+ unsigned int SCSI$L_RES_1; /* Reserved */
+ unsigned int SCSI$L_RES_2; /* Reserved */
+ unsigned int SCSI$L_RES_3; /* Reserved */
+ unsigned int SCSI$L_RES_4; /* Reserved */
+ unsigned int SCSI$L_RES_5; /* Reserved */
+ unsigned int SCSI$L_RES_6; /* Reserved */
+}
+SCSI$DESC;
+
+
+/*
+ Define the SCSI Input/Output Status Block.
+*/
+
+typedef struct scsi$iosb
+{
+ unsigned short SCSI$W_VMS_STAT; /* VMS Status Code */
+ unsigned long SCSI$L_IOSB_TFR_CNT; /* Actual Byte Count Transferred */
+ unsigned char SCSI$B_IOSB_FILL_1; /* Unused */
+ unsigned char SCSI$B_IOSB_STS; /* SCSI Device Status */
+}
+SCSI$IOSB;
+
+
+/*
+ Define the VMS symbolic representation for a successful SCSI command.
+*/
+
+#define SCSI$K_GOOD 0
+
+
+/*
+ Define the SCSI Flag Field Constants.
+*/
+
+#define SCSI$K_WRITE 0x0 /* Data Transfer Direction: Write */
+#define SCSI$K_READ 0x1 /* Data Transfer Direction: Read */
+#define SCSI$K_FL_ENAB_DIS 0x2 /* Enable Disconnect/Reconnect */
+
+
+/*
+ Define DESCR_CNT. It must be a power of two and large enough
+ for the maximum concurrent usage of descriptors.
+*/
+
+#define DESCR_CNT 16
+
+
+#define MK_EFN 0 /* Event Flag Number */
+#define FailureStatusP(Status) (~(Status) & 1)
+
+
+static struct dsc$descriptor_s *descr(char *String)
+{
+ static struct dsc$descriptor_s d_descrtbl[DESCR_CNT];
+ static unsigned short descridx = 0;
+ struct dsc$descriptor_s *d_ret = &d_descrtbl[descridx];
+ descridx = (descridx + 1) & (DESCR_CNT - 1);
+ d_ret->dsc$w_length = strlen((const char *) String);
+ d_ret->dsc$a_pointer = String;
+ d_ret->dsc$b_class = 0;
+ d_ret->dsc$b_dtype = 0;
+
+ return d_ret;
+}
+
+
+static int SCSI_OpenDevice(char *DeviceName)
+{
+ unsigned long d_dev[2], iosb[2], Status;
+ union prvdef setprivs, newprivs;
+ unsigned long ismnt = 0;
+ unsigned long dvcls = 0;
+ unsigned long dchr2 = 0;
+ int DeviceFD = 0;
+ struct itmlst_3
+ {
+ unsigned short ilen;
+ unsigned short code;
+ unsigned long *returnP;
+ unsigned long ignored;
+ }
+ dvi_itmlst[] = {
+ { 4, DVI$_MNT, 0 /*&ismnt*/, 0 },
+ { 4, DVI$_DEVCLASS, 0 /*&dvcls*/, 0 },
+ { 4, DVI$_DEVCHAR2, 0 /*&dchr2*/, 0 },
+ { 0, 0, 0, 0 }
+ };
+
+ dvi_itmlst[0].returnP = &ismnt;
+ dvi_itmlst[1].returnP = &dvcls;
+ dvi_itmlst[2].returnP = &dchr2;
+
+ Status = sys$alloc(descr(DeviceName), 0, 0, 0, 0);
+
+ if (FailureStatusP(Status))
+ {
+ VMS_ExitCode = Status;
+ FatalError("cannot allocate device '%s' - %X\n", DeviceName, Status);
+ }
+
+ Status = sys$assign(descr(DeviceName), &DeviceFD, 0, 0);
+ if (FailureStatusP(Status))
+ {
+ VMS_ExitCode = Status;
+ FatalError("cannot open device '%s' - %X\n", DeviceName, Status);
+ }
+
+ Status = sys$getdviw(0, DeviceFD, 0, &dvi_itmlst, &iosb, 0, 0, 0);
+ if (FailureStatusP(Status))
+ {
+ VMS_ExitCode = Status;
+ FatalError("cannot $getdvi(1) on device '%s' - %X\n", DeviceName, Status);
+ }
+
+ if (FailureStatusP(Status = iosb[0]))
+ {
+ VMS_ExitCode = Status;
+ FatalError("cannot $getdvi(2) on device '%s' - %X\n", DeviceName, Status);
+ }
+
+ if (dvcls != DC$_TAPE)
+ {
+ VMS_ExitCode = SS$_IVDEVNAM;
+ FatalError("specified device is NOT a magtape: operation denied\n");
+ }
+#ifndef __DECC
+#ifndef DEV$M_SCSI
+#define DEV$M_SCSI 0x1000000
+#endif
+#endif
+ if (~dchr2 & DEV$M_SCSI)
+ {
+ VMS_ExitCode = SS$_IVDEVNAM;
+ FatalError("specified magtape is NOT a SCSI device: operation denied\n");
+ }
+#if USING_DEC_DRIVE | USING_LDRSET
+#ifndef __DECC
+#ifndef DEV$M_LDR
+#define DEV$M_LDR 0x100000
+#endif
+#endif
+ if (~dchr2 & DEV$M_LDR)
+ {
+ VMS_ExitCode = SS$_IVDEVNAM;
+ FatalError("specified SCSI magtape does not have a loader: operation denied\n");
+ }
+#endif
+ if (ismnt)
+ {
+ VMS_ExitCode = SS$_DEVMOUNT;
+ FatalError("specified device is mounted: operation denied\n");
+ }
+
+ ots$move5(0, 0, 0, sizeof(newprivs), &newprivs);
+ newprivs.prv$v_diagnose = 1;
+ newprivs.prv$v_log_io = 1;
+ newprivs.prv$v_phy_io = 1;
+ Status = sys$setprv(1, &newprivs, 0, 0);
+
+ if (FailureStatusP(Status))
+ {
+ VMS_ExitCode = Status;
+ FatalError("error enabling privs (diagnose,log_io,phy_io): operation denied\n");
+ }
+
+ Status = sys$setprv(1, 0, 0, &setprivs);
+ if (FailureStatusP(Status))
+ {
+ VMS_ExitCode = Status;
+ FatalError("error retrieving current privs: operation denied\n");
+ }
+
+ if (!setprivs.prv$v_diagnose)
+ {
+ VMS_ExitCode = SS$_NODIAGNOSE;
+ FatalError("DIAGNOSE privilege is required: operation denied\n");
+ }
+
+ if (!setprivs.prv$v_phy_io && !setprivs.prv$v_log_io)
+ {
+ VMS_ExitCode = SS$_NOPHY_IO;
+ FatalError("PHY_IO or LOG_IO privilege is required: operation denied\n");
+ }
+
+ return DeviceFD;
+}
+
+
+static void SCSI_CloseDevice(char *DeviceName, int DeviceFD)
+{
+ unsigned long Status;
+
+ Status = sys$dassgn(DeviceFD);
+ if (FailureStatusP(Status))
+ FatalError("cannot close SCSI device '%s' - %X\n", DeviceName, Status);
+}
+
+
+static int SCSI_ExecuteCommand( int DeviceFD,
+ Direction_T Direction,
+ CDB_T *CDB,
+ int CDB_Length,
+ void *DataBuffer,
+ int DataBufferLength,
+ RequestSense_T *RequestSense)
+{
+ SCSI$DESC cmd_desc;
+ SCSI$IOSB cmd_iosb;
+ unsigned long Status;
+ int Result;
+ memset(RequestSense, 0, sizeof(RequestSense_T));
+ /* Issue the QIO to send the SCSI Command. */
+ ots$move5(0, 0, 0, sizeof(cmd_desc), &cmd_desc);
+ cmd_desc.SCSI$L_OPCODE = 1; /* Only defined SCSI opcode... a VMS thing */
+ cmd_desc.SCSI$A_CMD_ADDR = CDB;
+ cmd_desc.SCSI$L_CMD_LEN = CDB_Length;
+ cmd_desc.SCSI$A_DATA_ADDR = DataBuffer;
+ cmd_desc.SCSI$L_DATA_LEN = DataBufferLength;
+ cmd_desc.SCSI$L_PAD_LEN = 0;
+ cmd_desc.SCSI$L_PH_CH_TMOUT = 180; /* SCSI Phase Change Timeout (seconds) */
+ cmd_desc.SCSI$L_DISCON_TMOUT = 180; /* SCSI Disconnect Timeout (seconds) */
+
+ switch (Direction)
+ {
+ /*
+ NOTE: Do NOT include flag SCSI$K_FL_ENAB_SYNC.
+ It does NOT work for this case.
+ */
+ case Input:
+ cmd_desc.SCSI$L_FLAGS = SCSI$K_READ | SCSI$K_FL_ENAB_DIS;
+ break;
+
+ case Output:
+ cmd_desc.SCSI$L_FLAGS = SCSI$K_WRITE | SCSI$K_FL_ENAB_DIS;
+ break;
+ }
+
+ /* Issue the SCSI Command. */
+ Status = sys$qiow(MK_EFN, DeviceFD, IO$_DIAGNOSE, &cmd_iosb, 0, 0,
+ &cmd_desc, sizeof(cmd_desc), 0, 0, 0, 0);
+ Result = SCSI$K_GOOD;
+
+ if (Status & 1)
+ Status = cmd_iosb.SCSI$W_VMS_STAT;
+
+ if (Status & 1)
+ Result = cmd_iosb.SCSI$B_IOSB_STS;
+
+ if (Result != SCSI$K_GOOD)
+ {
+ unsigned char RequestSenseCDB[6] =
+ { 0x03 /* REQUEST_SENSE */, 0, 0, 0, sizeof(RequestSense_T), 0 };
+
+ printf("SCSI command error: %d - requesting sense data\n", Result);
+
+ /* Execute Request Sense to determine the failure reason. */
+ ots$move5(0, 0, 0, sizeof(cmd_desc), &cmd_desc);
+ cmd_desc.SCSI$L_OPCODE = 1; /* Only defined SCSI opcode... a VMS thing */
+ cmd_desc.SCSI$L_FLAGS = SCSI$K_READ | SCSI$K_FL_ENAB_DIS;
+ cmd_desc.SCSI$A_CMD_ADDR = RequestSenseCDB;
+ cmd_desc.SCSI$L_CMD_LEN = 6;
+ cmd_desc.SCSI$A_DATA_ADDR = RequestSense;
+ cmd_desc.SCSI$L_DATA_LEN = sizeof(RequestSense_T);
+ cmd_desc.SCSI$L_PH_CH_TMOUT = 180;
+ cmd_desc.SCSI$L_DISCON_TMOUT = 180;
+
+ /* Issue the QIO to send the Request Sense Command. */
+ Status = sys$qiow(MK_EFN, DeviceFD, IO$_DIAGNOSE, &cmd_iosb, 0, 0,
+ &cmd_desc, sizeof(cmd_desc), 0, 0, 0, 0);
+ if (FailureStatusP(Status))
+ {
+ printf("?Error returned from REQUEST_SENSE(1): %%X%08lX\n", Status);
+ sys$exit(Status);
+ }
+
+ /* Check the VMS Status from QIO. */
+ Status = cmd_iosb.SCSI$W_VMS_STAT;
+ if (FailureStatusP(Status))
+ {
+ printf("?Error returned from REQUEST_SENSE(2): %%X%08lX\n", Status);
+ sys$exit(Status);
+ }
+ }
+ return Result;
+}
+
+
+static void VMS_DefineStatusSymbols(void)
+{
+ char SymbolName[32], SymbolValue[32];
+ int StorageElementNumber;
+
+ if (DataTransferElementFull)
+ {
+ /* Define MTX_DTE Symbol (environment variable) as 'FULL:n'. */
+ sprintf(SymbolValue, "FULL:%d",
+ DataTransferElementSourceStorageElementNumber);
+ lib$set_symbol(descr("MTX_DTE"), descr(SymbolValue), &2);
+ }
+ else
+ {
+ /* Define MTX_DTE Symbol (environment variable) as 'EMPTY'. */
+ lib$set_symbol(descr("MTX_DTE"), descr("EMPTY"), &2);
+ }
+
+ /* Define MTX_MSZ Symbol (environment variable) "Magazine SiZe" as 'n'. */
+ sprintf(SymbolValue, "%d", StorageElementCount);
+ lib$set_symbol(descr("MTX_MSZ"), descr(SymbolValue), &2);
+ for (StorageElementNumber = 1;
+ StorageElementNumber <= StorageElementCount;
+ StorageElementNumber++)
+ {
+ sprintf(SymbolName, "MTX_STE%02d", StorageElementNumber);
+ strcpy(SymbolValue,
+ (StorageElementFull[StorageElementNumber] ? "FULL" : "EMPTY"));
+ lib$set_symbol(descr(SymbolName), descr(SymbolValue), &2);
+ }
+}