Newsgroups: alt.sources Subject: zoo 2.1 source part 08/15 Message-ID: <12775@bsu-cs.bsu.edu> From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi) Date: 10 Jul 91 10:19:34 GMT Checksum: 1455346899 (verify with "brik -cv") Submitted-by: dhesi@bsu-cs.bsu.edu Archive-name: zoo210/part08 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is part 08 of zoo210 # ============= prterror.c ============== if test -f 'prterror.c' -a X"$1" != X"-c"; then echo 'x - skipping prterror.c (File already exists)' else echo 'x - extracting prterror.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'prterror.c' && #ifndef LINT /* @(#) prterror.c 2.8 88/01/31 18:48:17 */ static char sccsid[]="@(#) prterror.c 2.8 88/01/31 18:48:17"; #endif /* LINT */ X /* The contents of this file are hereby released to the public domain. X X -- Rahul Dhesi 1986/11/14 X */ X #include "options.h" #ifndef OK_STDIO #include #define OK_STDIO #endif #include "various.h" #include "zooio.h" #include "zoofns.h" X #ifdef NEEDCTYP # include /* for isdigit() */ #endif X #ifdef STDARG # include #else # ifdef VARARGS # include # else # include "MUST DEFINE STDARG OR VARARGS" # endif #endif X #ifdef NEED_VPRINTF static int zvfprintf(); #endif X /* General error handler. Input format: X X parameter 1: 'w', 'e', or 'f'. X X 'm': message X 'M': message without preceding identification X 'w': WARNING X 'e': ERROR X 'f': FATAL X 'F': FATAL but program doesn't exist immediately X X All text printed is preceded by "Zoo: " or "Ooz: " depending X upon conditional compilation, except in the case of 'M' messages X which are printed without any text being added. X X For messages, the text supplied is printed if and only if the global X variable "quiet" is zero. Control then returns to the caller. X X For warnings, errors, and fatal errors, the variable "quiet" is used X as follows. Warning messages are suppressed if quiet > 1; error X messages are suppressed if quiet > 2. Fatal error messages are X never suppressed--doing so would be a bit risky. X X For warnings and errors, the error message is preceded by the "WARNING:" X or "ERROR". The error message is printed and control returns to the X caller. X X For fatal errors, the error message is preceded by "FATAL:" and an X error message is printed. If the option was 'f', the program exits with X a status of 1. If the option was 'F', control returns to the caller and X it is assumed that the caller will do any cleaning up necessary and then X exit with an error status. X X parameter 2: The format control string for printf. X remining parameters: passed on to vprintf(). X X All messages, whether informative or error, are sent to standard X output via printf. It might be a good idea to eventually send 'e' and X 'f' class messages to the standard error stream. Best would be X some way of telling if standard output and standard error are not X the same device, so that we could always send error messages to X standard error, and also duplicate them to standard output if X different from standard error. This is one thing that VMS seems X to be capable of doing. There seems to be no way of doing this X in the general case. */ X extern int quiet; X /* These declarations must be equivalent to those in errors.i */ char no_match[] = "No files matched.\n"; char failed_consistency[] = "Archive header failed consistency check.\n"; char invalid_header[] = "Invalid or corrupted archive.\n"; char internal_error[]="Internal error.\n"; char disk_full[] = "I/O error or disk full.\n"; char bad_directory[] = "Directory entry in archive is invalid.\n"; char no_memory[] = "Ran out of memory.\n"; char too_many_files[] = "Some filenames ignored -- can only handle %d.\n"; char packfirst[] = "Old format archive -- please pack first with P command.\n"; char garbled[] = "Command is garbled.\n"; char start_ofs[] = "Starting at %ld (offset %ld)\n"; X #ifndef OOZ char wrong_version[]= X "Zoo %d.%d or later is needed to fully manipulate this archive.\n"; char cant_process[] = X "The rest of the archive (%lu bytes) cannot be processed.\n"; char option_ignored[] = "Ignoring option %c.\n"; char inv_option[] = "Option %c is invalid.\n"; char bad_crc[] = "\007Bad CRC, %s probably corrupted\n"; #endif X #ifdef OOZ char could_not_open[] = "Could not open "; #else char could_not_open[] = "Could not open %s.\n"; #endif X #ifdef STDARG void prterror(int level, char *format, ...) #else /*VARARGS*/ void prterror(va_alist) va_dcl #endif { X va_list args; X char string[120]; /* local format string */ #ifdef VARARGS X int level; X char *format; #endif X #ifdef STDARG X va_start(args, format); #else X va_start(args); X level = va_arg(args, int); X format = va_arg(args, char *); #endif X X *string = '\0'; /* get a null string to begin with */ X #ifdef OOZ X strcpy (string, "Ooz: "); #else X strcpy (string, "Zoo: "); #endif X X switch (level) { X case 'M': *string = '\0'; /* fall through to 'm' */ X case 'm': if (quiet) return; break; X case 'w': X if (quiet > 1) return; X strcat (string, "WARNING: "); break; X case 'e': X if (quiet > 2) return; X strcat (string, "ERROR: "); break; X case 'F': X case 'f': strcat (string, "FATAL: "); break; X default: prterror ('f', internal_error); /* slick recursive call */ X } X X strcat (string, format); /* just append supplied format string */ X X /* and print the whole thing */ #ifdef NEED_VPRINTF X (void) zvfprintf(stdout, string, args); #else X (void) vprintf(string, args); #endif X fflush (stdout); X X if (level == 'f') /* and abort on fatal error 'f' but not 'F' */ X zooexit (1); } X X #ifdef NEED_VPRINTF /* Some systems don't have vprintf; if so, we roll our own. The following has been adapted from a Usenet posting by Jef Poskanzer . X This is a portable mini-vfprintf that depends only on fprintf. X We don't call this routine vfprintf to avoid unexpected conflicts with any library routine of the same name, notwithstanding the fact that we will usually use it only when there is no conflict. Also, even though we only need vprintf, the routine used here implements vfprintf. This will allow future uses as needed when output is to be sent to a stream other than stdout. */ X /* Whether to support double. Better not to, because it may cause math stuff to be linked in */ X #undef NEED_DOUBLE X static int zvfprintf(stream, format, args) FILE *stream; char *format; va_list args; { X char *ep; X char fchar; X char tformat[512]; X int do_long; /* whether to print as long (l format suffix) */ X int do_star; /* * used in format => get width from argument */ X int star_size; /* size arg corresponding to "*" format */ X int i; X long l; X unsigned u; X unsigned long ul; X char *s; #ifdef NEED_DOUBLE X double d; #endif X X while (*format != '\0') { X if (*format != '%') { /* Not special, just write out the char. */ X putc(*format, stream); X ++format; X } else { X do_star = 0; X do_long = 0; X ep = format + 1; X X /* Skip over all the field width and precision junk. */ X if (*ep == '-') X ++ep; X if (*ep == '0') X ++ep; X while (isdigit(*ep)) X ++ep; X if (*ep == '.') { X ++ep; X while (isdigit(*ep)) X ++ep; X } X if (*ep == '#') X ++ep; X if (*ep == '*') { X do_star = 1; X star_size = va_arg(args, int); /* get * argument */ X ++ep; X } X if (*ep == 'l') { X do_long = 1; X ++ep; X } X X /* Here's the field type. Extract it, and copy this format X ** specifier to a temp string so we can add an end-of-string. X */ X fchar = *ep; X (void) strncpy(tformat, format, ep - format + 1); X tformat[ep - format + 1] = '\0'; X X /* Now do a one-argument printf with the format string we have X isolated. If the * format was used, we will also supply the X additional parameter star_size, which we have already obtained X from the variable argument list. */ X X switch (fchar) { X case 'd': X if (do_long) { X l = va_arg(args, long); X if (do_star) X (void) fprintf(stream, tformat, star_size, l); X else X (void) fprintf(stream, tformat, l); X } else { X i = va_arg(args, int); X if (do_star) X (void) fprintf(stream, tformat, star_size, i); X else X (void) fprintf(stream, tformat, i); X } X break; X X case 'o': X case 'x': X case 'u': X if (do_long) { X ul = va_arg(args, unsigned long); X if (do_star) X (void) fprintf(stream, tformat, star_size, ul); X else X (void) fprintf(stream, tformat, ul); X } else { X u = va_arg(args, unsigned); X if (do_star) X (void) fprintf(stream, tformat, star_size, u); X else X (void) fprintf(stream, tformat, u); X } X break; X X case 'c': X i = (char) va_arg(args, int); X if (do_star) X (void) fprintf(stream, tformat, star_size, i); X else X (void) fprintf(stream, tformat, i); X break; X X case 's': X s = va_arg(args, char *); X if (do_star) X (void) fprintf(stream, tformat, star_size, s); X else X (void) fprintf(stream, tformat, s); X break; X #ifdef NEED_DOUBLE X case 'e': X case 'f': X case 'g': X d = va_arg(args, double); X if (do_star) X (void) fprintf(stream, tformat, star_size, d); X else X (void) fprintf(stream, tformat, d); X break; #endif X X case '%': X putc('%', stream); X break; X X default: X return -1; X } X X /* Resume formatting on the next character. */ X format = ep + 1; X } X } X va_end(args); X return 0; } #endif /*NEED_VPRINTF*/ SHAR_EOF chmod 0644 prterror.c || echo 'restore of prterror.c failed' Wc_c="`wc -c < 'prterror.c'`" test 9094 -eq "$Wc_c" || echo 'prterror.c: original size 9094, current size' "$Wc_c" fi # ============= sysv.c ============== if test -f 'sysv.c' -a X"$1" != X"-c"; then echo 'x - skipping sysv.c (File already exists)' else echo 'x - extracting sysv.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'sysv.c' && #ifndef LINT /* @(#) sysv.c 2.5 88/01/10 14:47:24 */ static char sysvid[]="@(#) sysv.c 2.5 88/01/10 14:47:24"; #endif /* LINT */ X /* machine.c for System V */ X /* The contents of this file are hereby released to the public domain. X X -- Rahul Dhesi 1986/12/31 */ X #ifdef UNBUF_IO /* do not use */ /* Function tell() returns the current seek position for a file descriptor. Microport System V/AT has an undocumented tell() library function (why?) but the **IX PC doesn't, so we code one here. It is needed for unbuffered I/O only. */ long lseek PARMS ((int, long, int)); long tell (fd) int fd; { return (lseek (fd, 0L, 1)); } #endif /* UNBUF_IO */ X /**************** Date and time functions are standard **IX-style functions. "nixtime.i" will be included by machine.c. */ X #include #include #include X /* Function isadir() returns 1 if the supplied handle is a directory, else it returns 0. */ X int isadir (file) ZOOFILE file; { X int handle = fileno(file); X struct stat buf; /* buffer to hold file information */ X if (fstat (handle, &buf) == -1) { X return (0); /* inaccessible -- assume not dir */ X } else { X if (buf.st_mode & S_IFDIR) X return (1); X else X return (0); X } } X /**************** Function fixfname() converts the supplied filename to a syntax legal for the host system. It is used during extraction. */ X char *fixfname(fname) char *fname; { X return (fname); /* default is no-op */ } X extern long timezone; /* defined by library routine */ long time (); struct tm *localtime (); X /* Function gettz(), returns the offset from GMT in seconds of the local time, taking into account daylight savings time */ X #if 1 /* Following should work for System V */ long gettz() { #define SEC_IN_DAY (24L * 60L * 60L) #define INV_VALUE (SEC_IN_DAY + 1L) X static long retval = INV_VALUE; /* cache, init to impossible value */ X struct tm *tm; X long clock; X if (retval != INV_VALUE) /* if have cached value, return it */ X return retval; X clock = time ((long *) 0); X tm = localtime (&clock); X retval = timezone - tm->tm_isdst*3600; X return retval; } #else /* This version of gettz should be portable to all Unices, although it can't X be described as elegant. Users immediately west of the International X Date Line (Polynesia, Soviet Far East) may get times out by 24 hours. X Contributed by: Ian Phillipps */ X /* Function gettz(), returns the offset from GMT in seconds */ long gettz() { #define NOONOFFSET 43200 #define SEC_IN_DAY (24L * 60L * 60L) #define INV_VALUE (SEC_IN_DAY + 1L) X static long retval = INV_VALUE; /* cache, init to impossible value */ X extern long time(); X extern struct tm *localtime(); X long now; X long noon; X struct tm *noontm; X if (retval != INV_VALUE) /* if have cached value, return it */ X return retval; X now = time((long *) 0); X /* Find local time for GMT noon today */ X noon = now - now % SEC_IN_DAY + NOONOFFSET ; X noontm = localtime( &noon ); X retval = NOONOFFSET - 60 * ( 60 * noontm->tm_hour - noontm->tm_min ); X return retval; #undef NOONOFFSET } #endif X /* Standard **IX-compatible time functions */ #include "nixtime.i" X /* Standard **IX-specific file attribute routines */ #include "nixmode.i" X /* Make a directory. System V has no system call accessible to ordinary users to make a new directory. Hence we spawn a shell and hope /bin/mkdir is there. Since /bin/mkdir gives a nasty error message if it fails, we call it only if nothing already exists by the name of the needed directory. */ X int mkdir(dirname) char *dirname; { X char cmd[PATHSIZE+11+1]; /* room for "/bin/mkdir " used below + 1 spare */ X if (!exists(dirname)) { X strcpy(cmd, "/bin/mkdir "); X strcat(cmd, dirname); X return (system(cmd)); X } X return (0); } X /* No file truncate system call in older System V. If yours has one, add it here -- see bsd.c for example. It's ok for zootrunc to be a no-op. */ /*ARGSUSED*/ int zootrunc(f) FILE *f; { return 0; } X SHAR_EOF chmod 0644 sysv.c || echo 'restore of sysv.c failed' Wc_c="`wc -c < 'sysv.c'`" test 4088 -eq "$Wc_c" || echo 'sysv.c: original size 4088, current size' "$Wc_c" fi # ============= turboc.c ============== if test -f 'turboc.c' -a X"$1" != X"-c"; then echo 'x - skipping turboc.c (File already exists)' else echo 'x - extracting turboc.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'turboc.c' && /* @(#) turboc.c 1.2 87/06/21 16:08:54 */ X int _stklen = 30000; /* stack size in bytes */ void _setenvp() {} /* don't initialize environment pointer etc. */ #include /* to get fileno() */ X /* following not needed any more since zoocreate() is fixed in portable.c */ /* unsigned _fmode = O_BINARY; */ X void dosname PARMS((char *, char *)); #ifdef ANSI_HDRS # include #else char *strcpy PARMS((char *, char *)); #endif X #include X /* register definitions specific for Turbo C */ union REGS { X struct { unsigned ax, bx, cx, dx, si, di, carry, flags; } x; X struct { unsigned char al, ah, bl, bh, cl, ch, dl, dh; } h; }; X /**************** function zootrunc() truncates a file at the current seek position. */ X int zootrunc (f) FILE *f; { X int handle = fileno(f); X extern long tell(); X extern int chsize(); X return chsize(handle, tell(handle)); } X /**************** Function fixfname() converts the supplied filename to a syntax legal for the host system. It is used during extraction. */ X char *fixfname(fname) char *fname; { X char tmpname[PATHSIZE]; X dosname (nameptr(fname), tmpname); X strcpy(fname,tmpname); X return(fname); } X static int set_break (int flag) { X extern int intdos(); X int retval; X union REGS regs; X regs.x.ax = 0x3300; /* get ctrl-break flag */ X intdos (®s, ®s); X retval = regs.h.dl; /* retval is old value of setting */ X regs.x.ax = 0x3301; /* set ctrl-break flag */ X regs.h.dl = flag; /* status to set to */ X intdos (®s, ®s); X return (retval); } X static int break_flag; X void zooexit (int status) { X set_break (break_flag); /* restore control_break setting */ X exit (status); } X void gentab (void); X void spec_init(void) { X break_flag = set_break (0); X signal (SIGINT, zooexit); /* install our own control-C handler */ } X #ifndef fileno /* To allow compilation with -A (for testing), which makes fileno() unavailable, we define a function here by that name. This may be compiler-specific for Turbo C++ 1.0. */ X int fileno(f) FILE *f; { X return f->fd; } #endif /* ! fileno */ SHAR_EOF chmod 0644 turboc.c || echo 'restore of turboc.c failed' Wc_c="`wc -c < 'turboc.c'`" test 2063 -eq "$Wc_c" || echo 'turboc.c: original size 2063, current size' "$Wc_c" fi # ============= turboc.cfg ============== if test -f 'turboc.cfg' -a X"$1" != X"-c"; then echo 'x - skipping turboc.cfg (File already exists)' else echo 'x - extracting turboc.cfg (Text)' sed 's/^X//' << 'SHAR_EOF' > 'turboc.cfg' && -IC:\TC\INCLUDE -LC:\TC\LIB -a -f- -k- -v- -G -O -Z -c -O -wrvl -wamb -wamp -wnod -wstv -wuse -wcln -wsig -wucp SHAR_EOF chmod 0644 turboc.cfg || echo 'restore of turboc.cfg failed' Wc_c="`wc -c < 'turboc.cfg'`" test 113 -eq "$Wc_c" || echo 'turboc.cfg: original size 113, current size' "$Wc_c" fi # ============= various.h ============== if test -f 'various.h' -a X"$1" != X"-c"; then echo 'x - skipping various.h (File already exists)' else echo 'x - extracting various.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'various.h' && /* @(#) various.h 2.3 87/12/27 14:44:34 */ X /* The contents of this file are hereby released to the public domain. X X -- Rahul Dhesi 1986/11/14 */ X /* This files gives definitions for most external functions used by Zoo. If ANSI_PROTO is defined, ANSI-style function prototypes are used, else normal K&R function declarations are used. X Note: Always precede this file with an include of stdio.h because it uses the predefined type FILE. */ X #ifndef PARMS #ifdef ANSI_PROTO #define PARMS(x) x #else #define PARMS(x) () #endif #endif X #ifdef ANSI_HDRS /* if not defined in stdio.h */ # include # include #else FILE *fdopen PARMS ((int, char *)); FILE *fopen PARMS ((char *, char *)); char *fgets PARMS ((char *, int, FILE *)); char *gets PARMS ((char *)); VOIDPTR malloc PARMS ((unsigned int)); VOIDPTR realloc PARMS ((char *, unsigned int)); char *strcat PARMS ((char *, char *)); char *strchr PARMS ((char *, int)); char *strcpy PARMS ((char *, char *)); char *strncat PARMS ((char *, char *, unsigned int)); char *strncpy PARMS ((char *, char *, unsigned int)); char *strrchr PARMS ((char *, int)); int fclose PARMS ((FILE *)); int fflush PARMS ((FILE *)); int fgetc PARMS ((FILE *)); int fgetchar PARMS (()); int fprintf PARMS ((FILE *, char *, ...)); int fputchar PARMS ((int)); int fputs PARMS ((char *, FILE *)); X #ifndef NO_STDIO_FN # ifdef ALWAYS_INT int fputc PARMS ((int, FILE *)); int fread PARMS ((VOIDPTR, int, int, FILE *)); int fwrite PARMS ((VOIDPTR, int, int, FILE *)); # else int fputc PARMS ((char, FILE *)); int fread PARMS ((VOIDPTR, unsigned, unsigned, FILE *)); int fwrite PARMS ((VOIDPTR, unsigned, unsigned, FILE *)); # endif /* ALWAYS_INT */ #endif /* NO_STDIO_FN */ X int fseek PARMS ((FILE *, long, int)); int printf PARMS ((char *, ...)); int rename PARMS ((char *, char *)); int setmode PARMS ((int, int)); int strcmp PARMS ((char *, char *)); int strncmp PARMS ((char *, char *, unsigned int)); int unlink PARMS ((char *)); long ftell PARMS ((FILE *)); unsigned int strlen PARMS ((char *)); X #endif /* ! ANSI_HDRS */ X SHAR_EOF chmod 0644 various.h || echo 'restore of various.h failed' Wc_c="`wc -c < 'various.h'`" test 2097 -eq "$Wc_c" || echo 'various.h: original size 2097, current size' "$Wc_c" fi # ============= version.c ============== if test -f 'version.c' -a X"$1" != X"-c"; then echo 'x - skipping version.c (File already exists)' else echo 'x - extracting version.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'version.c' && /* derived from: version.c 2.9 1988/08/25 12:43:57 */ char version[] = "zoo 2.1 $Date: 91/07/09 02:10:34 $"; SHAR_EOF chmod 0644 version.c || echo 'restore of version.c failed' Wc_c="`wc -c < 'version.c'`" test 111 -eq "$Wc_c" || echo 'version.c: original size 111, current size' "$Wc_c" fi # ============= vms.c ============== if test -f 'vms.c' -a X"$1" != X"-c"; then echo 'x - skipping vms.c (File already exists)' else echo 'x - extracting vms.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'vms.c' && #ifndef LINT /* derived from: @(#) vms.c 2.2 88/01/09 03:47:52 */ static char vmsid[]="$Source: /usr/home/dhesi/zoo/RCS/vms.c,v $\n\ $Id: vms.c,v 1.10 91/07/07 14:41:17 dhesi Exp $"; #endif /* LINT */ X /* Support routines for VAX/VMS. */ X #include #include X /* our own version of NULL; avoid any interaction with system defn. but don't require inclusion of stdio.h */ #define NILPTR 0 X /* Function isuadir() returns 1 if the supplied filename is a directory, else it returns 0. */ X int isuadir (file) char *file; { X struct stat buf; /* buffer to hold file information */ X if (stat (file, &buf) == -1) { X return (0); /* inaccessible -- assume not dir */ X } else { X if (buf.st_mode & S_IFDIR) X return (1); X else X return (0); X } } X /**************** Function fixfname() converts the supplied filename to a syntax legal for the host system. It is used during extraction. We allow a maximum of one dot in the filename, and it must not be at the beginning. We also truncate the number of charac- ters preceding and following the dot to at most 39. */ X char *strchr(); X char *fixfname(fname) char *fname; { X char *p; X char *dotpos; X static char legal[] = X "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_.0123456789"; X X /* convert all characters to legal characters */ X for (p = fname; *p != '\0'; p++) X if (strchr (legal, *p) == 0) { X if (*p == '-' || *p == ' ') X *p = '_'; X else X *p = legal [ *p % 26 ]; X } X X /* first char can't be dot */ X if (*fname == '.') X *fname = 'X'; X X /* find embedded dot if any */ X dotpos = strchr (fname, '.'); X X if (dotpos != NILPTR) { X for (p = dotpos+1; *p != '\0'; p++) /* remove 2nd dot onwards */ X if (*p == '.') X *p = '_'; X if (dotpos - fname + 1 > 39) { /* more than 39 before dot not allowed */ X char *q; X p = fname + 39; X q = dotpos; X while (*p++ = *q++) /* the notational convenience is considerable */ X ; X dotpos = strchr (fname, '.'); X } X if (strlen (dotpos + 1) > 39) /* more than 39 after dot not allowed */ X *(dotpos + 39 + 1) = '\0'; X } else X *(fname + 39) = '\0'; /* no dots, just truncate to 39 characters */ X return (fname); } X /* Function gettz(), returns the offset from GMT in seconds of the local time, taking into account daylight savings time -- or it would, if VAX/VMS knew about timezones! It's just a no-op. */ long gettz() { X return 0L; } X struct tm *localtime(); X /***************** Function gettime() gets the date and time of the file handle supplied. Date and time is in MSDOS format. This function duplicated from nixtime.i. */ X int gettime (file, date, time) ZOOFILE file; unsigned *date, *time; { X struct stat buf; /* buffer to hold file information */ X struct tm *tm; /* will hold year/month/day etc. */ X int handle; X handle = fileno(file); X if (fstat (handle, &buf) == -1) { X prterror ('w', "Could not get file time\n"); X *date = *time = 0; X } else { X tm = localtime (&buf.st_mtime); /* get info about file mod time */ X *date = tm->tm_mday + ((tm->tm_mon + 1) << 5) + X ((tm->tm_year - 80) << 9); X *time = tm->tm_sec / 2 + (tm->tm_min << 5) + X (tm->tm_hour << 11); X } X } X /* Function unlink() will delete a file using the VMS C delete() function. */ int unlink (fname) char *fname; { X return (delete (fname)); } X /* Function zooexit() receives attempts at exit. It always invokes exit() with status=1. */ void zooexit (status) int status; { X exit (1); } X X /* Function rename() renames a file. Thanks to Owen Anthony (was at one time). */ X #include X #ifdef NEED_VMS_RENAME /* if not using VMS 4.6 library rename() */ int rename (old_name, new_name) char *old_name; char *new_name; { X int status; X struct dsc$descriptor_s file1, file2; X file1.dsc$w_length = strlen (old_name); /* descriptor for old name */ X file1.dsc$a_pointer = old_name; X file1.dsc$b_class = DSC$K_CLASS_S; X file1.dsc$b_dtype = DSC$K_DTYPE_T; X file2.dsc$w_length = strlen (new_name); /* descriptor for new name */ X file2.dsc$a_pointer = new_name; X file2.dsc$b_class = DSC$K_CLASS_S; X file2.dsc$b_dtype = DSC$K_DTYPE_T; X X status = LIB$RENAME_FILE (&file1, &file2); X X return ((status & ~1) == 1); } #endif /* VMS_RENAME */ X /* Function specfname() modifies filenames before they are stored in an archive. Currently we remove any trailing version field, and then any trailing dot. */ char *specfname (fname) char *fname; { X char *p; X p = strchr (fname, ';'); X if (p != NILPTR) X *p = '\0'; X if (*fname != '\0') { X p = fname + strlen (fname) - 1; /* point to last char */ X if (*p == '.') /* remove any trailing dot */ X *p = '\0'; X } X return (fname); } X /* Function specdir() modifies directory names before they are stored in an archive. We remove any leading device name or logical name and and the [ and ] that bracket any directory name. Then we change any dots in the directory name to slashes. */ X #if 0 /* test stub that just truncates dir to null string */ char *specdir (fname) char *fname; { *fname = '\0'; return (fname); } #else X char *specdir (fname) char *fname; { X char *p; X char tmpstr[LFNAMESIZE]; X X p = strchr (fname, ':'); /* remove chars upto and including : */ X if (p != NILPTR) { X strcpy (tmpstr, p+1); X strcpy (fname, tmpstr); X } X X p = strchr (fname, '['); /* remove chars upto and including [ */ X if (p != NILPTR) { X strcpy (tmpstr, p+1); X strcpy (fname, tmpstr); X } X X p = strchr (fname, ']'); /* truncate at ] */ X if (p != NILPTR) { X if (*(p+1) != '\0') X prterror ('w', "Trailing garbage in directory name\n"); X *p = '\0'; X } X X for (p = fname; *p != '\0'; p++) /* change dots to slashes */ X if (*p == '.') X *p = '/'; X X /* make sure there is a leading slash -- just a hack for now */ X if (*fname != '/') { X strcpy (tmpstr, fname); X strcpy (fname, "/"); X strcat (fname, tmpstr); X } X #ifdef DEBUG printf ("dir name transformed to \"%s\"\n", fname); #endif } #endif X #define FMAX 3 /* Number of different filename patterns */ X char *nextfile (what, filespec, fileset) int what; /* whether to initialize or match */ register char *filespec; /* filespec to match if initializing */ register int fileset; /* which set of files */ { X int status; X char *p; /* temp ptr */ X struct dsc$descriptor_s d_fwild, d_ffound; X static int first_time [FMAX+1]; X static char saved_fspec [FMAX+1][PATHSIZE]; /* our own copy of filespec */ X static char found_fspec [FMAX+1][PATHSIZE]; /* matched filename */ X static unsigned long context [FMAX+1]; /* needed by VMS */ X if (what == 0) { X strcpy (saved_fspec[fileset], filespec); /* save the filespec */ X first_time[fileset] = 1; X return (0); X } X X /* Reach here if what is not 0, so it must be 1 */ X X /* Create a descriptor for the wildcarded filespec */ X d_fwild.dsc$w_length = strlen (saved_fspec[fileset]); X d_fwild.dsc$a_pointer = saved_fspec[fileset]; X d_fwild.dsc$b_class = DSC$K_CLASS_S; X d_fwild.dsc$b_dtype = DSC$K_DTYPE_T; X X d_ffound.dsc$w_length = sizeof (found_fspec[fileset]); X d_ffound.dsc$a_pointer = found_fspec[fileset]; X d_ffound.dsc$b_class = DSC$K_CLASS_S; X d_ffound.dsc$b_dtype = DSC$K_DTYPE_T; X X if (first_time[fileset]) { X first_time[fileset] = 0; X context[fileset] = 0L; /* tell VMS this is first search */ X } X status = LIB$FIND_FILE (&d_fwild, &d_ffound, &context[fileset]); X status = status & 1; /* use only lowest bit */ X X if (status == 0) { X LIB$FIND_FILE_END (&context[fileset]); X return ((char *) 0); X } else { X found_fspec[fileset][d_ffound.dsc$w_length] = '\0'; /* just in case */ X p = found_fspec[fileset]; X while (*p != ' ' && *p != '\0') X p++; X if (*p != '\0') X *p = '\0'; X return (found_fspec[fileset]); X } } X /* Function vmsmkdir() converts the received directory name into VMS format and then creates a directory. */ int vmsmkdir (subdir) char *subdir; { X char *lastptr(); X char *p; X char tmp[LFNAMESIZE]; X X p = subdir; X X /* leading "/" => "[", otherwise => "[." */ X if (*p == '/') { X strcpy (tmp, "["); X p++; X } else { X strcpy (tmp, "[."); X while (*p == '/' || *p == '.') X p++; X } X X strcat (tmp, p); X X /* X VMS doesn't like dots in directory names, so we convert them to X underscores. Leave first two characters untouched, because X we don't want to corrupt a leading "[." into "[_". X */ X for (p = tmp + 2; *p != '\0'; p++) X if (*p == '.') X *p = '_'; X X /* convert all slashes to dots */ X for (p = tmp; *p != '\0'; p++) X if (*p == '/') X *p = '.'; X X /* Remove any trailing dot */ X p = lastptr (tmp); X if (*p == '.') X *p = '\0'; X X /* append closing bracket */ X strcat (tmp, "]"); #if 0 X printf ("\nmaking directory \"%s\"\n", tmp); #endif X return (mkdir (tmp, 0)); } X /* Function spec_wild() transforms a pattern supplied on the command line into one suitable for wildcard expansion in the most efficient way possible. We change each "?" to "%" but let "*" remain unchanged. We also append a ".*" if the pattern contains no dot, so "*" will be interpreted as "*.*" for VMS globbing. */ char *spec_wild (arg) char *arg; { X char *p; #ifdef DEBUG X printf ("spec_wild: arg = [%s]\n", arg); #endif X if (*lastptr (arg) == ']') /* add *.* if no filename */ X strcat (arg, "*.*"); X p = nameptr (arg); /* point p to filename part */ X X /* if no dot in name append ".*" */ X if (strchr (p, '.') == NILPTR) X strcat (p, ".*"); X X for ( ; *p != '\0'; p++) /* change every "?" to "%" */ X if (*p == '?') X *p = '%'; #ifdef DEBUG X printf ("spec_wild: arg changed to [%s]\n", arg); #endif X return (arg); } X int zootrunc(f) FILE *f; { return 0; } SHAR_EOF chmod 0644 vms.c || echo 'restore of vms.c failed' Wc_c="`wc -c < 'vms.c'`" test 10243 -eq "$Wc_c" || echo 'vms.c: original size 10243, current size' "$Wc_c" fi true || echo 'restore of vmsbugs.doc failed' echo End of part 8, continue with part 9 exit 0