mtx-1.3.12/0000775002342000234200000000000011053074156011762 5ustar robertrobertmtx-1.3.12/scsitape.c0000664002342000234200000005264211052515177013754 0ustar robertrobert/* Copyright 2001 Enhanced Software Technologies Inc. * Copyright 2007-2008 by Robert Nelson * 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 -- set the block size to fsf -- go forward by filemarks bsf -- go backward by 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 -- write filemarks. seek -- seek to position . write <-- write blocks from stdin to the tape read [] [<#blocks/#bytes>] -- read blocks from tape, write to stdout. See the 'tapeinfo' program for status info about the tape drive. */ #include #include #include "mtx.h" #include "mtxl.h" #if HAVE_UNISTD_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_IOCTL_H #include #endif #if HAVE_SYS_MTIO_H #include /* will try issuing some ioctls for Solaris, sigh. */ #endif #ifdef _MSC_VER #include #endif void Usage(void) { FatalError("Usage: scsitape -f where is:\n setblk | fsf | bsf | eod | rewind | eject | mark |\n seek | read [ [] \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); } mtx-1.3.12/config.guess0000775002342000234200000012626011052513600014300 0ustar robertrobert#! /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 . # Please send patches to . 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 ." 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 /* 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 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 #include 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 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 #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' /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 echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 < # include #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 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 # 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 < 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: mtx-1.3.12/LICENSE0000664002342000234200000003543310637472152013004 0ustar robertrobert 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 mtx-1.3.12/scsi_win32.c0000664002342000234200000002000111052515177014104 0ustar robertrobert/* Copyright 2006-2008 Robert Nelson $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 #define WIN32_LEAN_AND_MEAN #include #ifdef _MSC_VER #include #else #include #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; } mtx-1.3.12/mtx.spec.in0000664002342000234200000000623611053074132014054 0ustar robertrobertName: 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 - 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 - 1.2.12pre1 - Need to create usr/sbin for install * Fri Mar 02 2001 Eric Green - 1.2.11pre6 - Move tapeinfo,loaderinfo, scsitape to /usr/sbin rather than /sbin * Wed Feb 28 2001 Kenneth Porter - 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 - 1.2.11pre3 - Removed patch, now use ./configure. * Mon Nov 27 2000 Eric Green - 1.2.10 - Fixed patching to use the portable.patch. * Tue Jul 25 2000 Eric Green - 1.2.8 - Added portability patch to mtx.spec so should compile on Red Hat Alpha etc. * Thu Jun 6 2000 Eric Green - 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 - 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 - Spell sourceforge right so the link at rpmfind.net will work. * Thu May 4 2000 Kenneth Porter - 1.2.5 * Thu Oct 29 1998 Ian Macdonald - moved mtx from /sbin to /bin, seeing as mt is also located there * Fri Oct 23 1998 Ian Macdonald - first RPM release mtx-1.3.12/mtx.doc0000664002342000234200000002004510637472152013267 0ustar robertrobert[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 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. 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. 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. 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 " 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 ] 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 ] 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 ] load The "load" command loads the volume in Storage Element into the Data Transfer Element. An error is signaled if the Data Transfer Element is already full. mtx [ -f ] unload [ ] The "unload" command unloads the volume in the Data Transfer Element into Storage Element . If 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 ] 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 ] 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 ] 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 ] 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 / 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. mtx-1.3.12/mtxl.README.html0000664002342000234200000001524410637472152014603 0ustar robertrobert SCSI Media Changer and Backup Device Control System

SCSI Media Changer and Backup Device Control System

[Also see the SourceForge project page.]

mtx 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). mtx is designed to be a low level driver in a larger scripted backup solution, such as Amanda. mtx is not supposed to itself be a high level interface to the SCSI devices that it controls.

This version has the following features:

  • Will deal with LARGE media libraries (over a hundred elements).
  • Supports multi-drive media changers such as the Exabyte 220 dual- drive tape library.
  • Supports the 'invert' bit for optical jukeboxes that need that in order to flip their media.
  • Supports the 'eepos' bits for libraries that need this to extend/retract their import/export tray.
  • Now supports import/export elements!
  • Reports volume tags (bar codes) and "alternate volume tags" (whatever those are!) for those tape libraries that support them.
  • Now runs under FreeBSD and at least Solaris 8.
  • Now has a 'man' page!
  • 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).

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.

Source Code

The current source code is: RPMs may be available from the following place: A .spec file is now included in the 'mtx' distribution for building your own RPM's.

Note that RPMs are courtesy of Kenneth Porter, who should be contacted regarding rpm-related problems.

Known Bugs And Limitations

  • 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.
  • 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.
  • 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.
  • 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.
  • 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).
  • VMS and Tru64 support are probably irretrievably busted.
  • This program will only use the first arm of multiple-arm robots unless the robot re-maps all arms to one element ID.
  • 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 http://download.sourceforge.net/amanda.

Philosophy

The Unix philosophy is "many small tools chained together". mtx supplies those small tools so that you can create your own backup and recovery tools by chaining mtx pieces together, whether it be with /bin/sh, Perl, Python, or CAML.

Support

See Also:


Maintained by Eric Lee Green
Hosted by VA Linux's SourceForge

Last modified: Mon Jun 25 15:37:22 MST 2001 mtx-1.3.12/scsi_hpux.c0000664002342000234200000000640211052333733014133 0ustar robertrobert/* Copyright 1997, 1998 Leonard Zubkoff Changes copyright 2000 Eric Green Copyright 2007-2008 by Robert Nelson 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 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; } mtx-1.3.12/mtx.h0000664002342000234200000004307611052515177012757 0ustar robertrobert/* MTX -- SCSI Tape Attached Medium Control Program Copyright 1997-1998 Leonard N. Zubkoff Changes 1999 Eric Lee Green to add support for multi-drive tape changers. Copyright 2007-2008 by Robert Nelson $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 #include #if HAVE_STDLIB_H # include #endif #if HAVE_FCNTL_H # include #endif #if HAVE_SYS_TYPES_H # include #endif #if HAVE_STRING_H # include #else # include #endif #if HAVE_UNISTD_H # include #endif #if HAVE_STDARG_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if HAVE_SYS_IOCTL_H # include #endif #if HAVE_SYS_PARAM_H # include #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 # include # include 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 # include # 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 # include # include # undef DEVICE_TYPE typedef int DEVICE_TYPE; #endif /* The 'cam' interface, like FreeBSD: */ #if HAVE_CAMLIB_H # include /* easy (?) access to the CAM user library. */ # include # include /* 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 typedef int DEVICE_TYPE; #endif /* the scsi_ctl interface, as used on HP/UX: */ #if HAVE_SYS_SCSI_CTL_H # include # include # include # include 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 typedef int DEVICE_TYPE; #endif /* the 'dslib' interface, as used on SGI. */ #if HAVE_DSLIB_H #include 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. */ mtx-1.3.12/nsmhack.c0000664002342000234200000002233711052333600013550 0ustar robertrobert/* Copyright 2001 DISC Inc. * Copyright 2007-2008 by Robert Nelson * 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 tongue_out 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 where 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) { 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(¶m,"1010",0,8); result=SendRecHack(¶m,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(¶m,"1011",0,16); result=SendRecHack(¶m,0,16); result->return_data[16]=0; printf("Product ID: %s\n",result->return_data); free(result); init_param(¶m,"1012",0,4); result=SendRecHack(¶m,0,4); result->return_data[4]=0; printf("Product Revision: %s\n",result->return_data); free(result); init_param(¶m,"1013",0,8); result=SendRecHack(¶m,0,8); result->return_data[8]=0; printf("Production Date: %s\n",result->return_data); free(result); init_param(¶m,"1014",0,8); result=SendRecHack(¶m,0,8); result->return_data[8]=0; printf("Part Number: %s\n",result->return_data); free(result); init_param(¶m,"1015",0,12); result=SendRecHack(¶m,0,12); result->return_data[12]=0; printf("Serial Number: %s\n",result->return_data); free(result); init_param(¶m,"1016",0,4); result=SendRecHack(¶m,0,4); result->return_data[4]=0; printf("Firmware Release: %s\n",result->return_data); free(result); init_param(¶m,"1017",0,8); result=SendRecHack(¶m,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(¶m,"1020",0,6); result=SendRecHack(¶m,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); } mtx-1.3.12/TODO0000664002342000234200000000152010637472152012455 0ustar robertrobert1 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? mtx-1.3.12/README0000664002342000234200000000276110637472152012655 0ustar robertrobertMTX 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 . This version was modified for multi-drive, optical changer, and tape library support by Eric Lee Green . 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 mtx-1.3.12/scsi_sun.c0000664002342000234200000000653011052515177013762 0ustar robertrobert/* Copyright 1997, 1998 Leonard Zubkoff Changes copyright 2000 Eric Green Copyright 2007-2008 by Robert Nelson $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; } mtx-1.3.12/loaderinfo.10000664002342000234200000000641411052334137014170 0ustar robertrobert.\" tapeinfo.1 Document copyright 2000 Eric Lee Green .\" Program Copyright 2000 Eric Lee Green .\" Copyright 2007-2008 by 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 LOADERINFO 1 LOADERINFO1.0 .SH NAME loaderinfo \- report SCSI tape device info .SH SYNOPSIS loaderinfo -f .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 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) mtx-1.3.12/configure.in0000775002342000234200000000351010637472152014302 0ustar robertrobertdnl 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) mtx-1.3.12/mtx.10000664002342000234200000002440511052334157012660 0ustar robertrobert.\" mtx.1 Document copyright 2000 Eric Lee Green .\" Program Copyright 1996, 1997 Leonard Zubkoff .\" Copyright 2007-2008 by Robert Nelson .\" Extensive changes 2000 by Eric Lee Green .\" .\" 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 ] [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 [ ] Load media from slot into drive . Drive 0 is assumed if the drive number is omitted. .TP 10 .B unload [] [ ] Unloads media from drive into slot . If is omitted, defaults to drive 0 (as do all commands). If 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 ] transfer 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 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 ] [invert] [invert2] exchange [] 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 [] Loads drive 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 is omitted, defaults to first drive. .TP 10 .B last [] Loads drive 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 [] 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 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 . 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 . 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) mtx-1.3.12/scsi_sgi.c0000664002342000234200000000436211052515177013740 0ustar robertrobert/* Copyright 1997, 1998 Leonard Zubkoff Changes copyright 2000 Eric Green Copyright 2007-2008 by Robert Nelson $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; } mtx-1.3.12/LICENSE.html0000664002342000234200000004717410637472152013754 0ustar robertrobert GNU General Public License - GNU Project - Free Software Foundation (FSF)

GNU General Public License


Table of Contents


GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

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.

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.

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

How to Apply These Terms to Your New Programs

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.

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.

one line to give the program's name and an idea of what it does.
Copyright (C) yyyy  name of author

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.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author
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.

The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.

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:

Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written 
by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

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.


FSF & GNU inquiries & questions to gnu@gnu.org. send other questions to gnu@gnu.org.

Copyright notice above.
Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA


mtx-1.3.12/Makefile.in0000664002342000234200000000746611052510715014037 0ustar robertrobert# 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 mtx-1.3.12/config.sub0000775002342000234200000007746011052513573013763 0ustar robertrobert#! /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 . 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 ." 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: mtx-1.3.12/scsieject.c0000664002342000234200000001125511052333672014106 0ustar robertrobert/* Copyright 2007-2008, Robert Nelson * 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 #include #include "mtx.h" #include "mtxl.h" #if HAVE_UNISTD_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #ifdef _MSC_VER #include #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 where 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); } mtx-1.3.12/mtxl.h0000664002342000234200000000673211052515177013131 0ustar robertrobert/* MTX -- SCSI Tape Attached Medium Changer Control Program Copyright 1997-1998 Leonard N. Zubkoff Copyright 2007-2008 by Robert Nelson This file created by Eric Lee Green 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 mtx-1.3.12/configure0000775002342000234200000053356611052512470013706 0ustar robertrobert#! /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 &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 #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #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 if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory 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 #include #include #include /* 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 to if __STDC__ is defined, since # 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 #else # include #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 _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 to if __STDC__ is defined, since # 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 #else # include #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 _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 #include #include #include 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 _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 _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 #include #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 #include #include 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 #include 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 #include 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 #include 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 #include 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 #include 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 #include 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 declares $ac_func. For example, HP-UX 11i 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 to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 declares _doprnt. For example, HP-UX 11i declares gettimeofday. */ #define _doprnt innocuous__doprnt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _doprnt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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 ." _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 >$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 mtx-1.3.12/tapeinfo.c0000664002342000234200000005706611052515177013753 0ustar robertrobert/* Copyright 2000 Enhanced Software Technologies Inc. * Copyright 2007-2008 by Robert Nelson * 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#] e.g. "TapeAlert:[22]Cleaning Cartridge Worn Out" * * Mode Sense: * Data Compression Page: * DataCompEnabled: * DataCompCapable: * DataDeCompEnabled: * CompType: * DeCompType: * * 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]: * Partition[1]:... * * Read Block Limits command: * MinBlock:<#> -- Minimum block size. * MaxBlock:<#> -- Maximum block size. */ #include #include #include "mtx.h" #include "mtxl.h" char *argv0; void usage(void) { FatalError("Usage: tapeinfo -f \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> 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 ". */ 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); } mtx-1.3.12/CHANGES0000664002342000234200000004242511052512013012750 0ustar robertrobertCHANGES, 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. mtx-1.3.12/sg_err.h0000664002342000234200000001252210637472152013423 0ustar robertrobert#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 mtx-1.3.12/install-sh0000775002342000234200000001304710637472152014000 0ustar robertrobert#!/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 mtx-1.3.12/scsi_aix.c0000664002342000234200000000607011052515177013735 0ustar robertrobert/* Changes 2003 Steve Heck Copyright 2007-2008 by Robert Nelson $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; } mtx-1.3.12/msvc/0000775002342000234200000000000010667407504012741 5ustar robertrobertmtx-1.3.12/msvc/nsmhack/0000775002342000234200000000000010667407504014365 5ustar robertrobertmtx-1.3.12/msvc/nsmhack/nsmhack.vcproj0000664002342000234200000001051010637472150017227 0ustar robertrobert mtx-1.3.12/msvc/mtx/0000775002342000234200000000000010667407504013551 5ustar robertrobertmtx-1.3.12/msvc/mtx/mtx.vcproj0000664002342000234200000001177110637472150015611 0ustar robertrobert mtx-1.3.12/msvc/mtx/Distributions.txt0000664002342000234200000000131410637472150017147 0ustar robertrobertDebian ====== 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 Stable Version: 1.2.18-1mdk Merged: No changes Redhat ====== Maintainer: Jesse Keating (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 mtx-1.3.12/msvc/tapeinfo/0000775002342000234200000000000010667407504014546 5ustar robertrobertmtx-1.3.12/msvc/tapeinfo/tapeinfo.vcproj0000664002342000234200000001051310637472150017574 0ustar robertrobert mtx-1.3.12/msvc/scsitape/0000775002342000234200000000000010667407504014554 5ustar robertrobertmtx-1.3.12/msvc/scsitape/scsitape.vcproj0000664002342000234200000001021410637472151017607 0ustar robertrobert mtx-1.3.12/msvc/scsieject/0000775002342000234200000000000010667407504014715 5ustar robertrobertmtx-1.3.12/msvc/scsieject/scsieject.vcproj0000664002342000234200000001021710637472151020114 0ustar robertrobert mtx-1.3.12/msvc/loaderinfo/0000775002342000234200000000000010667407504015063 5ustar robertrobertmtx-1.3.12/msvc/loaderinfo/loaderinfo.vcproj0000664002342000234200000001033410637472146020434 0ustar robertrobert mtx-1.3.12/msvc/config.h0000664002342000234200000000166210637472151014361 0ustar robertrobert/* 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 mtx-1.3.12/msvc/mtx.sln0000664002342000234200000000616610637472151014275 0ustar robertrobert 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 mtx-1.3.12/config.h.in0000664002342000234200000000164310637472152014016 0ustar robertrobert/* 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 mtx-1.3.12/build.win320000775002342000234200000000072510637472152013761 0ustar robertrobertmanpages="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 mtx-1.3.12/makedist0000775002342000234200000000060010637472152013512 0ustar robertrobert#!/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 cd .. if [ ! -s mtx-${1} ] then ln -s "${ME}" "mtx-${1}" fi tar --exclude CVS --exclude .svn -czvhf mtx-${1}.tar.gz mtx-${1} mtx-1.3.12/mtx.spec0000664002342000234200000000623111053074156013450 0ustar robertrobertName: 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 - 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 - 1.2.12pre1 - Need to create usr/sbin for install * Fri Mar 02 2001 Eric Green - 1.2.11pre6 - Move tapeinfo,loaderinfo, scsitape to /usr/sbin rather than /sbin * Wed Feb 28 2001 Kenneth Porter - 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 - 1.2.11pre3 - Removed patch, now use ./configure. * Mon Nov 27 2000 Eric Green - 1.2.10 - Fixed patching to use the portable.patch. * Tue Jul 25 2000 Eric Green - 1.2.8 - Added portability patch to mtx.spec so should compile on Red Hat Alpha etc. * Thu Jun 6 2000 Eric Green - 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 - 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 - Spell sourceforge right so the link at rpmfind.net will work. * Thu May 4 2000 Kenneth Porter - 1.2.5 * Thu Oct 29 1998 Ian Macdonald - moved mtx from /sbin to /bin, seeing as mt is also located there * Fri Oct 23 1998 Ian Macdonald - first RPM release mtx-1.3.12/loaderinfo.c0000664002342000234200000002752011052515177014260 0ustar robertrobert/* Copyright 2000 Enhanced Software Technologies Inc. * Copyright 2007-2008 by Robert Nelson * 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 #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 \n"); } /* we only have one argument: "-f ". */ 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); } mtx-1.3.12/scsi_linux.c0000664002342000234200000003316711052515177014322 0ustar robertrobert/* Copyright 1997, 1998 Leonard Zubkoff Changes in Feb 2000 Eric Green Copyright 2007-2008 by Robert Nelson $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 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 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 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 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 */ mtx-1.3.12/scsi_freebsd.c0000664002342000234200000000665211052515177014574 0ustar robertrobert/* Copyright 2000 Enhanced Software Technologies Inc. (http://www.estinc.com) Copyright 2007-2008 by Robert Nelson Written by Eric Lee Green $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? */ } mtx-1.3.12/README.win320000664002342000234200000000244310637473627013623 0ustar robertrobertBUILDING 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, on Windows you use Changer. On Linux the tape drive is referenced using /dev/nst, on Windows you use Tape. 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 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 mtx-1.3.12/scsitape.10000664002342000234200000001513511052334216013657 0ustar robertrobert.\" scsitape.1 Document Copyright 2001 Eric Lee Green .\" Copyright 2007-2008 by 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 SCSITAPE 1 SCSITAPE1.0 .SH NAME scsitape \- control SCSI tape devices .SH SYNOPSIS scsitape [-f ] 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 Set the tape drive's SCSI block size to bytes. (NOTE: if you are using your OS's native tape driver, THIS IS EVIL!). .TP 10 .B fsf Go forward by tapemarks. .TP 10 .B bsf Go to immediately previous the 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 write filemarks ( 'mark 0' flushes the drive's buffers ). .TP 10 .B seek Seek to a logical position that was reported by a previous 'tapeinfo' command. .TP 10 .B write write blocks from stdin to the tape. Chunk the data into -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 [] [ <#blocks/#bytes> ] read blocks from the tape, write them to stdout. If we are in variable block mode, 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 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 . 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 where you are doing variable-block-size reads and wish for 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 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) mtx-1.3.12/COMPATABILITY0000664002342000234200000001354110637472152013717 0ustar robertrobertWARNING: 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 mtx-1.3.12/mam2debug.c0000664002342000234200000000610611052515177013776 0ustar robertrobert/* Mammoth 2 Debug Buffer Dumper Copyright 2000 Enhanced Software Technologies Inc. Copyright 2007-2008 by Robert Nelson $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $ $Revision: 193 $ Written by Eric Lee Green 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 #include #include #include #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); } mtx-1.3.12/sg_err.c0000664002342000234200000006401211052334027013405 0ustar robertrobert /* 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 * * 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); } mtx-1.3.12/mtxl.c0000664002342000234200000015275311053064412013121 0ustar robertrobert/* 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 $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $ $Revision: 193 $ This file created Feb 2000 by Eric Lee Green 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); } mtx-1.3.12/vms/0000775002342000234200000000000010667407504012576 5ustar robertrobertmtx-1.3.12/vms/000readme0000664002342000234200000001575010637472152014204 0ustar robertrobertMTX -- SCSI Tape Attached Medium Changer Control Program Copyright 1997 by Leonard N. Zubkoff 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 mtx-1.3.12/vms/defs.h0000664002342000234200000000160310637472152013666 0ustar robertrobert#ifdef __DECC #pragma module MTX "V01-00" #else #module MTX "V01-00" #endif typedef int DEVICE_TYPE; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; mtx-1.3.12/vms/scsi.c0000664002342000234200000002670510637472152013713 0ustar robertrobert/* 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); } } mtx-1.3.12/vms/ldrset.cld0000664002342000234200000000037510637472152014562 0ustar robertrobertdefine 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 mtx-1.3.12/vms/descrip.mms0000664002342000234200000000274710637472152014755 0ustar robertrobert! ! 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 mtx-1.3.12/vms/ldrset.c0000664002342000234200000001214310637472152014236 0ustar robertrobert/* 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 #include #include #include #include #include #include #include #include #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); } mtx-1.3.12/vms/build.com0000664002342000234200000000202110637472152014366 0ustar robertrobert$!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 mtx-1.3.12/vms/ldrutil.mar0000664002342000234200000000502310637472152014754 0ustar robertrobert .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 ;Find UCB address from channel .IFF .call_entry, 2,home_args=TRUE,- preserve=,- output=,- 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 ;Find UCB address from channel .IFF .call_entry, 2,home_args=TRUE,- preserve=,- output=,- 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 ;Find UCB address from channel .IFF .call_entry, 2,home_args=TRUE,- preserve=,- output=,- label=_setldr .endc $cmkrnl_s - routin = __setldr,- arglst = (AP) ret .IF NDF,ALPHA .entry __clrldr,^m ;Find UCB address from channel .IFF .call_entry, 2,home_args=TRUE,- preserve=,- output=,- 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 ;Find UCB address from channel .IFF .call_entry, 2,home_args=TRUE,- preserve=,- output=,- label=_clrldr .endc $cmkrnl_s - routin = __clrldr,- arglst = (AP) ret .end mtx-1.3.12/mtx.c0000664002342000234200000006146211052515177012751 0ustar robertrobert/* 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 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 of Enteka Enterprise Technology Service for porting MTX to Solaris/SPARC. Thanks to Carsten Koch 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 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 ] noattach \n\ mtx [ -f ] inquiry | inventory \n\ mtx [ -f ] [altres] [nobarcode] status\n\ mtx [ -f ] [altres] first []\n\ mtx [ -f ] [altres] last []\n\ mtx [ -f ] [altres] previous []\n\ mtx [ -f ] [altres] next []\n\ mtx [ -f ] [altres] [invert] load []\n\ mtx [ -f ] [altres] [invert] unload [][]\n\ mtx [ -f ] [altres] [eepos eepos-number] transfer \n\ mtx [ -f ] [altres] [eepos eepos-number][invert][invert2] exchange \n\ mtx [ -f ] [altres] position \n\ mtx [ -f ] 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 argument '%d' to 'load' command\n", arg1 + 1); } if (arg2 < 0 || arg2 >= ElementStatus->DataTransferElementCount) { FatalError( "illegal 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 argument '%d' to 'unload' command\n", arg1 + 1); } if (arg2 < 0 || arg2 >= ElementStatus->DataTransferElementCount) { FatalError( "illegal 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 } mtx-1.3.12/contrib/0000775002342000234200000000000010667407504013431 5ustar robertrobertmtx-1.3.12/contrib/config_sgen_solaris.sh0000775002342000234200000000665110637472152020013 0ustar robertrobert#!/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 $?mtx-1.3.12/contrib/tapeload.pl0000664002342000234200000001001210637472152015547 0ustar robertrobert!/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= ; # 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; } mtx-1.3.12/contrib/README0000664002342000234200000000031610637472152014307 0ustar robertrobertEverything 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. mtx-1.3.12/contrib/mtx-changer0000775002342000234200000002537410637472152015605 0ustar robertrobert#! /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 [arg...]" echo " -info reports capability and loaded tape" echo " -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: 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: reason echo "$ct $CommandResStr" exit 1 else # success; output: 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 mtx-1.3.12/contrib/tapeinfo.py0000664002342000234200000000230010637472152015601 0ustar robertrobert# 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 mtx-1.3.12/contrib/tapeunload.pl0000664002342000234200000000631510637472152016125 0ustar robertrobert#!/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= ; # 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; } mtx-1.3.12/contrib/qdback.tar.gz0000664002342000234200000002550010637472152016005 0ustar robertrobert̙=/?C^xyppq'}IB|#`mT@~vAL=ߧHAHDUL86HK)^R0BΤH_,C_"<XϪxݽe(co&-3dHq{i?V NWb/h{s1nd"<@W"]4D' ^,0(zbJ$ST!lEh08#w2Ii)BV dT_ <$'3)Ro^8rx|y nG1-\RPGr ?B ?߾'nս7붸|=ǹlkxET@#ߜ9iaN>}rtbO$JTW2` aw9JSAW?<0< ;x:ഃ/x>sRH1@Dv^ Asrnu;ĺitz~Ј F fB1@"Shq.`o #. DGz]8,c*b$g2IDEF#{E9?o]vzݜS%U\WQl˥S?%@Hbch@[G ۖ R1Do/aAN40 D ]\R>ZƱ SXb]zvU!NxgN/V^e5B  ; e냵`r:j5{D[G\]pU^MɮxAʽ\tO<vG{dda*30Qȓw~t0b ~u;v!& W+֋o8%h۾](L)S@E8̴dr!(X#'?\:`McĻYm (j})U2~i])x:҂$52hYAx0J ʡ79q/Q߽urٻhF-Dި%3L$vK6s޶1 {gоG˄>k77%Cش6zf{7EtO?Kex/K^C~4rһ^n>1L]տ{eY6f^8A^nbï.Go_t.s~uyH.'t`=q4p\87`_4F #aރ wYyĖwcA8jbA1Z`իe yPco"c=y*>+3J%Kz6dvT[![0*@[r-e4%xwM=SG{8iݼ k?X6*o~PQOkTܦ8Bvi)rlrA8!G2{c! %XS (~pN(!@SW^t =fKtd 1 H/oڭ6 Wl]W< #w*! dV^&?w{tœ 218!xr(vj/f~h! ymD_ *1̀dBjl&>iIuq'FQ@XtHZt1paOμL4x b }1 tJL Q e' IRR81T 2@s@M;zHw2`~Gqc=FE43 4+?9৮=;(14i'̐OjbL*ud c)N!"U[_P1ć5Y@l9SDmav!F /) xֻxj!ʄMCt /|Ύw6 \a/$iPN 3$P0Q:Rj0-uv-;,э(bf 4b ꌷ '\v餖DcL'ڞ8%#8H~HĂ!60diz6=xm,Q,/n4K~Xj0?цGU"E\60w%ZY''^HaGk`*fE:Pp,pqeǸɊ)VTxk$[_3Ӿa',rȺ {yBccrKyz)x{kPlCp b%v䋊59m!5 ->s~TkCQCCT-Х-$ZaEAo7+V$Jšfb $m* ĒC =wAևˊם%lܵ萍;[%x :F`p,N(r14exX@[i  6|frpMŪ,&-3g~r(ss+˳(`*6d$?;Y 0x˅p+ ]w ;E@nc!6F\PV([? U$ HAGm3 F}U*۶n?B IΚ/zڼ`ٹ`z t&cs{F^S0ʻՏXǕzF*V) ԁf`|׈M9r%GqU2Ї  G ñS,wT=pC,]4k NR40k2c 3b%)tBP"C f/.;ccK_UeRٜ8<^/H)gmljή8Ġ\̣40M6%ZiTp1:S)Žth( `HjUbD= Nꗮ?uZd,~KIM@_]~l%Qn[X;f%>N7XDN^"6A,!CN7xд0F2D)7;y`>FbyDHJyqc~1^cLkMYcus][3h5~,'jn.E28EAn6Zm6Z Swqr(ӄ\ظi8[]"Խ(( %.Hd0^2K*]zxǯ~:ķ vh&1'GF?qe- js] A 0-pXrGT62NUb"ҟJBRPum1L`s\L%YNHʖE\wvIS[D-3&;/- 5a%rkBfuxܧ{Zg1QL̰6[* s &D-qG%l=Cm%DŽ2X^ma9&p,s@Ʈ&4u;A_# 뙐B(Ug 9F0 o3k %V0/үE"dIVG˫# tL05k< _ 7PrO_ 6Xf$<Ԙ`9WG^sVqSJn؂A8d%7,{B] ۟2,K2MgAszty%TuOβע«4wԤHA׺) TAgccEG ZR-%ىW9+E1w{n͢>:ƌN<<:g̗4>QYF+&Jf`{Wt=<-prRVOv>ȏxCl&B ]0q[ssLL(҂>! ,!UD~ F\4S,bؼ.y VpڧkxNRq[y DBR\+H/)RonPe=3-}>sc3JP,N:f?@wUCsA }}/祿_8_竲~cCp y\ MKdn?r쌽[}zzi[&|O{mYÚfքq D窛6$-P];9͚{s."uO#$ld]h5OCQikkCG%1σ'xJ>%B4H'Ogt4ivdc'{@%%{0?Auj,R5.h1>Td2**Gڤ\{ݥٱn6昙jb.16"*hb0G> dZ0e} ZuV(B$|ι?z.]%o-贰k51raoSbwEh?GG"x#G al 1"rAm;tȥ2tmeh>feSr0FKsԪ/SAKY͟}5sX[ Fqfd4c4"Y~m rV:J^\c+h,jccԖ.|] H}׭i]L/tNE{5~"C`/ ߟ1&hKh!o f؃sS z_)E>\m (dfN%xW&G2yvd9c=D YN7Ir\Utp8/(߭]6:;ܦ.%&4{ W3[ʡ*G*er1Qp;͑ 2L!9"&NGfXW *^(oáW'iָ}Έ h@If{3g7&Y9۷lj/Dyo\!lbš`BV|[X{n{Ոȋ[F,8h./(XaNdh"j^x~ ]xe2}#R7RPG\+dBAXSw #ory^6rXfTD @Fɦ] Xk*bL][QI )m)Vjhr-qb>z,׊c xB[)Mst{["'wtŏ بI֙vYyi}:ЭdQ{{a]Gٿo!P880UTc6􇍇jjˌwm>r{bJxs5;‼߆Q`gX]MH3OM]MUuzoEl]o ]&F|;*|J팍>h@70Ɯn#}.ND=2[J YN3O%u% }=.Wa_ٳgTRZp9αoo7[gWG 8Q2[^^0dqժtT^(l5WVyYsߋ7x7 7Wf ==#~Bgda GRw}pn;tqFB! OFy̫c]2Uj~N 9G;4Rڝ>'|YSo]8ۤ2OyR.`UoowU wZԮ6ླZ|=ȾU^5*|?@cxrKLHL[L7 NϓGy3 :N>dO$ j; .޼9dXЅ}ia ̘΍nxqnd!BܥjȐ\cU l6clpf@{?f-.5\EĖ⚨@'}N3}gaoeQQ8A3iúN{[QBB)ҾUCB 2ydSu~M yGg&d7=1xQ}JžgWX+<:6?X(#o2Eʿ~O?OzϟZ;{z^xrX_U:f݈uD2D*X 9o F;Nڄ>GK AX $7JϏiV$WH-jӴpRsCBڢ@l!dwZ- FJ6lV "@M{]l%WEJCoqR͍*uKj;̉]6۔K?cryL)aNDqS- /-0\|ȺD=vJM;Uw'%Sy"KS,#li>C(,x&S?m)0OOPhx\' ;CaO<3ydP }`oNt|B^ JK6LZcThsDNf)mb[Zl U ֒TZUQqR4_w\t<l hD6RwǓ|,u0Bskco2Q2p R4Kx?` 1 .(OoEY⼴ЩY_鸬RvEauy88c\"2xr!Q>> ճ,=:0 [xhG Zh:.glZzս)%7!Zh}z x'Nft_& \i-'c29J٪끧/W+!1ߥ nILf"DACqu|(,n "±.yW%*ƂGlMc*CI]-T{zzOj!x#aD旷<~D,!=)֓'J(6w OHJ'5ɯ,^i;+']ht sI9P!ױ>x2-t*$Rj|TCӁ=TPΌx`d:Ihd<'So\V9k`w7F0.0htIgTioXD P!ŴNv;bYN66m/x=ߞ*Ug;XCՇG ST'ule%*kg{˛_z=m򻋫ˏl-~ ޕ̒!ҔaŒm.YϐSaDD"u$wzA#tc-,jQ '] Di:s.eb@DYo"N;*MIyb Py-EȘ&Zbz.paF3^U$]ΪaA iUE^?@e&L}⥐h`ׂn:d뾩*%; ߜ^Χ  řâ\HsC62s|E(Z߼hϬv@?â)UwkCw0 訠ۚYP9yTk~b,L[Uq `T]5 39<=pP=9UIUכ(Zip@ƔTPL&XkS6d>$g>,p7cb=yv68==e #hBU@=RSvHy˶rgҁ-ph/\v&T[Ɗr@Dbm ;3Ȗ; ?QTKw +yL{(.7,Yx+F;M2'~q9![5SFӄ4Ez.LQtREГB̢fw=ߩP6ͦM6<-u& kqؙ#cKVVs[62) {Q# o# t6 wQgU9sS4 2mMXd6{.sIJȁ}oWIa)"5WܐGǶm@H7;/-af02|`"2uhcM 2>?eLA$;:tmHt}s ;Ni$k4Zl}Sþ_lEdDxwUs/Z`~{cxqFqkaKŝՁF]IFT!]M7ES4\ zYmYie'Y}^߽`j#wo{c1I&z@;kl@0kHGe%݊"ЧgA:nMH4]pns6K 2-(l{8'pG_3ΜTUlmfFUvy $g7Q܍ɷ"&`tԬ ݂^."quf *`$5aAg Z%*h_!sBDoԾ&y*]S9XbyˠۊUJ4w:(T`J΁@K5-gCI ԪGBc<$cFpHARRKnu%9E%>Ǽ~)aGj8#ZȌ72gE%NzR *6ic5y(sP/:y[R; &,UH- u0:X,4Gӧ#uA @jg38(XnB^jb-qԶ`7Z0ȿ}ʅ'_܏o{>gD'f>uvȎQ@3;_3}A;5== # mtx-1.3.12/contrib/mtxctl-0.0.2.tar.gz0000664002342000234200000001307010637472152016525 0ustar robertrobert 9zttߎ>>}Vt˒Ԏpe~m:#cB}Wghtq_Sm?zqB|e'jhYlU.0]9WPA -s<|";N,2?"_{U" CzmԴ?ś?:>>?|UvXNSRHCXW lH ĉ=|> cp C4CU { ˹ Kqk 7pf*%-/q^+X$pI^!vwک/aإQh6F{l1&B vLNԍi{P !'a vHJX;(v 4y}{a"@Ev|zv! A\f^/ϸo9_( l6gxS'?< ]{> <C${ Ht5_ R`rpMa<;phiz0<]\{'O Ⱗy}:yM̍f(=tPw>2-2^Ά:=__Ͽ)3lc%~Iw&(t,4ڝiK0&q.tGo+~9}M]еQݻȌF$ PȨVNF6\(6RqYZD,;Q.y9p |f9[ (Vʘuթ6S8bP\)Ǜzt߻jf$c8,~Qo!$[lEڅICjpqQadCFUS_O`clج(%0I7 $x1"iY3TBS,˲=]֟wuvZ^(K:t{ط{iiL -S׉5Rf:'G5\>cwzgyG釯uP=ֺ WěG-0NN;u {Χv1ě9s&uy%GVB@]k 6O;F9^aWB#ttAIx];-%| 㛟oNlHRoBhT W=7o' [xw<ϷJK: ӀqߴKAUz^ۧn;`bT ԝz'qx$xQan,=`UAw%$iWEΒ rvU䥠G3'8Ւmn0|>XU #:7Mk)" ÜngD$u3sEc~ّB/ qFԡJ#zW@\T}Y]v{&u&'vi 4V8zHR1qHI3]TAE$IrG|q\<եHJ_ek/&v  <5vP]L\84l1Xz..o<"f%0Cožkˢ GGBu/ )rD{H {~aǞ?26AXFqP*xk5F(q8"_ٮgK=Q>^C*`ˈ!W6^y%ֿt05-sG2/Ol{eWoiwNT&UKg{9N{~b5ŝ /-cY6g /a0Wx ϏYR a0 cd=Tȋ{L #aGO{.z@A|u4z-k'OhhIy|YKJ >1P0:pQe2t\/!~:BչKY3t6vjA ESRzevD`;N8&ݺ8a8⣞wrwLH{l;AeP.>D|5 cwmFl*¬ai~IO}+| ~FuMX7qڬΚb*IeM3lMMq/8kﯢý #^OV]ks߮DzۀZ.IM꫱GZF{+5QZSMPN|t Y*m}dȃ"e.MҴ0%x%Qs4#>IL&ג [HP0q0H d{>-}BZ 9 _(1Qܵc?Hc(K0m TGSDJ)=\ EMSFYgܫgSǟm Og/~z=EPM0z,6oH!nZOY͋qjT/g};ײIQnaR}1FyyAPQ -m&$R)NKU š `i2#X wH,H!` @ouАz@GtŹ佨aI"sJ\B+c_TR\|'G|mMXЪdX` |vMXJk)Ȕ;Ԙ3 2#(*5%*aw/ZGݓCRjKݰ&,kӯ]'绪'1j ܩ{Deg]WȿеF6V6wbBZO_:o§Ta ɟC|s%)TŇ~k;n9'WmxF}ɝ7^q]'dRƊ!el+'@\hlfqm7A]_嗰ݏԥcg<`|P(%1*f!s͸]L ;R%XS"r:~-$TF1ҮjzAjbi" 1LW*ܐ0A0pp܃)P1u&гO냫>9?8hzȧUi\A_Fbjů%GL`au]Z. E%+ɍ!ӱdctYYU|7l4Pʫ/p7-*Uv^DWA~|=ĉՒ)k)/*, ?x\,%R2ز]t&[NGa*BYٌvө$4E(3eиMXO_DHF4f.J\"|*:gD8k9RCJ*j(*a*mJ*F "HKI<\F6V =nU;Vխ$ֺ\cVhy@CEI 3Xri5pJJrc󢮬Sw FPzAxyE%/{~SvɍCAOϼR*B77`THܭdM*fZNnWkL(JDSJ6"6ˏbmVu1}jQ(>*;)/њT*> [.CS\PE&>KJqMA^~b M]TP [4ܣtDDC^.uQ#bVN/}%JjJU 8T0(Xo6vjT7l1خP5}j6rUM =6~%܇780;-q(@k}YRASe +uܸjV@tXuAdC*װ*gs_ަ%>x:+qE6oil.gK[@3Ms̪q(^);<4kQ^80ӄk譄o}g?~9??jͺtR`||d<]5Z˒n{J'r0~7yr[EYM 暫>3+ו-K]Nΐ3҇`K|Y(ii#6'|E[^YDyg=7k88pq!`HK7y@jBOJөxhW?|߷^.K".Rr+c&y?CדL%'x.ha\<W\M2GJSD> $iǜ8H0_`;)Օo.vBpbLwPbA0=W_ @[9B;^ũAH)Vc.%_ZJ" "!Zbs煷$~%aj`ܒrIҚm'hp.k^HEQHb]D >*f0qsJ؃:Lȍ&w9„sjg=B=zwlnAJJTw;˗RS#LZ+E#ΝRr?8P"Ϟ쥩 \u0umS.]55 d"9Q%SQJ\JlEQt$~d|&؎gs '@}@r6qAA )hFWx}ÒAO,s,P8.]*`baH*WrG[ ]Vs%+?%{Zqt!Ka5}] 5uؔIWCHbh?նmmk[ֶmmk[ֶmmk[ֶmmk[ֶmmk[Jxmtx-1.3.12/contrib/MTX.html0000664002342000234200000002003210637472152014762 0ustar robertrobert TapeChanger::MTX - use 'mtx' to manipulate a tape library

NAME

TapeChanger::MTX - use 'mtx' to manipulate a tape library


SYNOPSIS

  use TapeChanger::MTX;
  my $loaded = TapeChanger::MTX->loadedtape;
  print "Currently loaded: $loaded\n" if ($loaded);
  TapeChanger::MTX->loadtape('next');
  my $nowloaded = TapeChanger::MTX->loadedtape; 
  print "Currently loaded: $nowloaded\n" if ($nowloaded);

See below for more available functions.


DESCRIPTION

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.


VARIABLES

$TapeChanger::MTX::MT =item $TapeChanger::MTX::MTX
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'.

$TapeChanger::MTX::DRIVE
$TapeChanger::MTX::CONTROL
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.

$TapeChanger::MTX::EJECT
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'.

$TapeChanger::MTX::READY_TIME
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.

$TapeChanger::MTX::DEBUG
Print debugging information? Set to '0' for normal verbosity, '1' for debugging information, or '-1' for 'quiet mode' (be as quiet as possible).


USAGE

This module uses the following functions:

tape_cmd ( COMMAND )
mt_cmd ( COMMAND )
Runs 'mtx' and 'mt' as appropriate. COMMAND 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.

numdrives ()
numslots ()
loadedtape ()
Returns the number of drives, number of slots, and currently loaded tape values, respectively, by parsing tape_cmd('status').

loadtape ( SLOT [, DRIVE] )
Loads a tape into the tape changer, and waits until the drive is again ready to be written to. SLOT can be any of the following (with the relevant function indicated):
  current       C<loadedtape()>
  prev          C<loadprevtape()>
  next          C<loadnexttape()>
  first         C<loadfirsttape()>
  last          C<loadlasttape()>
  0             C<_ejectdrive()>
  1..99         Loads the specified tape number, ejecting whatever is
                currently in the drive.

DRIVE is the drive to load, and defaults to 0. Returns 0 if successful, an error string otherwise.

loadnexttape ()
loadprevtape ()
loadfirsttape ()
loadlasttape ()
Loads the next, previous, first, and last tapes in the changer respectively. Use tape_cmd('next'), tape_cmd('previous'), tape_cmd('first'), and tape_cmd('last'), respectively.

ejecttape ()
Ejects the tape, by first ejecting the tape from the drive (mt_cmd(rewind) then mt_cmd(offline)) and then returning it to its slot (tape_cmd(unload)). Returns 1 if successful, 0 otherwise.

resetchanger ()
Resets the changer, ejecting the tape and loading the first one from the changer.

checkdrive ()
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 mt_cmd(status). Returns 1 if so, 0 otherwise.

reportstatus
Returns a string containing the loaded tape and the drive that it's mounted on.

cannot_run ()
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.


NOTES

~/.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 setuid() 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.


REQUIREMENTS

Perl 5.6.0 or better, an installed 'mtx' binary, and a tape changer and reader connected to the system.


TODO

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).


SEE ALSO

mtx, mt, tapechanger. Inspired by stc-changer, which comes with the AMANDA tape backup package (http://www.amanda.org), and MTX, available at http://mtx.sourceforge.net.


AUTHOR

Tim Skirvin <tskirvin@uiuc.edu>


COPYRIGHT

Copyright 2001-2002 by the University of Illinois Board of Trustees and Tim Skirvin <tskirvin@ks.uiuc.edu>.

mtx-1.3.12/contrib/TapeChanger-MTX-0.71b.tar.gz0000664002342000234200000001404310637472152020134 0ustar robertrobertZ<TapeChanger-MTX-0.71b.tariw1__yl(Y, l%)'yqRB  M9v/+ωH5;;̢Lɵ\ɨ]Qo꟭h4wwv6;W>kl5_swwwՂ1ƉI֋n`Qdx}yy'j4~`o#/Id EOL{6^:I7='>YE*Nʼnx:+‘G@R5!`t8Axa cDR V{ 6˶cURI(NMRIpD "'7?;,KكWt7yyA"O(A nn)YOS@%v@E,Lc1Oh)a:\1 #1ᬝ/( Hq`;v^) ^v0p^p%k}VuW3$8X:A6ފ[/boHv7ҿϰK0xD^Q7ybвNCg(p#XR\;7cC8P!O' 8䍌-/y*uqt {ۨ=l Dr(4Q3D $FYe)6s=e8ϲ⇠HƠ= V0 4HP8&ӱG!9_'T{lK!a)Wdr^]!D^6&q@$mC$&_N@U"lP#0$%*hW~_&a{ ˸8덏r:hm?{VrS9k t a:>2e`' H$}88{LdiDʦ{fߜlS~%s)aDܞFn=[GUaΒG9ƨ[|w59KhB*=Qqbִp슒89Tu8m馀VJyS6JC5Hk>LHZItO/4ʡ:։RfkEGnXF_yP A_AzztAi}uiʧe(<9ch@5(E휁f$W6m@"P"B|CC04WN@I:c^ OZ0ХKB90(v6vxj ]~ii3"6vO/ё$\2.'2iŌ@/[K< ?8 ^ "B-Oͺi =ߔlmE`4<1-<8|BwitL9rYIQ.G@$OW_1BIق0F2J Um߂Nh^x&p* AȜi1"x|8yWHג ;DWmY(>W:% [/affF@a"@yrgM(;0 OƐ 3ay`Hfbz'Ko ZD+4F)yf Ӭ80sM88yd@4P %b 5 QP/A VEqoa>ii 42~+)+dl<, +3 WEez*ʜZX*tF)+ Ofj?(g*=;d?I0[6<G# dCȜK7b,b1Y)G`0.IUwc7- ihlȢY΄Ѵ?+ȘsLj|<-m%[maW9uچ89kPNi>98䨀Vɍ_,^J$8X>{v0B$*PWHXO&5{'5O-)K0Ь4x*EIEGaMy|hf_vXn+^=߀{o݁Xkg_nkVsW_hKk `H eUxX@?F{`*S=8sf$6Wձj\T\mZ;_[Fy6'\UI @PȣP]À7tFr(;xF[[ʳmJ] dsV{bM>PSP6;\)mӓ/PN_g/D# -mۍ=h ]rx~ Ex ޠ릵6tez [ y#?r)4 _mMX*gRvI\"7N#aO]K[`OhWH}vz}Vyi5_ׯfVY-קam❚]yEGCb6S1ꅗl^ «nףM`';ߩ'47+:O'.Ti~?Ýk6ꈯ;C4CRo%VC,>->p^|3,e-7>_:۽jh}@&'>J[9ҧoֳ0PVNwJ|??w+X?lmEg|6>ċtszwwc&o/xuf/j_ֿijrN+]Ŕ>~zssogGYaf:Yu"@hKusM +f~FWVӫl5kf}W#^j~/$7UI>fֈb.g 6.뮋ùB_ lN莊_q%0증ǂTja8S~}3f'u/ŕʾqaZ*p9XMnS\pU~k!LT@%0Tbx8X-Mզ|@s% $DP9o^C\ uȱaŁE[ơZj?=[-S=j ~xroU~N8 Nf$Kyу0Iq6P g8*-Lw Y2ConpBTfsE5bl0p,@TPxMB .䤢Jcao -/z!C׻yY~ փ}UKCtbń U6q+;1]\ ~}Ψs{wJ\;C ނ`HILNLE^G3q.AI^XZAi+[ϊ|[[*O A;ooDFXʇZ95 5]Ip2TK ŷvRs.b[PY&$^H#,`t~ξu/GbAKPi`I(uN oVL€@Zʠhc L#X9rsQ sg{Hjq  {QpWH ` Uqe3$4 9t خbeJJ/1VU E x=dy e@Cd5h@gQ0 F(+G^mtx-1.3.12/contrib/tapechanger.html0000664002342000234200000002003210637472152016573 0ustar robertrobert TapeChanger::MTX - use 'mtx' to manipulate a tape library

NAME

TapeChanger::MTX - use 'mtx' to manipulate a tape library


SYNOPSIS

  use TapeChanger::MTX;
  my $loaded = TapeChanger::MTX->loadedtape;
  print "Currently loaded: $loaded\n" if ($loaded);
  TapeChanger::MTX->loadtape('next');
  my $nowloaded = TapeChanger::MTX->loadedtape; 
  print "Currently loaded: $nowloaded\n" if ($nowloaded);

See below for more available functions.


DESCRIPTION

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.


VARIABLES

$TapeChanger::MTX::MT =item $TapeChanger::MTX::MTX
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'.

$TapeChanger::MTX::DRIVE
$TapeChanger::MTX::CONTROL
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.

$TapeChanger::MTX::EJECT
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'.

$TapeChanger::MTX::READY_TIME
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.

$TapeChanger::MTX::DEBUG
Print debugging information? Set to '0' for normal verbosity, '1' for debugging information, or '-1' for 'quiet mode' (be as quiet as possible).


USAGE

This module uses the following functions:

tape_cmd ( COMMAND )
mt_cmd ( COMMAND )
Runs 'mtx' and 'mt' as appropriate. COMMAND 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.

numdrives ()
numslots ()
loadedtape ()
Returns the number of drives, number of slots, and currently loaded tape values, respectively, by parsing tape_cmd('status').

loadtape ( SLOT [, DRIVE] )
Loads a tape into the tape changer, and waits until the drive is again ready to be written to. SLOT can be any of the following (with the relevant function indicated):
  current       C<loadedtape()>
  prev          C<loadprevtape()>
  next          C<loadnexttape()>
  first         C<loadfirsttape()>
  last          C<loadlasttape()>
  0             C<_ejectdrive()>
  1..99         Loads the specified tape number, ejecting whatever is
                currently in the drive.

DRIVE is the drive to load, and defaults to 0. Returns 0 if successful, an error string otherwise.

loadnexttape ()
loadprevtape ()
loadfirsttape ()
loadlasttape ()
Loads the next, previous, first, and last tapes in the changer respectively. Use tape_cmd('next'), tape_cmd('previous'), tape_cmd('first'), and tape_cmd('last'), respectively.

ejecttape ()
Ejects the tape, by first ejecting the tape from the drive (mt_cmd(rewind) then mt_cmd(offline)) and then returning it to its slot (tape_cmd(unload)). Returns 1 if successful, 0 otherwise.

resetchanger ()
Resets the changer, ejecting the tape and loading the first one from the changer.

checkdrive ()
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 mt_cmd(status). Returns 1 if so, 0 otherwise.

reportstatus
Returns a string containing the loaded tape and the drive that it's mounted on.

cannot_run ()
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.


NOTES

~/.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 setuid() 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.


REQUIREMENTS

Perl 5.6.0 or better, an installed 'mtx' binary, and a tape changer and reader connected to the system.


TODO

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).


SEE ALSO

mtx, mt, tapechanger. Inspired by stc-changer, which comes with the AMANDA tape backup package (http://www.amanda.org), and MTX, available at http://mtx.sourceforge.net.


AUTHOR

Tim Skirvin <tskirvin@uiuc.edu>


COPYRIGHT

Copyright 2001-2002 by the University of Illinois Board of Trustees and Tim Skirvin <tskirvin@ks.uiuc.edu>.

mtx-1.3.12/debian/0000775002342000234200000000000011052512015013172 5ustar robertrobertmtx-1.3.12/debian/dirs0000664002342000234200000000003711052333055014063 0ustar robertrobertetc/bash_completion.d usr/sbin mtx-1.3.12/debian/copyright0000664002342000234200000000076611052333376015151 0ustar robertrobertThis 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 Changes copyright 2000, 2001 Eric Green Changes copyright 2007-2008 by Robert Nelson 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'. mtx-1.3.12/debian/changelog0000664002342000234200000001240011052512011015035 0ustar robertrobertmtx (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 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 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 Sat, 19 Aug 2006 18:44:54 -0600 mtx (1.2.17rel-1) unstable; urgency=low * new upstream version -- Bdale Garbee 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 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 Sat, 14 Feb 2004 22:36:23 -0700 mtx (1.2.16rel-3) unstable; urgency=low * apply patch from Torsten Werner that elminates hard-coding of the value of HZ, closes: #224147 -- Bdale Garbee Tue, 16 Dec 2003 10:04:26 -0700 mtx (1.2.16rel-2) unstable; urgency=low * apply patch from R.A.Owen that fixes the "staggered" output from the status command on some changers, closes: #129910 -- Bdale Garbee 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 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 Sun, 30 Dec 2001 21:28:46 -0700 mtx (1.2.10-1) unstable; urgency=low * new upstream source -- Bdale Garbee 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 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 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 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 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 Tue, 27 Jan 1998 15:06:13 -0700 mtx (1.0-5) unstable; urgency=low * explicit include path to find in the /usr/src/linux/include tree. closes bug 16877 -- Bdale Garbee 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 Sun, 21 Sep 1997 02:38:50 -0600 mtx (1.0-3) unstable; urgency=low * libc6 -- Bdale Garbee 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 Sun, 10 Aug 1997 03:50:42 -0600 mtx (1.0-1) unstable; urgency=low * Initial Release. -- Bdale Garbee Sun, 10 Aug 1997 03:05:18 -0600 mtx-1.3.12/debian/rules0000775002342000234200000000263211052333055014262 0ustar robertrobert#!/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 mtx-1.3.12/debian/compat0000664002342000234200000000000211052510145014372 0ustar robertrobert4 mtx-1.3.12/debian/bash_completion0000664002342000234200000000201211052333055016263 0ustar robertrobert# mtx completion by Jon Middleton # # $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 mtx-1.3.12/debian/control0000664002342000234200000000115011052510176014600 0ustar robertrobertSource: mtx Section: admin Priority: extra Maintainer: Robert Nelson 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. mtx-1.3.12/FAQ0000664002342000234200000001514510637472152012327 0ustar robertrobertFrequently 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. mtx-1.3.12/scsieject.10000664002342000234200000000750011052334173014017 0ustar robertrobert.\" 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 ] 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 based on the scsitape program written by Eric Lee Green . 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 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) mtx-1.3.12/tapeinfo.10000664002342000234200000000610411052334224013644 0ustar robertrobert.\" tapeinfo.1 Document copyright 2000 Eric Lee Green .\" Program Copyright 2000 Eric Lee Green .\" Copyright 2007-2008 by 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 TAPEINFO 1 TAPEINFO1.0 .SH NAME tapeinfo \- report SCSI tape device info .SH SYNOPSIS tapeinfo -f .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 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) mtx-1.3.12/mam2debug2.c0000664002342000234200000000611611052515177014061 0ustar robertrobert/* Mammoth 2 Debug Buffer Dumper Copyright 2000 Enhanced Software Technologies Inc. Copyright 2007-2008 by Robert Nelson $Date: 2008-08-19 03:03:38 -0700 (Tue, 19 Aug 2008) $ $Revision: 193 $ Written by Eric Lee Green 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 #include #include #include #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); } mtx-1.3.12/du/0000775002342000234200000000000010667407504012401 5ustar robertrobertmtx-1.3.12/du/defs.h0000664002342000234200000000075610637472151013500 0ustar robertrobert#include #include #include #include #include #include #include typedef int DEVICE_TYPE; #ifdef __osf__ #include #include #include #else /* must be ultrix */ #include #endif #include #include #include #include #define DEV_CAM "/dev/cam" /* CAM device path */ #define DIGITAL_UNIX mtx-1.3.12/du/scsi.c0000664002342000234200000001303210637472151013502 0ustar robertrobert/* 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; }