Annotation of coherent/b/bin/zip/fileio.c, revision 1.1

1.1     ! root        1: /*
        !             2: 
        !             3:  Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
        !             4:  Kai Uwe Rommel and Igor Mandrichenko.
        !             5:  Permission is granted to any individual or institution to use, copy, or
        !             6:  redistribute this software so long as all of the original files are included
        !             7:  unmodified, that it is not sold for profit, and that this copyright notice
        !             8:  is retained.
        !             9: 
        !            10: */
        !            11: 
        !            12: /*
        !            13:  *  fileio.c by Mark Adler.
        !            14:  */
        !            15: 
        !            16: #include "zip.h"
        !            17: 
        !            18: #include <time.h>
        !            19: 
        !            20: #ifdef WIN32
        !            21: #  include <sys/utime.h>
        !            22: #  include <windows.h> /* for findfirst/findnext */
        !            23: #endif
        !            24: 
        !            25: #ifdef MACOS
        !            26: #  define EXDEV 1
        !            27: #endif
        !            28: 
        !            29: #ifdef OSF
        !            30: #  define EXDEV 18    /* avoid a bug in the DEC OSF/1 header files. */
        !            31: #else
        !            32: #  include <errno.h>
        !            33: #endif
        !            34: 
        !            35: #ifdef MINIX
        !            36: #  ifdef S_IWRITE
        !            37: #    undef S_IWRITE
        !            38: #  endif /* S_IWRITE */
        !            39: #  define S_IWRITE S_IWUSR
        !            40: #endif /* S_IWUSR */
        !            41: 
        !            42: #ifdef ATARI_ST
        !            43: #  undef MSDOS
        !            44: #endif
        !            45: 
        !            46: #ifdef MSDOS
        !            47: #  include <io.h>
        !            48: #  if (defined(__TURBOC__) || defined(__GO32__))
        !            49: #    include <dir.h>
        !            50: #  else /* !__TURBOC__ */
        !            51: #    if !defined(__EMX__) && !defined(__WATCOMC__)
        !            52: #      include <direct.h>
        !            53: #    endif
        !            54: #  endif /* ?__TURBOC__ */
        !            55: #  define link rename
        !            56: #  ifdef OS2
        !            57: #    define MATCH shmatch
        !            58: #  else /* !OS2 */
        !            59: #    define MATCH dosmatch
        !            60: #  endif /* ?OS2 */
        !            61: #else /* !MSDOS */
        !            62:    extern int errno;    /* error number from system functions */
        !            63: #  ifdef VMS
        !            64: #    define RMDIR
        !            65: #    define link rename
        !            66: #    include "VMSmunch.h"
        !            67: #  endif /* VMS */
        !            68: #  ifdef MACOS
        !            69: #    define link rename
        !            70: #    define mktemp tmpnam
        !            71: #  endif
        !            72: #  define MATCH shmatch
        !            73: #endif /* ?MSDOS */
        !            74: 
        !            75: #ifdef ATARI_ST
        !            76: #  define MSDOS 1
        !            77: #endif
        !            78: 
        !            79: #ifdef UTS
        !            80: #  define RMDIR
        !            81: #endif /* UTS */
        !            82: 
        !            83: 
        !            84: /* Extra malloc() space in names for cutpath() */
        !            85: #ifdef VMS
        !            86: #  define PAD 3         /* may have to change .FOO] to ]FOO.DIR */
        !            87: #else /* !VMS */
        !            88: #  define PAD 0
        !            89: #endif /* ?VMS */
        !            90: 
        !            91: 
        !            92: /* For now, assume DIRENT implies System V implies TERMIO */
        !            93: #if defined(DIRENT) && !defined(MINIX) && !defined(TERMIO)
        !            94: #  define TERMIO
        !            95: #endif
        !            96: 
        !            97: 
        !            98: #ifdef CRYPT
        !            99: #  ifdef MSVMS
        !           100: #    ifdef MSDOS
        !           101: #      ifdef __EMX__
        !           102: #        define getch() _read_kbd(0, 1, 0)
        !           103: #      else
        !           104: #        ifdef __GO32__
        !           105: #          include <pc.h>
        !           106: #          define getch() getkey()
        !           107: #        else
        !           108: #          include <conio.h>
        !           109: #        endif
        !           110: #      endif
        !           111: #    else /* !MSDOS */
        !           112: #      define getch() getc(stderr)
        !           113: #      define echoff(f) echo(0)   /* for echo control */
        !           114: #      define echon()   echo(1)
        !           115: #      include <iodef.h>
        !           116: #      include <ttdef.h>
        !           117: #      if !defined(SS$_NORMAL)
        !           118: #        define SS$_NORMAL 1   /* only thing we need from <ssdef.h> */
        !           119: #      endif
        !           120: #    endif /* ?MSDOS */
        !           121: #  else /* !MSVMS */
        !           122: #    ifdef TERMIO       /* Amdahl, Cray, all SysV? */
        !           123: #      ifdef CONVEX
        !           124: #        include <sys/termios.h>
        !           125: #        include <sgtty.h>
        !           126: #        define O_BINARY 0
        !           127: #      else /* !CONVEX */
        !           128: #        ifdef LINUX 
        !           129: #          include <termios.h>
        !           130: #        else /* !LINUX */
        !           131: #          include <termio.h>
        !           132: #        endif /* ?LINUX */
        !           133: #        define sgttyb termio
        !           134: #        define sg_flags c_lflag
        !           135:          int ioctl OF((int, int, voidp *));
        !           136: #      endif /* ?CONVEX */
        !           137: #      define GTTY(f,s) ioctl(f,TCGETA,s)
        !           138: #      define STTY(f,s) ioctl(f,TCSETAW,s)
        !           139: #    else /* !TERMIO */
        !           140: #      ifndef MINIX
        !           141: #        include <sys/ioctl.h>
        !           142: #      endif /* !MINIX */
        !           143: #      include <sgtty.h>
        !           144:        int gtty OF((int, struct sgttyb *));
        !           145:        int stty OF((int, struct sgttyb *));
        !           146: #      define GTTY gtty
        !           147: #      define STTY stty
        !           148: #    endif /* ?TERMIO */
        !           149:      int isatty OF((int));
        !           150:      char *ttyname OF((int));
        !           151:      int open OF((char *, int, ...));
        !           152:      int close OF((int));
        !           153:      int read OF((int, voidp *, int));
        !           154: #  endif /* ?MSVMS */
        !           155: #endif /* ?CRYPT */
        !           156: 
        !           157: #ifdef VMS
        !           158: #  include <descrip.h>
        !           159: #  include <rms.h>
        !           160: #endif
        !           161: 
        !           162: /* For directory access. (This is getting rather messy. Cleanup
        !           163:  * scheduled for version 17.9.)
        !           164:  */
        !           165: #ifndef UTIL
        !           166: 
        !           167: #ifdef SYSV                     /* use readdir()  */
        !           168: #  include <dirent.h>
        !           169: #  define dstrm DIR
        !           170: #  define direct dirent
        !           171: #else
        !           172: 
        !           173: #ifdef DIRENT                   /* use getdents() */
        !           174: #  if defined(MINIX) || defined(OSF)
        !           175: #    include <dirent.h>
        !           176: #  else /* !MINIX */
        !           177: #    include <sys/dirent.h>
        !           178: #  endif /* ?MINIX */
        !           179: #  define direct dirent
        !           180: #  ifdef MINIX
        !           181:      int getdents OF((int, char *, unsigned));
        !           182: #  else /* !MINIX */
        !           183:      int getdents OF((int, char *, int));
        !           184: #  endif /* ?MINIX */
        !           185: #  define DBSZ 4096     /* This has to be bigger than a directory block */
        !           186:    typedef struct {     /* directory stream buffer */
        !           187:      int f;             /* file descriptor for the directory "file" */
        !           188:      char *p;           /* pointer to next entry in buffer */
        !           189:      char *q;           /* pointer after end of buffer contents */
        !           190:      char b[DBSZ];              /* buffer */
        !           191:    } dstrm;
        !           192: 
        !           193: #else /* !DIRENT */             /* use opendir(), etc. */
        !           194: #  if defined(CONVEX) || defined(ultrix)
        !           195: #    include <dirent.h>
        !           196: #    ifdef direct
        !           197: #      undef direct /* ultrix 4.2, at least if !__POSIX */
        !           198: #    endif
        !           199: #    define direct dirent
        !           200: #  endif /* CONVEX || ultrix */
        !           201: #  ifdef NDIR
        !           202: #    include "ndir.h"           /* for HPUX */
        !           203: #  else /* !NDIR */
        !           204: #    ifdef MSDOS
        !           205: #     ifdef OS2
        !           206: #      include "os2zip.h"
        !           207: #     else /* !OS2 */
        !           208: #      ifndef ATARI_ST
        !           209: #        include <dos.h>
        !           210: #      endif
        !           211: #      if (defined(__TURBOC__) || defined(__GO32__))
        !           212: #        define FATTR           FA_HIDDEN+FA_SYSTEM+FA_DIREC
        !           213: #        define FFIRST(n,d)     findfirst(n,(struct ffblk *)d,FATTR)
        !           214: #        define FNEXT(d)        findnext((struct ffblk *)d)
        !           215: #      else /* !__TURBOC__ */
        !           216: #        define FATTR           _A_HIDDEN+_A_SYSTEM+_A_SUBDIR
        !           217: #        define FFIRST(n,d)     _dos_findfirst(n,FATTR,(struct find_t *)d)
        !           218: #        define FNEXT(d)        _dos_findnext((struct find_t *)d)
        !           219: #      endif /* ?__TURBOC__ */
        !           220:        typedef struct direct {
        !           221:          char d_reserved[30];
        !           222:          char d_name[13];
        !           223:         int d_first;
        !           224: #ifdef WIN32
        !           225:         HANDLE d_hFindFile;
        !           226: #endif
        !           227:        } DIR;
        !           228: #     endif /* ?OS2 */
        !           229: #    else /* !MSDOS */
        !           230: #      ifdef VMS
        !           231: #        include <ssdef.h>
        !           232:          typedef struct direct {
        !           233:              int d_wild;                /* flag for wildcard vs. non-wild */
        !           234:              struct FAB fab;
        !           235:              struct NAM nam;
        !           236:              char d_qualwildname[NAM$C_MAXRSS + 1];
        !           237:              char d_name[NAM$C_MAXRSS + 1];
        !           238:          } DIR;
        !           239: #      else /* !VMS */
        !           240: #        ifdef MACOS
        !           241:            typedef struct direct {
        !           242:              int d_wild;                /* flag for wildcard vs. non-wild */
        !           243:              char *d_name;
        !           244:           } DIR;
        !           245: #        endif
        !           246: #        ifdef M_XENIX
        !           247: #          include <sys/ndir.h>
        !           248: #        else /* !M_XENIX */
        !           249: #          include <sys/dir.h>
        !           250: #        endif /* ?M_XENIX */
        !           251: #        ifdef NODIR                    /* for AT&T 3B1 */
        !           252: #          define dirent direct
        !           253:            typedef FILE DIR;
        !           254: #          define dstrm DIR
        !           255: #        endif /* NODIR */
        !           256: #      endif /* ?VMS */
        !           257: #    endif /* ?MSDOS */
        !           258: #  endif /* ?NDIR */
        !           259: #  define dstrm DIR
        !           260: #  ifndef NODIR
        !           261:      DIR *opendir OF((char *));
        !           262: #  endif /* !NODIR */
        !           263: #  ifndef CONVEX
        !           264:      struct direct *readdir OF((DIR *));
        !           265: #  endif /* !CONVEX */
        !           266: #endif /* ?DIRENT */
        !           267: #endif /* ?SYSV */
        !           268: #endif /* !UTIL */
        !           269: 
        !           270: 
        !           271: /* Library functions not in (most) header files */
        !           272: 
        !           273: #if defined(__IBMC__) || defined(__WATCOMC__)
        !           274: #  define NO_MKTEMP
        !           275: #endif
        !           276: char *mktemp OF((char *));
        !           277: 
        !           278: #ifdef __GO32__
        !           279:   char *strlwr OF((char *));
        !           280: #else
        !           281:   int link OF((char *, char *));
        !           282:   int unlink OF((char *));
        !           283: # if defined(MSDOS)
        !           284:    int chmod OF((char *, int));
        !           285:    /* For many targets, chmod is already defined by sys/stat.h, and second
        !           286:     * parameter is an unsigned long.
        !           287:     */
        !           288: # endif
        !           289: #endif
        !           290: 
        !           291: 
        !           292: #ifndef UTIL    /* the companion #endif is a bit of ways down ... */
        !           293: 
        !           294: #ifndef __TURBOC__
        !           295:    int utime OF((char *, time_t *));
        !           296: #endif /* !__TURBOC__ */
        !           297: #ifndef MSDOS
        !           298:    int open OF((char *, int, ...));
        !           299:    int close OF((int));
        !           300: #  ifndef RMDIR
        !           301:      int rmdir OF((char *));
        !           302: #  endif /* !RMDIR */
        !           303: #endif /* !MSDOS */
        !           304: 
        !           305: 
        !           306: /* Local globals (kinda like "military intelligence" or "broadcast quality") */
        !           307: local int exflag = 0;           /* Exclude flag */
        !           308: 
        !           309: #ifdef VMS
        !           310:   typedef int statime;
        !           311: #else /* !VMS */
        !           312:   typedef time_t statime;
        !           313: #endif /* ?VMS */
        !           314: 
        !           315: /* Local functions */
        !           316: #ifdef PROTO
        !           317: #  ifdef VMS
        !           318:      local void vms_wild(char *, dstrm *);
        !           319: #  endif /* VMS */
        !           320: #  ifdef DIRENT
        !           321:      local dstrm *opend(char *);
        !           322:      local void closed(dstrm *);
        !           323: #  endif /* DIRENT */
        !           324:    local char *readd(dstrm *);
        !           325:    local int fqcmp(voidp *, voidp *);
        !           326:    local int fqcmpz(voidp *, voidp *);
        !           327:    local char *last(char *);
        !           328:    local char *msname(char *);
        !           329: #  ifdef VMS
        !           330:      local char *strlower(char *);
        !           331:      local char *strupper(char *);
        !           332: #  endif /* VMS */
        !           333:    local char *ex2in(char *, int *);
        !           334:    local int newname(char *);
        !           335:    local void inctime(struct tm *);
        !           336:    local ulg unix2dostime(statime *);
        !           337: #  if !defined(__TURBOC__) && !defined(OS2) && !defined(__GO32__)
        !           338:      local int cmptime(struct tm *, struct tm *);
        !           339:      local time_t invlocal(struct tm *);
        !           340: #  endif /* !__TURBOC__ */
        !           341: #endif /* PROTO */
        !           342: 
        !           343: 
        !           344: #if defined(MSDOS) && !defined(OS2)
        !           345: dstrm *opendir(n)
        !           346: char *n;                /* directory to open */
        !           347: /* Start searching for files in the MSDOS directory n */
        !           348: {
        !           349:   dstrm *d;             /* malloc'd return value */
        !           350:   char *p;              /* malloc'd temporary string */
        !           351: 
        !           352:   if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL ||
        !           353:       (p = malloc(strlen(n) + 5)) == NULL)
        !           354:     return NULL;
        !           355:   strcat(strcpy(p, n), "/*.*");
        !           356: #ifdef WIN32
        !           357:   {
        !           358:   WIN32_FIND_DATA fd;
        !           359:   DWORD dwAttr;
        !           360:   BOOL bAttr;
        !           361: 
        !           362:   if ((HANDLE)0xFFFFFFFF == (d->d_hFindFile = FindFirstFile(p, &fd)))
        !           363:     {
        !           364:     free((voidp *)p);
        !           365:     return NULL;
        !           366:     }
        !           367:   else
        !           368:     strcpy(d->d_name, fd.cFileName);
        !           369:   if (-1 != (dwAttr = GetFileAttributes(fd.cFileName)))
        !           370:     {
        !           371:     bAttr = FALSE;
        !           372:     if (FILE_ATTRIBUTE_SYSTEM == (dwAttr & FILE_ATTRIBUTE_SYSTEM))
        !           373:        bAttr = TRUE;
        !           374:     if (FILE_ATTRIBUTE_HIDDEN == (dwAttr & FILE_ATTRIBUTE_HIDDEN))
        !           375:        bAttr = TRUE;
        !           376:     if (FILE_ATTRIBUTE_DIRECTORY == (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
        !           377:        bAttr = TRUE;
        !           378:     if (!bAttr)
        !           379:        {
        !           380:        free ((voidp *)p);
        !           381:        free ((void *) d);
        !           382:        return NULL;
        !           383:        }
        !           384:     }
        !           385: 
        !           386:   }
        !           387: #else
        !           388:   if (FFIRST(p, d))
        !           389:   {
        !           390:     free((voidp *)p);
        !           391:     return NULL;
        !           392:   }
        !           393:   free((voidp *)p);
        !           394: #endif
        !           395:   d->d_first = 1;
        !           396:   return d;
        !           397: }
        !           398: 
        !           399: struct direct *readdir(d)
        !           400: dstrm *d;               /* directory stream to read from */
        !           401: /* Return pointer to first or next directory entry, or NULL if end. */
        !           402: {
        !           403:   if (d->d_first)
        !           404:     d->d_first = 0;
        !           405:   else
        !           406: #ifdef WIN32
        !           407:     {
        !           408:     WIN32_FIND_DATA fd;
        !           409: 
        !           410:     if (!FindNextFile(d->d_hFindFile, &fd))
        !           411:        return NULL;
        !           412:     else
        !           413:        strcpy(d->d_name, fd.cFileName);
        !           414:     }
        !           415: #else /* !WIN32 */
        !           416:     if (FNEXT(d))
        !           417:       return NULL;
        !           418: #endif
        !           419:   return (struct direct *)d;
        !           420: }
        !           421: #  define closedir free
        !           422: 
        !           423: #endif /* MSDOS && !OS2 */
        !           424: 
        !           425: 
        !           426: #ifdef VMS
        !           427: 
        !           428: /*---------------------------------------------------------------------------
        !           429: 
        !           430:     _vms_findfirst() and _vms_findnext(), based on public-domain DECUS C
        !           431:     fwild() and fnext() routines (originally written by Martin Minow, poss-
        !           432:     ibly modified by Jerry Leichter for bintnxvms.c), were written by Greg
        !           433:     Roelofs and are still in the public domain.  Routines approximate the
        !           434:     behavior of MS-DOS (MSC and Turbo C) findfirst and findnext functions.
        !           435: 
        !           436:   ---------------------------------------------------------------------------*/
        !           437: local void vms_wild(p, d)
        !           438: char *p;
        !           439: dstrm *d;
        !           440: {
        !           441:   /*
        !           442:    * Do wildcard setup
        !           443:    */
        !           444:   /* set up the FAB and NAM blocks. */
        !           445:   d->fab = cc$rms_fab;             /* initialize fab */
        !           446:   d->nam = cc$rms_nam;             /* initialize nam */
        !           447: 
        !           448:   d->fab.fab$l_nam = &d->nam;           /* fab -> nam */
        !           449:   d->fab.fab$l_fna = p;                 /* argument wild name */
        !           450:   d->fab.fab$b_fns = strlen(p);         /* length */
        !           451: 
        !           452:   d->nam.nam$l_esa = d->d_qualwildname; /* qualified wild name */
        !           453:   d->nam.nam$b_ess = NAM$C_MAXRSS;      /* max length */
        !           454:   d->nam.nam$l_rsa = d->d_name;         /* matching file name */
        !           455:   d->nam.nam$b_rss = NAM$C_MAXRSS;      /* max length */
        !           456: 
        !           457:   /* parse the file name */
        !           458:   if (sys$parse(&d->fab) != RMS$_NORMAL)
        !           459:     return;
        !           460:   /* Does this replace d->fab.fab$l_fna with a new string in its own space?
        !           461:      I sure hope so, since p is free'ed before this routine returns. */
        !           462: 
        !           463:   /* have qualified wild name (i.e., disk:[dir.subdir]*.*); null-terminate
        !           464:    * and set wild-flag */
        !           465:   d->d_qualwildname[d->nam.nam$b_esl] = '\0';
        !           466:   d->d_wild = (d->nam.nam$l_fnb & NAM$M_WILDCARD)? 1 : 0;   /* not used... */
        !           467: #ifdef DEBUG
        !           468:   printf("  incoming wildname:  %s\n", p);
        !           469:   printf("  qualified wildname:  %s\n", d->d_qualwildname);
        !           470: #endif /* DEBUG */
        !           471: }
        !           472: 
        !           473: dstrm *opendir(n)
        !           474: char *n;                /* directory to open */
        !           475: /* Start searching for files in the VMS directory n */
        !           476: {
        !           477:   char *c;              /* scans VMS path */
        !           478:   dstrm *d;             /* malloc'd return value */
        !           479:   int m;                /* length of name */
        !           480:   char *p;              /* malloc'd temporary string */
        !           481: 
        !           482:   if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL ||
        !           483:       (p = malloc((m = strlen(n)) + 4)) == NULL)
        !           484:     return NULL;
        !           485:   /* Directory may be in form "[DIR.SUB1.SUB2]" or "[DIR.SUB1]SUB2.DIR;1".
        !           486:      If latter, convert to former. */
        !           487:   if (m > 0  &&  *(c = strcpy(p,n)+m-1) != ']')
        !           488:   {
        !           489:     while (--c > p  &&  *c != ';')
        !           490:       ;
        !           491:     if (c-p < 5  ||  strncmp(c-4, ".DIR", 4))
        !           492:     {
        !           493:       free((voidp *)d);  free((voidp *)p);
        !           494:       return NULL;
        !           495:     }
        !           496:     c -= 3;
        !           497:     *c-- = '\0';        /* terminate at "DIR;#" */
        !           498:     *c = ']';           /* "." --> "]" */
        !           499:     while (c > p  &&  *--c != ']')
        !           500:       ;
        !           501:     *c = '.';           /* "]" --> "." */
        !           502:   }
        !           503:   strcat(p, "*.*");
        !           504:   vms_wild(p, d);       /* set up wildcard */
        !           505:   free((voidp *)p);
        !           506:   return d;
        !           507: }
        !           508: 
        !           509: struct direct *readdir(d)
        !           510: dstrm *d;               /* directory stream to read from */
        !           511: /* Return pointer to first or next directory entry, or NULL if end. */
        !           512: {
        !           513:   int r;                /* return code */
        !           514: 
        !           515:   do {
        !           516:     d->fab.fab$w_ifi = 0;       /* internal file index:  what does this do? */
        !           517: 
        !           518:     /* get next match to possible wildcard */
        !           519:     if ((r = sys$search(&d->fab)) == RMS$_NORMAL)
        !           520:     {
        !           521:         d->d_name[d->nam.nam$b_rsl] = '\0';   /* null terminate */
        !           522:         return (struct direct *)d;   /* OK */
        !           523:     }
        !           524:   } while (r == RMS$_PRV);
        !           525:   return NULL;
        !           526: }
        !           527: #  define closedir free
        !           528: #endif /* VMS */
        !           529: 
        !           530: 
        !           531: #ifdef NODIR                    /* for AT&T 3B1 */
        !           532: /*
        !           533: **  Apparently originally by Rich Salz.
        !           534: **  Cleaned up and modified by James W. Birdsall.
        !           535: */
        !           536: 
        !           537: #  define opendir(path) fopen(path, "r")
        !           538:  
        !           539: struct direct *readdir(dirp)
        !           540: DIR *dirp;
        !           541: {
        !           542:   static struct direct entry;
        !           543: 
        !           544:   if (dirp == NULL) 
        !           545:     return NULL;
        !           546:   for (;;)
        !           547:     if (fread (&entry, sizeof (struct direct), 1, dirp) == 0) 
        !           548:       return NULL;
        !           549:     else if (entry.d_ino) 
        !           550:       return (&entry);
        !           551: } /* end of readdir() */
        !           552: 
        !           553: #  define closedir(dirp) fclose(dirp)
        !           554: #endif /* NODIR */
        !           555: 
        !           556: 
        !           557: #ifdef DIRENT
        !           558: local dstrm *opend(n)
        !           559: char *n;                /* directory name to open */
        !           560: /* Open the directory *n, returning a pointer to an allocated dstrm, or
        !           561:    NULL if error. */
        !           562: {
        !           563:   dstrm *d;             /* pointer to malloc'ed directory stream */
        !           564: 
        !           565:   if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL)
        !           566:     return NULL;
        !           567:   if ((d->f = open(n, 0, 0)) < 0)               /* open directory */
        !           568:     return NULL;
        !           569:   d->p = d->q = d->b;                           /* buffer is empty */
        !           570:   return d;
        !           571: }
        !           572: #else /* !DIRENT */
        !           573: #  define opend opendir                         /* just use opendir() */
        !           574: #endif /* ?DIRENT */
        !           575: 
        !           576: 
        !           577: local char *readd(d)
        !           578: dstrm *d;               /* directory stream to read from */
        !           579: /* Return a pointer to the next name in the directory stream d, or NULL if
        !           580:    no more entries or an error occurs. */
        !           581: {
        !           582:   struct direct *e;     /* directory entry read */
        !           583: 
        !           584: #ifdef DIRENT
        !           585:   int n;                /* number of entries read by getdents */
        !           586: 
        !           587:   if (d->p >= d->q)                             /* if empty, fill buffer */
        !           588:     if ((n = getdents(d->f, d->b, DBSZ)) <= 0)
        !           589:       return NULL;
        !           590:     else
        !           591:       d->q = n + (d->p = d->b);
        !           592:   e = (struct direct *)(d->p);                  /* point to entry */
        !           593:   d->p += ((struct direct *)(d->p))->d_reclen;  /* advance */
        !           594:   return e->d_name;                             /* return name */
        !           595: #else /* !DIRENT */
        !           596:   return (e = readdir(d)) == NULL ? (char *)NULL : e->d_name;
        !           597: #endif /* ?DIRENT */
        !           598: }
        !           599: 
        !           600: 
        !           601: #ifdef DIRENT
        !           602: local void closed(d)
        !           603: dstrm *d;               /* directory stream to close */
        !           604: /* Close the directory stream */
        !           605: {
        !           606:   close(d->f);
        !           607:   free((voidp *)d);
        !           608: }
        !           609: #else /* !DIRENT */
        !           610: #  define closed closedir
        !           611: #endif /* ?DIRENT */
        !           612: 
        !           613: 
        !           614: #ifdef MSDOS
        !           615: 
        !           616: int wild(w)
        !           617: char *w;                /* path/pattern to match */
        !           618: /* If not in exclude mode, expand the pattern based on the contents of the
        !           619:    file system.  Return an error code in the ZE_ class. */
        !           620: {
        !           621:   char *a;              /* alloc'ed space for name */
        !           622:   dstrm *d;             /* stream for reading directory */
        !           623:   char *e;              /* name found in directory */
        !           624:   int f;                /* true if there was a match */
        !           625:   char *n;              /* constructed name from directory */
        !           626:   char *p;              /* path */
        !           627:   char *q;              /* name */
        !           628:   int r;                /* temporary variable */
        !           629:   char v[5];            /* space for device current directory */
        !           630: 
        !           631:   /* Allocate and copy pattern */
        !           632:   if ((p = a = malloc(strlen(w) + 1)) == NULL)
        !           633:     return ZE_MEM;
        !           634:   strcpy(p, w);
        !           635: 
        !           636:   /* Normalize pattern to upper case, path delimiter as '/'. */
        !           637: #if defined(FORCE_UPPER)
        !           638: #ifndef OS2
        !           639:   strupr(p);                            /* convert to upper case */
        !           640: #else /* OS2 */
        !           641:   if (IsFileSystemFAT(p)) strupr(p);
        !           642: #endif /* !OS2 */
        !           643: #endif
        !           644:   for (q = p; *q; q++)                  /* use / consistently */
        !           645:     if (*q == '\\')
        !           646:       *q = '/';
        !           647: 
        !           648:   /* If excluding, don't bother with file system */
        !           649:   if (exflag)
        !           650:   {
        !           651:     r = procname(p);
        !           652:     free((voidp *)a);
        !           653:     return r;
        !           654:   }
        !           655: 
        !           656:   /* Only name can have special matching characters */
        !           657:   if ((q = isshexp(p)) != NULL &&
        !           658:       (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))
        !           659:   {
        !           660:     free((voidp *)a);
        !           661:     return ZE_PARMS;
        !           662:   }
        !           663: 
        !           664:   /* Separate path and name into p and q */
        !           665:   if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))
        !           666:   {
        !           667:     *q++ = 0;                           /* path/name -> path, name */
        !           668:     if (*p == 0)                        /* path is just / */
        !           669:       p = strcpy(v, "/.");
        !           670:   }
        !           671:   else if ((q = strrchr(p, ':')) != NULL)
        !           672:   {                                     /* has device and no or root path */
        !           673:     *q++ = 0;
        !           674:     p = strcat(strcpy(v, p), ":");      /* copy device as path */
        !           675:     if (*q == '/')                      /* -> device:/., name */
        !           676:     {
        !           677:       strcat(p, "/");
        !           678:       q++;
        !           679:     }
        !           680:     strcat(p, ".");
        !           681:   }
        !           682:   else                                  /* no path or device */
        !           683:   {
        !           684:     q = p;
        !           685:     p = strcpy(v, ".");
        !           686:   }
        !           687: 
        !           688:   /* Search that level for matching names */
        !           689:   if ((d = opend(p)) == NULL)
        !           690:   {
        !           691:     free((voidp *)a);
        !           692:     return ZE_MISS;
        !           693:   }
        !           694:   if ((r = strlen(p)) > 1 &&
        !           695:       (strcmp(p + r - 2, ":.") == 0 || strcmp(p + r - 2, "/.") == 0))
        !           696:     *(p + r - 1) = 0;
        !           697:   f = 0;
        !           698:   while ((e = readd(d)) != NULL)
        !           699:     if (strcmp(e, ".") && strcmp(e, "..") && MATCH(q, e))
        !           700:     {
        !           701:       f = 1;
        !           702:       if (strcmp(p, ".") == 0)                  /* path is . */
        !           703:         procname(e);                            /* name is name */
        !           704:       else
        !           705:       {
        !           706:         if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)
        !           707:         {
        !           708:           free((voidp *)a);
        !           709:           return ZE_MEM;
        !           710:         }
        !           711:         n = strcpy(n, p);
        !           712:         if (n[r = strlen(n) - 1] != '/' && n[r] != ':')
        !           713:           strcat(n, "/");
        !           714:         r = procname(strcat(n, e));             /* name is path/name */
        !           715:         free((voidp *)n);
        !           716:         if (r)
        !           717:         {
        !           718:           free((voidp *)a);
        !           719:           return r;
        !           720:         }
        !           721:       }
        !           722:     }
        !           723:   closed(d);
        !           724: 
        !           725:   /* Done */
        !           726:   free((voidp *)a);
        !           727:   return f ? ZE_OK : ZE_MISS;
        !           728: }
        !           729: 
        !           730: #endif /* MSDOS */
        !           731: 
        !           732: 
        !           733: #ifdef VMS
        !           734: int wild(p)
        !           735: char *p;                /* path/pattern to match */
        !           736: /* Expand the pattern based on the contents of the file system.  Return an
        !           737:    error code in the ZE_ class. */
        !           738: {
        !           739:   dstrm *d;             /* stream for reading directory */
        !           740:   char *e;              /* name found in directory */
        !           741:   int f;                /* true if there was a match */
        !           742: 
        !           743:   /* Search given pattern for matching names */
        !           744:   if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL)
        !           745:     return ZE_MEM;
        !           746:   vms_wild(p, d);       /* pattern may be more than just directory name */
        !           747:   f = 0;
        !           748:   while ((e = readd(d)) != NULL)        /* "dosmatch" is already built in */
        !           749:     if (procname(e) == ZE_OK)
        !           750:       f = 1;
        !           751:   closed(d);
        !           752: 
        !           753:   /* Done */
        !           754:   return f ? ZE_OK : ZE_MISS;
        !           755: }
        !           756: #endif /* VMS */
        !           757: 
        !           758: 
        !           759: char *getnam(n)
        !           760: char *n;                /* where to put name (must have >=FNMAX+1 bytes) */
        !           761: /* Read a space, \n, \r, or \t delimited name from stdin into n, and return
        !           762:    n.  If EOF, then return NULL.  Also, if the name read is too big, return
        !           763:    NULL. */
        !           764: {
        !           765:   int c;                /* last character read */
        !           766:   char *p;              /* pointer into name area */
        !           767: 
        !           768:   p = n;
        !           769:   while ((c = getchar()) == ' ' || c == '\n' || c == '\r' || c == '\t')
        !           770:     ;
        !           771:   if (c == EOF)
        !           772:     return NULL;
        !           773:   do {
        !           774:     if (p - n >= FNMAX)
        !           775:       return NULL;
        !           776:     *p++ = (char)c;
        !           777:     c = getchar();
        !           778:   } while (c != EOF && c != ' ' && c != '\n' && c != '\r' && c != '\t');
        !           779:   *p = 0;
        !           780:   return n;
        !           781: }
        !           782: 
        !           783: 
        !           784: struct flist far *fexpel(f)
        !           785: struct flist far *f;    /* entry to delete */
        !           786: /* Delete the entry *f in the doubly-linked found list.  Return pointer to
        !           787:    next entry to allow stepping through list. */
        !           788: {
        !           789:   struct flist far *t;  /* temporary variable */
        !           790: 
        !           791:   t = f->nxt;
        !           792:   *(f->lst) = t;                        /* point last to next, */
        !           793:   if (t != NULL)
        !           794:     t->lst = f->lst;                    /* and next to last */
        !           795:   if (f->name != NULL)                  /* free memory used */
        !           796:     free((voidp *)(f->name));
        !           797:   if (f->zname != NULL)
        !           798:     free((voidp *)(f->zname));
        !           799:   farfree((voidp far *)f);
        !           800:   fcount--;                             /* decrement count */
        !           801:   return t;                             /* return pointer to next */
        !           802: }
        !           803: 
        !           804: 
        !           805: local int fqcmp(a, b)
        !           806: voidp *a, *b;           /* pointers to pointers to found entries */
        !           807: /* Used by qsort() to compare entries in the found list by name. */
        !           808: {
        !           809:   return strcmp((*(struct flist far **)a)->name,
        !           810:                 (*(struct flist far **)b)->name);
        !           811: }
        !           812: 
        !           813: 
        !           814: local int fqcmpz(a, b)
        !           815: voidp *a, *b;           /* pointers to pointers to found entries */
        !           816: /* Used by qsort() to compare entries in the found list by zname. */
        !           817: {
        !           818:   return strcmp((*(struct flist far **)a)->zname,
        !           819:                 (*(struct flist far **)b)->zname);
        !           820: }
        !           821: 
        !           822: 
        !           823: local char *last(p)
        !           824: char *p;                /* sequence of / delimited path components */
        !           825: /* Return a pointer to the start of the last path component. */
        !           826: {
        !           827:   char *t;              /* temporary variable */
        !           828: 
        !           829: #ifdef VMS
        !           830:   if ((t = strrchr(p, ']')) != NULL)
        !           831: #else /* !VMS */
        !           832:   if ((t = strrchr(p, '/')) != NULL)
        !           833: #endif /* ?VMS */
        !           834:     return t + 1;
        !           835:   else
        !           836:     return p;
        !           837: }
        !           838: 
        !           839: 
        !           840: local char *msname(n)
        !           841: char *n;
        !           842: /* Reduce all path components to MSDOS upper case 8.3 style names.  Probably
        !           843:    should also check for invalid characters, but I don't know which ones
        !           844:    those are. */
        !           845: {
        !           846:   int c;                /* current character */
        !           847:   int f;                /* characters in current component */
        !           848:   char *p;              /* source pointer */
        !           849:   char *q;              /* destination pointer */
        !           850: 
        !           851:   p = q = n;
        !           852:   f = 0;
        !           853:   while ((c = *p++) != 0)
        !           854:     if (c == '/')
        !           855:     {
        !           856:       *q++ = (char)c;
        !           857:       f = 0;                            /* new component */
        !           858:     }
        !           859:     else if (c == '.')
        !           860:       if (f < 9)
        !           861:       {
        !           862:         *q++ = (char)c;
        !           863:         f = 9;                          /* now in file type */
        !           864:       }
        !           865:       else
        !           866:         f = 12;                         /* now just excess characters */
        !           867:     else
        !           868:       if (f < 12 && f != 8)
        !           869:       {
        !           870:         *q++ = (char)(to_up(c));
        !           871:         f++;                            /* do until end of name or type */
        !           872:       }
        !           873:   *q = 0;
        !           874:   return n;
        !           875: }
        !           876: 
        !           877: 
        !           878: #ifdef VMS
        !           879: local char *strlower(s)
        !           880: char *s;                /* string to convert */
        !           881: /* Convert all uppercase letters to lowercase in string s */
        !           882: {
        !           883:   char *p;              /* scans string */
        !           884: 
        !           885:   for (p = s; *p; p++)
        !           886:     if (*p >= 'A' && *p <= 'Z')
        !           887:       *p += 'a' - 'A';
        !           888:   return s;
        !           889: }
        !           890: 
        !           891: local char *strupper(s)
        !           892: char *s;                /* string to convert */
        !           893: /* Convert all lowercase letters to uppercase in string s */
        !           894: {
        !           895:   char *p;              /* scans string */
        !           896: 
        !           897:   for (p = s; *p; p++)
        !           898:     if (*p >= 'a' && *p <= 'z')
        !           899:       *p -= 'a' - 'A';
        !           900:   return s;
        !           901: }
        !           902: #endif /* VMS */
        !           903: 
        !           904: local char *ex2in(x, pdosflag)
        !           905: char *x;                /* external file name */
        !           906: int *pdosflag;          /* output: force MSDOS file attributes? */
        !           907: /* Convert the external file name to a zip file name, returning the malloc'ed
        !           908:    string or NULL if not enough memory. */
        !           909: {
        !           910:   char *n;              /* internal file name (malloc'ed) */
        !           911:   char *t;              /* shortened name */
        !           912:   int dosflag;
        !           913: 
        !           914: #ifdef OS2
        !           915:   dosflag = dosify || IsFileSystemFAT(x);
        !           916:   if ( !dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL )
        !           917:   {
        !           918:     x = t;
        !           919:     dosflag = 0;
        !           920:   }
        !           921: #else
        !           922: # ifdef MSDOS
        !           923:   dosflag = 1;
        !           924: # else /* !MSDOS */
        !           925:   dosflag = dosify; /* default for non-DOS and non-OS/2 */
        !           926: # endif /* MSDOS */
        !           927: #endif /* OS2 */
        !           928: 
        !           929:   /* Find starting point in name before doing malloc */
        !           930: #ifdef MSDOS                            /* msdos */
        !           931:   t = *x && *(x + 1) == ':' ? x + 2 : x;
        !           932:   while (*t == '/' || *t == '\\')
        !           933:     t++;
        !           934: #else /* !MSDOS */
        !           935: #  ifdef VMS                            /* vms */
        !           936:   t = x;
        !           937:   if ((n = strrchr(t, ':')) != NULL)
        !           938:     t = n + 1;
        !           939:   if (*t == '[' && (n = strrchr(t, ']')) != NULL)
        !           940:     if ((x = strchr(t, '.')) != NULL && x < n)
        !           941:       t = x + 1;
        !           942:     else
        !           943:       t = n + 1;
        !           944: #  else /* !VMS */                      /* unix */
        !           945:   for (t = x; *t == '/'; t++)
        !           946:     ;
        !           947: #  endif /* ?VMS */
        !           948: #endif /* ?MSDOS */
        !           949: 
        !           950:   /* Make changes, if any, to the copied name (leave original intact) */
        !           951: #ifdef MSDOS
        !           952:   for (n = t; *n; n++)
        !           953:     if (*n == '\\')
        !           954:       *n = '/';
        !           955: #endif /* MSDOS */
        !           956: 
        !           957:   if (!pathput)
        !           958:     t = last(t);
        !           959: 
        !           960:   /* Malloc space for internal name and copy it */
        !           961:   if ((n = malloc(strlen(t) + 1)) == NULL)
        !           962:     return NULL;
        !           963:   strcpy(n, t);
        !           964: 
        !           965: #ifdef VMS
        !           966:   if ((t = strrchr(n, ']')) != NULL)
        !           967:   {
        !           968:     *t = '/';
        !           969:     while (--t > n)
        !           970:       if (*t == '.')
        !           971:         *t = '/';
        !           972:   }
        !           973: 
        !           974:   /* Fix from Greg Roelofs: */
        !           975:   /* Get current working directory and strip from n (t now = n) */
        !           976:   {
        !           977:     char cwd[256], *p, *q;
        !           978:     int c;
        !           979: 
        !           980:     if (getcwd(cwd, 256) && ((p = strchr(cwd, '.')) != NULL))
        !           981:     {
        !           982:       ++p;
        !           983:       if ((q = strrchr(p, ']')) != NULL)
        !           984:       {
        !           985:         *q = '/';
        !           986:         while (--q > p)
        !           987:           if (*q == '.')
        !           988:             *q = '/';
        !           989:         /* strip bogus path parts from n */
        !           990:         if (strncmp(n, p, (c=strlen(p))) == 0)
        !           991:         {
        !           992:           q = n + c;
        !           993:           while (*t++ = *q++)
        !           994:             ;
        !           995:         }
        !           996:       }
        !           997:     }
        !           998:   }
        !           999:   strlower(n);
        !          1000:   if (!vmsver)
        !          1001:     if ((t = strrchr(n, ';')) != NULL)
        !          1002:       *t = 0;
        !          1003: 
        !          1004:   if( (t = strrchr(n, '.')) != NULL )
        !          1005:   {
        !          1006:     if( t[1] == 0 )               /* "filename." -> "filename" */
        !          1007:       *t = 0;
        !          1008:     else if( t[1] == ';' )        /* "filename.;vvv" -> "filename;vvv" */
        !          1009:     {
        !          1010:       char *f;
        !          1011:       for( f=t+1; *t++ = *f++; )
        !          1012:         ;
        !          1013:     }
        !          1014:   }
        !          1015: #endif /* VMS */
        !          1016:   if (dosify)
        !          1017:     msname(n);
        !          1018: #if defined(MSDOS) && !defined(OS2) && !defined(FORCE_UPPER)
        !          1019:   else
        !          1020:     strlwr(n);
        !          1021: #endif
        !          1022:   /* Returned malloc'ed name */
        !          1023:   if (pdosflag) 
        !          1024:     *pdosflag = dosflag;
        !          1025:   return n;
        !          1026: }
        !          1027: 
        !          1028: 
        !          1029: char *in2ex(n)
        !          1030: char *n;                /* internal file name */
        !          1031: /* Convert the zip file name to an external file name, returning the malloc'ed
        !          1032:    string or NULL if not enough memory. */
        !          1033: {
        !          1034:   char *x;              /* external file name */
        !          1035: #ifdef VMS
        !          1036:   char *t;              /* scans name */
        !          1037: 
        !          1038:   if ((t = strrchr(n, '/')) == NULL)
        !          1039: #endif /* VMS */
        !          1040:   {
        !          1041:     if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
        !          1042:       return NULL;
        !          1043:     strcpy(x, n);
        !          1044:   }
        !          1045: #ifdef VMS
        !          1046:   else
        !          1047:   {
        !          1048:     if ((x = malloc(strlen(n) + 3 + PAD)) == NULL)
        !          1049:       return NULL;
        !          1050:     strcpy(x, "[.");
        !          1051:     strcpy(x + 2, n);
        !          1052:     *(t = x + 2 + (t - n)) = ']';
        !          1053:     while (--t > x)
        !          1054:       if (*t == '/')
        !          1055:         *t = '.';
        !          1056:   }
        !          1057:   strupper(x);
        !          1058: #endif /* VMS */
        !          1059: #ifdef OS2
        !          1060:   if ( !IsFileNameValid(x) )
        !          1061:     ChangeNameForFAT(x);
        !          1062: #endif /* !OS2 */
        !          1063: #if defined(FORCE_UPPER) && defined(MSDOS)
        !          1064:   /* Don't convert to upper case, causes wrong warnings. Keep the
        !          1065:    * name as it was before in the old zip file.
        !          1066:    */
        !          1067:   strupr(x);
        !          1068: #endif
        !          1069:   return x;
        !          1070: }
        !          1071: 
        !          1072: 
        !          1073: int exclude()
        !          1074: /* Change from including to excluding names when procname() called.  Return
        !          1075:    an error code in the ZE_ class. */
        !          1076: {
        !          1077:   struct flist far *f;          /* steps through found linked list */
        !          1078:   extent j;                     /* index for s */
        !          1079:   struct flist far **s;         /* sorted table */
        !          1080: 
        !          1081:   /* sort found list, remove duplicates */
        !          1082:   if (fcount)
        !          1083:   {
        !          1084:     if ((s = (struct flist far **)malloc(
        !          1085:          fcount * sizeof(struct flist far *))) == NULL)
        !          1086:       return ZE_MEM;
        !          1087:     for (j = 0, f = found; f != NULL; f = f->nxt)
        !          1088:       s[j++] = f;
        !          1089:     qsort((char *)s, fcount, sizeof(struct flist far *), fqcmp);
        !          1090:     for (j = fcount - 1; j > 0; j--)
        !          1091:       if (strcmp(s[j - 1]->name, s[j]->name) == 0)
        !          1092:         fexpel(s[j]);           /* fexpel() changes fcount */
        !          1093:     qsort((char *)s, fcount, sizeof(struct flist far *), fqcmpz);
        !          1094:     for (j = 1; j < fcount; j++)
        !          1095:       if (strcmp(s[j - 1]->zname, s[j]->zname) == 0)
        !          1096:       {
        !          1097:         warn("name in zip file repeated: ", s[j]->zname);
        !          1098:         warn("  first full name: ", s[j - 1]->name);
        !          1099:         warn(" second full name: ", s[j]->name);
        !          1100:         return ZE_PARMS;
        !          1101:       }
        !          1102:     free((voidp *)s);
        !          1103:   }
        !          1104:   exflag = 1;
        !          1105:   return ZE_OK;
        !          1106: }
        !          1107: 
        !          1108: 
        !          1109: local int newname(n)
        !          1110: char *n;                /* name to add (or exclude) */
        !          1111: /* Add (or exclude) a name that is not in the zip file.  Return an error
        !          1112:    code in the ZE_ class. */
        !          1113: {
        !          1114:   char *m;
        !          1115:   struct flist far *f;  /* where in found, or new found entry */
        !          1116:   struct zlist far *z;  /* where in zfiles (if found) */
        !          1117:   int dosflag;
        !          1118: 
        !          1119:   /* Search for name in zip file.  If there, mark it, else add to
        !          1120:      list of new names to do (or remove from that list). */
        !          1121:   if ((m = ex2in(n, &dosflag)) == NULL)
        !          1122:     return ZE_MEM;
        !          1123:   if ((z = zsearch(m)) != NULL)
        !          1124:     if (exflag)
        !          1125:     {
        !          1126:       z->mark = 0;
        !          1127:       free((voidp *)m);
        !          1128:       if (verbose)
        !          1129:         printf("zip diagnostic: excluding %s\n", z->name);
        !          1130:     }
        !          1131:     else
        !          1132:     {
        !          1133:       free((voidp *)(z->name));
        !          1134:       free((voidp *)(z->zname));
        !          1135:       if ((z->name = malloc(strlen(n) + 1 + PAD)) == NULL)
        !          1136:         return ZE_MEM;
        !          1137:       strcpy(z->name, n);
        !          1138:       z->zname = m;
        !          1139:       z->mark = 1;
        !          1140:       z->dosflag = dosflag;
        !          1141:       if (verbose)
        !          1142:         printf("zip diagnostic: including %s\n", z->name);
        !          1143:     }
        !          1144:   else
        !          1145:     if (exflag)
        !          1146:     {
        !          1147:       /* search list for name--if there, remove it */
        !          1148:       for (f = found; f != NULL; f = f->nxt)
        !          1149:         if (namecmp(n, f->name) == 0)
        !          1150:         {
        !          1151:           fexpel(f);
        !          1152:           break;
        !          1153:         }
        !          1154:       free((voidp *)m);
        !          1155:     }
        !          1156:     else
        !          1157:     {
        !          1158:       /* allocate space and add to list */
        !          1159:       if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL ||
        !          1160:           (f->name = malloc(strlen(n) + 1 + PAD)) == NULL)
        !          1161:       {
        !          1162:         if (f != NULL)
        !          1163:           farfree((voidp far *)f);
        !          1164:         return ZE_MEM;
        !          1165:       }
        !          1166:       strcpy(f->name, n);
        !          1167:       f->zname = m;
        !          1168:       f->dosflag = dosflag;
        !          1169:       *fnxt = f;
        !          1170:       f->lst = fnxt;
        !          1171:       f->nxt = NULL;
        !          1172:       fnxt = &f->nxt;
        !          1173:       fcount++;
        !          1174:     }
        !          1175:   return ZE_OK;
        !          1176: }
        !          1177: 
        !          1178: 
        !          1179: int procname(n)
        !          1180: char *n;                /* name to process */
        !          1181: /* Process a name or sh expression to operate on (or exclude).  Return
        !          1182:    an error code in the ZE_ class. */
        !          1183: {
        !          1184:   char *a;              /* path and name for recursion */
        !          1185:   dstrm *d;             /* directory stream from opend() */
        !          1186:   char *e;              /* pointer to name from readd() */
        !          1187:   struct flist far *f;  /* steps through found list */
        !          1188:   int m;                /* matched flag */
        !          1189:   char *p;              /* path for recursion */
        !          1190:   struct stat s;        /* result of stat() */
        !          1191:   struct zlist far *z;  /* steps through zfiles list */
        !          1192: 
        !          1193:   if (strcmp(n, "-") == 0)   /* if compressing stdin */
        !          1194:     return newname(n);
        !          1195:   else if (
        !          1196: #ifdef S_IFLNK          /* if symbolic links exist ... */
        !          1197:       linkput ? lstat(n, &s) :
        !          1198: #endif /* S_IFLNK */
        !          1199:       SSTAT(n, &s)
        !          1200: #if defined(__TURBOC__) || defined(VMS)
        !          1201:        /* Borland and VMS C bug: stat() succeeds on wild card names! */
        !          1202:       || isshexp(n)
        !          1203: #endif
        !          1204:      )
        !          1205:   {
        !          1206:     /* Not a file or directory--search for shell expression in zip file */
        !          1207:     p = ex2in(n, NULL);         /* shouldn't affect matching chars */
        !          1208:     m = 1;
        !          1209:     for (z = zfiles; z != NULL; z = z->nxt)
        !          1210:       if (MATCH(p, z->zname))
        !          1211:       {
        !          1212:         z->mark = !exflag;
        !          1213:         if (verbose)
        !          1214:           printf("zip diagnostic: %scluding %s\n",
        !          1215:                  exflag ? "ex" : "in", z->name);
        !          1216:         m = 0;
        !          1217:       }
        !          1218:     /* If excluding, also search for expression in found list */
        !          1219:     if (exflag)
        !          1220:     {
        !          1221:       for (f = found; f != NULL;)
        !          1222:         if (MATCH(p, f->zname))
        !          1223:         {
        !          1224:           f = fexpel(f);
        !          1225:           m = 0;
        !          1226:         }
        !          1227:         else
        !          1228:           f = f->nxt;
        !          1229:     }
        !          1230:     free((voidp *)p);
        !          1231:     if (m)
        !          1232:       return ZE_MISS;           /* no match */
        !          1233:   }
        !          1234:   else
        !          1235:   {
        !          1236:     /* Live name--use if file, recurse if directory */
        !          1237: #if defined(FORCE_UPPER) && defined(MSDOS)
        !          1238: # ifndef OS2
        !          1239:     strupr(n);                  /* convert to upper case */
        !          1240: # else /* OS2 */
        !          1241:     if (IsFileSystemFAT(n)) strupr(n);
        !          1242: # endif /* !OS2 */
        !          1243: #endif
        !          1244: 
        !          1245: #ifdef MSDOS
        !          1246:     for (p = n; *p; p++)          /* use / consistently */
        !          1247:       if (*p == '\\')
        !          1248:         *p = '/';
        !          1249: #endif /* MSDOS */
        !          1250:     if ((s.st_mode & S_IFDIR) == 0)
        !          1251:     {
        !          1252:       /* add or remove name of file */
        !          1253:         if ((m = newname(n)) != ZE_OK)
        !          1254:           return m;
        !          1255:     } else {
        !          1256:         /* recurse into directory */
        !          1257:         if (recurse && (d = opend(n)) != NULL)
        !          1258:         {
        !          1259: #ifdef VMS
        !          1260:           while ((e = readd(d)) != NULL)
        !          1261:             if ((m = procname(e)) != ZE_OK)     /* recurse on name */
        !          1262:             {
        !          1263:               /* want to just set warning error and continue */
        !          1264:               closed(d);
        !          1265:               return m;
        !          1266:             }
        !          1267: #else /* !VMS */
        !          1268:           if ((p = malloc(strlen(n)+2)) == NULL)
        !          1269:             return ZE_MEM;
        !          1270:           if (strcmp(n, ".") == 0)
        !          1271:             *p = 0; /* avoid "./" prefix and do not create zip entry */
        !          1272:           else
        !          1273:           {
        !          1274:             strcpy(p, n);
        !          1275:             a = p + strlen(p);
        !          1276:             if (a[-1] != '/')
        !          1277:               strcpy(a, "/");
        !          1278:             if ((m = newname(p)) != ZE_OK)
        !          1279:               return m;
        !          1280:           }
        !          1281:           while ((e = readd(d)) != NULL)
        !          1282:             if (strcmp(e, ".") && strcmp(e, ".."))
        !          1283:             {
        !          1284:               if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
        !          1285:               {
        !          1286:                 free((voidp *)p);
        !          1287:                 closed(d);
        !          1288:                 return ZE_MEM;
        !          1289:               }
        !          1290:               strcat(strcpy(a, p), e);
        !          1291:               if ((m = procname(a)) != ZE_OK)   /* recurse on name */
        !          1292:               {
        !          1293:                 free((voidp *)a);  free((voidp *)p);
        !          1294:                 closed(d);
        !          1295:                 return m;
        !          1296:               }
        !          1297:               free((voidp *)a);
        !          1298:             }
        !          1299:           free((voidp *)p);
        !          1300: #endif /* ?VMS */
        !          1301:           closed(d);
        !          1302:         }
        !          1303:       }
        !          1304:     }
        !          1305:   return ZE_OK;
        !          1306: }
        !          1307: 
        !          1308: 
        !          1309: #if !defined(CRAY) && !defined(__TURBOC__) && !defined(OS2) /* and ... */
        !          1310: #if !defined( __GO32__)
        !          1311: 
        !          1312: local int cmptime(p, q)
        !          1313: struct tm *p, *q;       /* times to compare */
        !          1314: /* Return negative if time p is before time q, positive if after, and
        !          1315:    zero if the same */
        !          1316: {
        !          1317:   int r;                /* temporary variable */
        !          1318: 
        !          1319:   if (p == NULL)
        !          1320:     return -1;
        !          1321:   else if ((r = p->tm_year - q->tm_year) != 0)
        !          1322:     return r;
        !          1323:   else if ((r = p->tm_mon - q->tm_mon) != 0)
        !          1324:     return r;
        !          1325:   else if ((r = p->tm_mday - q->tm_mday) != 0)
        !          1326:     return r;
        !          1327:   else if ((r = p->tm_hour - q->tm_hour) != 0)
        !          1328:     return r;
        !          1329:   else if ((r = p->tm_min - q->tm_min) != 0)
        !          1330:     return r;
        !          1331:   else
        !          1332:     return p->tm_sec - q->tm_sec;
        !          1333: }
        !          1334: 
        !          1335: 
        !          1336: local time_t invlocal(t)
        !          1337: struct tm *t;           /* time to convert */
        !          1338: /* Find inverse of localtime() using bisection.  This routine assumes that
        !          1339:    time_t is an integer type, either signed or unsigned.  The expectation
        !          1340:    is that sometime before the year 2038, time_t will be made a 64-bit
        !          1341:    integer, and this routine will still work. */
        !          1342: {
        !          1343:   time_t i;             /* midpoint of current root range */
        !          1344:   time_t l;             /* lower end of root range */
        !          1345:   time_t u;             /* upper end of root range */
        !          1346: 
        !          1347:   /* Bracket the root [0,largest time_t].  Note: if time_t is a 32-bit signed
        !          1348:      integer, then the upper bound is GMT 1/19/2038 03:14:07, after which all
        !          1349:      the Unix systems in the world come to a grinding halt.  Either that, or
        !          1350:      all those systems will suddenly find themselves transported to December
        !          1351:      of 1901 ... */
        !          1352:   l = 0;
        !          1353:   u = 1;
        !          1354:   while (u < (u << 1))
        !          1355:     u = (u << 1) + 1;
        !          1356: 
        !          1357:   /* Find the root */
        !          1358:   while (u - l > 1)
        !          1359:   {
        !          1360:     i = l + ((u - l) >> 1);
        !          1361:     if (cmptime(localtime(&i), t) <= 0)
        !          1362:       l = i;
        !          1363:     else
        !          1364:       u = i;
        !          1365:   }
        !          1366:   return l;
        !          1367: }
        !          1368: #endif
        !          1369: #endif
        !          1370: 
        !          1371: 
        !          1372: void stamp(f, d)
        !          1373: char *f;                /* name of file to change */
        !          1374: ulg d;                  /* dos-style time to change it to */
        !          1375: /* Set last updated and accessed time of file f to the DOS time d. */
        !          1376: {
        !          1377: #if defined(MACOS)
        !          1378:   warn("timestamp not implemented yet", "");
        !          1379: #else
        !          1380: #ifdef __TURBOC__
        !          1381:   int h;                /* file handle */
        !          1382: 
        !          1383:   if ((h = open(f, 0)) != -1)
        !          1384:   {
        !          1385: #ifdef ATARI_ST
        !          1386:     d = ( d >> 16 ) | ( d << 16 );
        !          1387: #endif
        !          1388:     setftime(h, (struct ftime *)&d);
        !          1389:     close(h);
        !          1390:   }
        !          1391: #else /* !__TURBOC__ */
        !          1392: #ifdef VMS
        !          1393:   int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year;
        !          1394:   char timbuf[24];
        !          1395:   static char *month[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
        !          1396:                           "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
        !          1397:   struct VMStimbuf {
        !          1398:       char *actime;           /* VMS revision date, ASCII format */
        !          1399:       char *modtime;          /* VMS creation date, ASCII format */
        !          1400:   } ascii_times = {timbuf, timbuf};
        !          1401: 
        !          1402:   /* Convert DOS time to ASCII format for VMSmunch */
        !          1403:   tm_sec = (int)(d << 1) & 0x3e;
        !          1404:   tm_min = (int)(d >> 5) & 0x3f;
        !          1405:   tm_hour = (int)(d >> 11) & 0x1f;
        !          1406:   tm_mday = (int)(d >> 16) & 0x1f;
        !          1407:   tm_mon = ((int)(d >> 21) & 0xf) - 1;
        !          1408:   tm_year = ((int)(d >> 25) & 0x7f) + 1980;
        !          1409:   sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", tm_mday, month[tm_mon],
        !          1410:     tm_year, tm_hour, tm_min, tm_sec);
        !          1411: 
        !          1412:   /* Set updated and accessed times of f */
        !          1413:   if (VMSmunch(f, SET_TIMES, &ascii_times) != RMS$_NMF)
        !          1414:     warn("can't set zipfile time: ", f);
        !          1415: 
        !          1416: #else /* !VMS */
        !          1417: #ifdef OS2
        !          1418:   SetFileTime(f, d);
        !          1419: #else /* !OS2 */
        !          1420:   struct tm t;          /* argument for mktime() or invlocal() */
        !          1421:   time_t u[2];          /* argument for utime() */
        !          1422: #ifndef __GO32__
        !          1423:   extern time_t mktime OF((struct tm *));
        !          1424: #endif
        !          1425: 
        !          1426:   /* Convert DOS time to time_t format in u[0] and u[1] */
        !          1427:   t.tm_sec = (int)(d << 1) & 0x3e;
        !          1428:   t.tm_min = (int)(d >> 5) & 0x3f;
        !          1429:   t.tm_hour = (int)(d >> 11) & 0x1f;
        !          1430:   t.tm_mday = (int)(d >> 16) & 0x1f;
        !          1431:   t.tm_mon = ((int)(d >> 21) & 0xf) - 1;
        !          1432:   t.tm_year = ((int)(d >> 25) & 0x7f) + 80;
        !          1433: #if defined(MSDOS) || defined(OS2) || defined(CRAY)
        !          1434:   /* mktime() is more reliable than invlocal() because the time range is
        !          1435:    * wider on MSDOS than on Unix; required for Cray because invlocal assumes
        !          1436:    * 32-bit ints
        !          1437:    */
        !          1438:   u[0] = u[1] = mktime(&t);
        !          1439: #else
        !          1440:   u[0] = u[1] = invlocal(&t);
        !          1441: #endif
        !          1442: 
        !          1443:   /* Set updated and accessed times of f */
        !          1444:   utime(f, u);
        !          1445: #endif /* ?OS2 */
        !          1446: #endif /* ?VMS */
        !          1447: #endif /* ?__TURBOC__ */
        !          1448: #endif /* ?MACOS */
        !          1449: }
        !          1450: 
        !          1451: 
        !          1452: local void inctime(s)
        !          1453: struct tm *s;           /* time to increment in place */
        !          1454: /* Increment the time structure *s by one second, return the result in
        !          1455:    place. */
        !          1456: {
        !          1457:   int y;                /* temporary variable */
        !          1458: 
        !          1459:   /* days in each month, except for February */
        !          1460:   static int days[] = {31,0,31,30,31,30,31,31,30,31,30,31};
        !          1461: 
        !          1462:   /* Set days in February from year (1900 is a leap year, 2000 is not) */
        !          1463:   y = s->tm_year + 1900;
        !          1464:   days[1] = y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) ? 29 : 28;
        !          1465: 
        !          1466:   /* Increment time with carry */
        !          1467:   if (s->tm_sec != 59)
        !          1468:     s->tm_sec++;
        !          1469:   else if (s->tm_sec = 0, s->tm_min != 59)
        !          1470:     s->tm_min++;
        !          1471:   else if (s->tm_min = 0, s->tm_hour != 23)
        !          1472:     s->tm_hour++;
        !          1473:   else if (s->tm_hour = 0, s->tm_mday != days[s->tm_mon])
        !          1474:     s->tm_mday++;
        !          1475:   else if (s->tm_mday = 1, s->tm_mon != 11)
        !          1476:     s->tm_mon++;
        !          1477:   else
        !          1478:   {
        !          1479:     s->tm_mon = 0;
        !          1480:     s->tm_year++;
        !          1481:   }
        !          1482: }
        !          1483: 
        !          1484: 
        !          1485: ulg dostime(y, n, d, h, m, s)
        !          1486: int y;                  /* year */
        !          1487: int n;                  /* month */
        !          1488: int d;                  /* day */
        !          1489: int h;                  /* hour */
        !          1490: int m;                  /* minute */
        !          1491: int s;                  /* second */
        !          1492: /* Convert the date y/n/d and time h:m:s to a four byte DOS date and
        !          1493:    time (date in high two bytes, time in low two bytes allowing magnitude
        !          1494:    comparison). */
        !          1495: {
        !          1496:   return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0) :
        !          1497:         (((ulg)y - 1980) << 25) | ((ulg)n << 21) | ((ulg)d << 16) |
        !          1498:         ((ulg)h << 11) | ((ulg)m << 5) | ((ulg)s >> 1);
        !          1499: }
        !          1500: 
        !          1501: 
        !          1502: local ulg unix2dostime(t)
        !          1503: statime *t;             /* unix time to convert */
        !          1504: /* Return the Unix time t in DOS format, rounded up to the next two
        !          1505:    second boundary. */
        !          1506: {
        !          1507:   struct tm *s;         /* result of localtime() */
        !          1508: 
        !          1509:   s = localtime(t);             /* Use local time since MSDOS does */
        !          1510:   inctime(s);                   /* Add one second to round up */
        !          1511:   return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
        !          1512:                  s->tm_hour, s->tm_min, s->tm_sec);
        !          1513: }
        !          1514: 
        !          1515: 
        !          1516: ulg filetime(f, a, n)
        !          1517: char *f;                /* name of file to get info on */
        !          1518: ulg *a;                 /* return value: file attributes */
        !          1519: long *n;                /* return value: file size */
        !          1520: /* If file *f does not exist, return 0.  Else, return the file's last
        !          1521:    modified date and time as an MSDOS date and time.  The date and
        !          1522:    time is returned in a long with the date most significant to allow
        !          1523:    unsigned integer comparison of absolute times.  Also, if a is not
        !          1524:    a NULL pointer, store the file attributes there, with the high two
        !          1525:    bytes being the Unix attributes, and the low byte being a mapping
        !          1526:    of that to DOS attributes.  If n is not NULL, store the file size
        !          1527:    there.
        !          1528:    If f is "-", use standard input as the file. If f is a device, return
        !          1529:    a file size of -1 */
        !          1530: {
        !          1531:   struct stat s;        /* results of stat() */
        !          1532:   char name[FNMAX];
        !          1533:   int len = strlen(f);
        !          1534: 
        !          1535:   strcpy(name, f);
        !          1536:   if (name[len - 1] == '/')
        !          1537:     name[len - 1] = 0; 
        !          1538:   /* not all systems allow stat'ing a file with / appended */
        !          1539: 
        !          1540:   if (strcmp(f, "-") == 0) {
        !          1541:     if (fstat(fileno(stdin), &s) != 0)
        !          1542:       error("fstat(stdin)");
        !          1543:   } else if ((
        !          1544: #ifdef S_IFLNK
        !          1545:              linkput ? lstat(name, &s) :
        !          1546: #endif
        !          1547:              SSTAT(name, &s)) != 0)
        !          1548:              /* Accept about any file kind including directories
        !          1549:               * (stored with trailing / with -r option)
        !          1550:               */
        !          1551:     return 0;
        !          1552: 
        !          1553:   if (a != NULL)
        !          1554: #ifdef OS2
        !          1555:     *a = (s.st_mode << 16) | GetFileMode(name);
        !          1556: #else
        !          1557:     *a = (s.st_mode << 16) | !(s.st_mode & S_IWRITE);
        !          1558: #endif
        !          1559:   if (n != NULL)
        !          1560:     *n = (s.st_mode & S_IFREG) == 0 ? -1L : s.st_size;
        !          1561: 
        !          1562: #ifdef OS2
        !          1563:   return GetFileTime(name);
        !          1564: #else /* !OS2 */
        !          1565: #  ifdef VMS
        !          1566:      return unix2dostime(&s.st_ctime);   /* Use creation time in VMS */
        !          1567: #  else /* !VMS */
        !          1568: #    ifdef ATARI_ST
        !          1569:        return s.st_mtime; /* Turbo C doesn't use UNIX times */
        !          1570: #    else
        !          1571:        return unix2dostime(&s.st_mtime);
        !          1572: #    endif
        !          1573: #  endif /* ?VMS */
        !          1574: #endif /* ?OS2 */
        !          1575: }
        !          1576: 
        !          1577: 
        !          1578: int issymlnk(a)
        !          1579: ulg a;                  /* Attributes returned by filetime() */
        !          1580: /* Return true if the attributes are those of a symbolic link */
        !          1581: {
        !          1582: #ifdef S_IFLNK
        !          1583:   return ((a >> 16) & S_IFMT) == S_IFLNK;
        !          1584: #else /* !S_IFLNK */
        !          1585:   return (int)a & 0;    /* avoid warning on unused parameter */
        !          1586: #endif /* ?S_IFLNK */
        !          1587: }
        !          1588: 
        !          1589: 
        !          1590: int deletedir(d)
        !          1591: char *d;                /* directory to delete */
        !          1592: /* Delete the directory *d if it is empty, do nothing otherwise.
        !          1593:    Return the result of rmdir(), delete(), or system().
        !          1594:  */
        !          1595: {
        !          1596: #ifdef MACOS
        !          1597:   warn("deletedir not implemented yet", "");
        !          1598:   return 127;
        !          1599: #else
        !          1600: #ifdef RMDIR
        !          1601:   /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
        !          1602:   int r, len;
        !          1603:   char *s;              /* malloc'd string for system command */
        !          1604: 
        !          1605:   len = strlen(d);
        !          1606:   if ((s = malloc(len + 34)) == NULL)
        !          1607:     return 127;
        !          1608: 
        !          1609: #ifdef VMS
        !          1610:   {
        !          1611:     char *c;            /* pointer into VMS path */
        !          1612:     /* convert "DEV:[DIR.SUB1.SUB2]" form to "DEV:[DIR.SUB1]SUB2.DIR;0" */
        !          1613:     strcat(strcpy(s, "set prot=(o:rwed) "), d);   /* d starts at s+18 */
        !          1614:     if (*(c = s+17+len) != ']')
        !          1615:     {
        !          1616:       free(s);
        !          1617:       return 127;
        !          1618:     }
        !          1619:     strcpy(c, ".DIR;0");        /* 0 translates to highest version */
        !          1620:     while (--c > s+18  &&  *c != '.'  &&  *c != '[') ;
        !          1621:     if (c == s+18)
        !          1622:     {
        !          1623:       free(s);
        !          1624:       return 127;
        !          1625:     }
        !          1626:     if (*c == '.')
        !          1627:       *c = ']';
        !          1628:     else if (*--c == ']')  /* presumably of form "DEV:[DIR.SUB1.][SUB2]" */
        !          1629:     {                      /* (possible to have "DEV:[DIR.SUB1.][][SUB2]"?) */
        !          1630:       char *b = c + 2;
        !          1631:       c[-1] = ']';
        !          1632:       while (*c++ = *b++) ;
        !          1633:     }
        !          1634:     else        /* must have reached device name:  can't delete top level */
        !          1635:     {
        !          1636:       free(s);
        !          1637:       return 127;
        !          1638:     }
        !          1639:   }
        !          1640:   /* unprotect directory and delete it as a file.  May fail if exists 
        !          1641:      normal file "foo.dir" on top of directory "foo.dir" */
        !          1642:   system(s);
        !          1643:   r = delete(s+18);
        !          1644: #else /* !VMS */
        !          1645:   sprintf(s, "IFS=\" \t\n\" /bin/rmdir %s 2>/dev/null", d);
        !          1646:   r = system(s);
        !          1647: #endif /* ?VMS */
        !          1648:   free(s);
        !          1649:   return r;
        !          1650: #else /* !RMDIR */
        !          1651:   return rmdir(d);
        !          1652: #endif /* ?RMDIR */
        !          1653: #endif /* ?MACOS */
        !          1654: }
        !          1655: 
        !          1656: 
        !          1657: #endif /* !UTIL */
        !          1658: 
        !          1659: int destroy(f)
        !          1660: char *f;                /* file to delete */
        !          1661: /* Delete the file *f, returning non-zero on failure. */
        !          1662: {
        !          1663:   return unlink(f);
        !          1664: }
        !          1665: 
        !          1666: 
        !          1667: int replace(d, s)
        !          1668: char *d, *s;            /* destination and source file names */
        !          1669: /* Replace file *d by file *s, removing the old *s.  Return an error code
        !          1670:    in the ZE_ class. */
        !          1671: {
        !          1672:   struct stat t;        /* results of stat() */
        !          1673: 
        !          1674:   if (SSTAT(d, &t) == 0 && unlink(d))
        !          1675:     return ZE_CREAT;                    /* Can't erase zip file--give up */
        !          1676:   if (link(s, d))                       /* Just move s on top of d */
        !          1677: #if !defined(VMS) && !defined(ATARI_ST)
        !          1678:     /* For VMS & ATARI assume failure is EXDEV */
        !          1679:     if (errno != EXDEV
        !          1680: #  ifdef ENOTSAM
        !          1681:        && errno != ENOTSAM /* Used at least on Turbo C */
        !          1682: #  endif
        !          1683:         ) return ZE_CREAT;
        !          1684:     else
        !          1685: #endif
        !          1686:     {
        !          1687:       FILE *f, *g;      /* source and destination files */
        !          1688:       int r;            /* temporary variable */
        !          1689: 
        !          1690:       if ((f = fopen(s, FOPR)) == NULL) {
        !          1691:         fprintf(stderr," replace: can't open %s\n", s);
        !          1692:         return ZE_TEMP;
        !          1693:       }
        !          1694:       if ((g = fopen(d, FOPW)) == NULL)
        !          1695:       {
        !          1696:         fclose(f);
        !          1697:         return ZE_CREAT;
        !          1698:       }
        !          1699:       r = fcopy(f, g, (ulg)-1L);
        !          1700:       fclose(f);
        !          1701:       if (fclose(g) || r != ZE_OK)
        !          1702:       {
        !          1703:         unlink(d);
        !          1704:         return r ? (r == ZE_TEMP ? ZE_WRITE : r) : ZE_WRITE;
        !          1705:       }
        !          1706: #ifdef VMS /* only delete if rename failed:  previous version may exist */
        !          1707:       unlink(s);
        !          1708:     }
        !          1709: #else /* !VMS */
        !          1710:     }
        !          1711:   unlink(s);
        !          1712: #endif /* !VMS */
        !          1713:   return ZE_OK;
        !          1714: }
        !          1715: 
        !          1716: 
        !          1717: int getfileattr(f)
        !          1718: char *f;                /* file path */
        !          1719: /* Return the file attributes for file f or 0 if failure */
        !          1720: {
        !          1721:   struct stat s;
        !          1722: 
        !          1723:   return SSTAT(f, &s) == 0 ? s.st_mode : 0;
        !          1724: }
        !          1725: 
        !          1726: 
        !          1727: int setfileattr(f, a)
        !          1728: char *f;                /* file path */
        !          1729: int a;                  /* attributes returned by getfileattr() */
        !          1730: /* Give the file f the attributes a, return non-zero on failure */
        !          1731: {
        !          1732: #if defined (VMS) || defined(MACOS)
        !          1733:   return 0;
        !          1734: #else /* !VMS */
        !          1735:   return chmod(f, a);
        !          1736: #endif /* ?VMS */
        !          1737: }
        !          1738: 
        !          1739: 
        !          1740: #ifdef NO_MKTEMP
        !          1741: 
        !          1742: char *tempname(zip)
        !          1743:   char *zip;              /* path name of zip file to generate temp name for */
        !          1744: 
        !          1745: /* Return a temporary file name in its own malloc'ed space.
        !          1746:  * This function might accidentally destroy an existing file
        !          1747:  * with extension .$z$ . Use mktemp below if you have it on your system.
        !          1748:  */
        !          1749: {
        !          1750:   char *p;              /* temporary pointer */
        !          1751:   char *t;              /* malloc'ed space for name */
        !          1752: 
        !          1753:   if ((t = malloc(strlen(zip)+5)) == NULL)
        !          1754:     return NULL;
        !          1755:   strcpy(t, zip);
        !          1756:   if ((p = strrchr(t, '.')) != NULL &&
        !          1757:       (!strncmp(p, ".zip", 4) || !strncmp(p, ".ZIP", 4)))
        !          1758:       /* strncmp to avoid problems with VMS ';' */
        !          1759:     strcpy(p, ".$z$");
        !          1760:   else
        !          1761:     strcat(t, ".$z$");
        !          1762: 
        !          1763:   return t;
        !          1764: }
        !          1765: #else /* !NO_MKTEMP */
        !          1766: 
        !          1767: char *tempname(zip)
        !          1768:   char *zip;              /* path name of zip file to generate temp name for */
        !          1769: 
        !          1770: /* Return a temporary file name in its own malloc'ed space, using tempath. */
        !          1771: {
        !          1772:   char *t = zip;   /* malloc'ed space for name (use zip to avoid warning) */
        !          1773: 
        !          1774:   if (tempath != NULL)
        !          1775:   {
        !          1776:     if ((t = malloc(strlen(tempath)+10)) == NULL)
        !          1777:       return NULL;
        !          1778:     strcpy(t, tempath);
        !          1779: #ifndef VMS
        !          1780:     if (t[strlen(t)-1] != '/')
        !          1781:       strcat(t, "/");
        !          1782: #endif
        !          1783:   }
        !          1784:   else
        !          1785:   {
        !          1786:     if ((t = malloc(9)) == NULL)
        !          1787:       return NULL;
        !          1788:     *t = 0;
        !          1789:   }
        !          1790:   strcat(t, "_ZXXXXXX");
        !          1791:   return mktemp(t);
        !          1792: }
        !          1793: 
        !          1794: #endif /* NO_MKTEMP */
        !          1795: 
        !          1796: 
        !          1797: int fcopy(f, g, n)
        !          1798: FILE *f, *g;            /* source and destination files */
        !          1799: ulg n;                  /* number of bytes to copy or -1 for all */
        !          1800: /* Copy n bytes from file *f to file *g, or until EOF if n == -1.  Return
        !          1801:    an error code in the ZE_ class. */
        !          1802: {
        !          1803:   char *b;              /* malloc'ed buffer for copying */
        !          1804:   extent k;             /* result of fread() */
        !          1805:   ulg m;                /* bytes copied so far */
        !          1806: 
        !          1807:   if ((b = malloc(CBSZ)) == NULL)
        !          1808:     return ZE_MEM;
        !          1809:   m = 0;
        !          1810:   while (n == -1L || m < n)
        !          1811:   {
        !          1812:     if ((k = fread(b, 1, n == -1 ?
        !          1813:                    CBSZ : (n - m < CBSZ ? (extent)(n - m) : CBSZ), f)) == 0)
        !          1814:       if (ferror(f))
        !          1815:       {
        !          1816:         free((voidp *)b);
        !          1817:         return ZE_READ;
        !          1818:       }
        !          1819:       else
        !          1820:         break;
        !          1821:     if (fwrite(b, 1, k, g) != k)
        !          1822:     {
        !          1823:       free((voidp *)b);
        !          1824:       fprintf(stderr," fcopy: write error\n");
        !          1825:       return ZE_TEMP;
        !          1826:     }
        !          1827:     m += k;
        !          1828:   }
        !          1829:   free((voidp *)b);
        !          1830:   return ZE_OK;
        !          1831: }
        !          1832: 
        !          1833: 
        !          1834: #ifdef CRYPT
        !          1835: 
        !          1836: #ifndef MSDOS
        !          1837: 
        !          1838: #ifdef VMS
        !          1839: 
        !          1840: int echo(opt)
        !          1841:     int opt;
        !          1842: {
        !          1843: /*---------------------------------------------------------------------------
        !          1844:     Based on VMSmunch.c, which in turn was based on Joe Meadows' file.c code.
        !          1845:   ---------------------------------------------------------------------------
        !          1846:      * For VMS v5.x:
        !          1847:      *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
        !          1848:      *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
        !          1849:      *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
        !          1850:      *     System Services Reference Manual, pp. sys-23, sys-379
        !          1851:      *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
        !          1852:      *     Intro to System Routines, sec. 2.9.2
        !          1853:      * GRR, 15 Aug 91
        !          1854:   ---------------------------------------------------------------------------*/
        !          1855:     static struct dsc$descriptor_s DevDesc =
        !          1856:         {9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"};
        !          1857:      /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
        !          1858:     static short           DevChan, iosb[4];
        !          1859:     static long            i, status;
        !          1860:     static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
        !          1861:   
        !          1862: 
        !          1863: /*---------------------------------------------------------------------------
        !          1864:     Assign a channel to standard input.
        !          1865:   ---------------------------------------------------------------------------*/
        !          1866: 
        !          1867:     status = sys$assign(&DevDesc, &DevChan, 0, 0);
        !          1868:     if (!(status & 1))
        !          1869:         return status;
        !          1870: 
        !          1871: /*---------------------------------------------------------------------------
        !          1872:     Use sys$qio and the IO$_SENSEMODE function to determine the current tty
        !          1873:     status (for password reading, could use IO$_READVBLK function instead,
        !          1874:     but echo on/off will be more general).
        !          1875:   ---------------------------------------------------------------------------*/
        !          1876: 
        !          1877:     status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
        !          1878:                      oldmode, 8, 0, 0, 0, 0);
        !          1879:     if (!(status & 1))
        !          1880:         return status;
        !          1881:     status = iosb[0];
        !          1882:     if (!(status & 1))
        !          1883:         return status;
        !          1884: 
        !          1885: /*---------------------------------------------------------------------------
        !          1886:     Copy old mode into new-mode buffer, then modify to be either NOECHO or
        !          1887:     ECHO (depending on function argument opt).
        !          1888:   ---------------------------------------------------------------------------*/
        !          1889: 
        !          1890:     newmode[0] = oldmode[0];
        !          1891:     newmode[1] = oldmode[1];
        !          1892:     if (opt == 0)
        !          1893:         newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
        !          1894:     else
        !          1895:         newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
        !          1896: 
        !          1897: /*---------------------------------------------------------------------------
        !          1898:     Use the IO$_SETMODE function to change the tty status.
        !          1899:   ---------------------------------------------------------------------------*/
        !          1900: 
        !          1901:     status = sys$qio(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
        !          1902:                      newmode, 8, 0, 0, 0, 0);
        !          1903:     if (!(status & 1))
        !          1904:         return status;
        !          1905:     status = iosb[0];
        !          1906:     if (!(status & 1))
        !          1907:         return status;
        !          1908: 
        !          1909: /*---------------------------------------------------------------------------
        !          1910:     Deassign the sys$input channel by way of clean-up, then exit happily.
        !          1911:   ---------------------------------------------------------------------------*/
        !          1912: 
        !          1913:     status = sys$dassgn(DevChan);
        !          1914:     if (!(status & 1))
        !          1915:         return status;
        !          1916: 
        !          1917:     return SS$_NORMAL;   /* we be happy */
        !          1918: 
        !          1919: } /* end function echo() */
        !          1920: 
        !          1921: 
        !          1922: #else /* !VMS */
        !          1923: 
        !          1924: local int echofd = -1;  /* file descriptor whose echo is off */
        !          1925: 
        !          1926: void echoff(f)
        !          1927: int f;                  /* file descriptor to turn echo off on */
        !          1928: /* Turn echo off for file descriptor f.  Assumes that f is a tty device. */
        !          1929: {
        !          1930:   struct sgttyb sg;     /* tty device structure */
        !          1931: 
        !          1932:   echofd = f;
        !          1933:   GTTY(f, &sg);                                 /* get settings */
        !          1934:   sg.sg_flags &= ~ECHO;                         /* turn echo off */
        !          1935:   STTY(f, &sg);
        !          1936: }
        !          1937: 
        !          1938: void echon()
        !          1939: /* Turn echo back on for file descriptor echofd. */
        !          1940: {
        !          1941:   struct sgttyb sg;     /* tty device structure */
        !          1942: 
        !          1943:   if (echofd != -1)
        !          1944:   {
        !          1945:     GTTY(echofd, &sg);                          /* get settings */
        !          1946:     sg.sg_flags |= ECHO;                        /* turn echo on */
        !          1947:     STTY(echofd, &sg);
        !          1948:     echofd = -1;
        !          1949:   }
        !          1950: }
        !          1951: 
        !          1952: #endif /* ?VMS */
        !          1953: 
        !          1954: #endif /* !MSDOS */
        !          1955: 
        !          1956: 
        !          1957: char *getp(m, p, n)
        !          1958: char *m;                /* prompt for password */
        !          1959: char *p;                /* return value: line input */
        !          1960: int n;                  /* bytes available in p[] */
        !          1961: /* Get a password of length n-1 or less into *p using the prompt *m.
        !          1962:    The entered password is not echoed.  Return p on success, NULL on
        !          1963:    failure (can't get controlling tty). */
        !          1964: {
        !          1965:   char c;               /* one-byte buffer for read() to use */
        !          1966:   int i;                /* number of characters input */
        !          1967:   char *w;              /* warning on retry */
        !          1968: 
        !          1969: #ifndef MSDOS
        !          1970: #ifndef VMS
        !          1971:   int f;                /* file decsriptor for tty device */
        !          1972: 
        !          1973:   /* Turn off echo on tty */
        !          1974:   if (!isatty(2))
        !          1975:     return NULL;                                /* error if not tty */
        !          1976:   if ((f = open(ttyname(2), 0, 0)) == -1)
        !          1977:     return NULL;
        !          1978: #endif /* !VMS */
        !          1979:   echoff(f);                                    /* turn echo off */
        !          1980: #endif /* !MSDOS */
        !          1981: 
        !          1982:   /* Get password */
        !          1983:   w = "";
        !          1984:   do {
        !          1985: #ifdef VMS   /* bug:  VMS adds '\n' to NULL fputs (apparently) */
        !          1986:     if (*w)
        !          1987: #endif /* VMS */
        !          1988:     fputs(w, stderr);                           /* warning if back again */
        !          1989:     fputs(m, stderr);                           /* prompt */
        !          1990:     fflush(stderr);
        !          1991:     i = 0;
        !          1992:     do {                                        /* read line, keeping n */
        !          1993: #ifdef MSVMS
        !          1994:       if ((c = (char)getch()) == '\r')
        !          1995:         c = '\n';
        !          1996: #else /* !MSVMS */
        !          1997:       read(f, &c, 1);
        !          1998: #endif /* ?MSVMS */
        !          1999:       if (i < n)
        !          2000:         p[i++] = c;
        !          2001:     } while (c != '\n');
        !          2002:     putc('\n', stderr);  fflush(stderr);
        !          2003:     w = "(line too long--try again)\n";
        !          2004:   } while (p[i-1] != '\n');
        !          2005:   p[i-1] = 0;                                   /* terminate at newline */
        !          2006: 
        !          2007: #ifndef MSDOS
        !          2008:   echon();                                      /* turn echo back on */
        !          2009: #ifndef VMS
        !          2010:   close(f);
        !          2011: #endif /* !VMS */
        !          2012: #endif /* !MSDOS */
        !          2013: 
        !          2014:   /* Return pointer to password */
        !          2015:   return p;
        !          2016: }
        !          2017: 
        !          2018: #endif /* ?CRYPT */
        !          2019: 
        !          2020: 
        !          2021: #ifdef ZMEM
        !          2022: 
        !          2023: /************************/
        !          2024: /*  Function memset()  */
        !          2025: /************************/
        !          2026: 
        !          2027: /*
        !          2028:  * memset - for systems without it
        !          2029:  *  bill davidsen - March 1990
        !          2030:  */
        !          2031: 
        !          2032: char *
        !          2033: memset(buf, init, len)
        !          2034: register char *buf;     /* buffer loc */
        !          2035: register int init;      /* initializer */
        !          2036: register unsigned int len;   /* length of the buffer */
        !          2037: {
        !          2038:     char *start;
        !          2039: 
        !          2040:     start = buf;
        !          2041:     while (len--) *(buf++) = init;
        !          2042:     return(start);
        !          2043: }
        !          2044: 
        !          2045: 
        !          2046: /************************/
        !          2047: /*  Function memcpy()  */
        !          2048: /************************/
        !          2049: 
        !          2050: char *
        !          2051: memcpy(dst,src,len)           /* v2.0f */
        !          2052: register char *dst, *src;
        !          2053: register unsigned int len;
        !          2054: {
        !          2055:     char *start;
        !          2056: 
        !          2057:     start = dst;
        !          2058:     while (len--)
        !          2059:         *dst++ = *src++;
        !          2060:     return(start);
        !          2061: }
        !          2062: 
        !          2063: 
        !          2064: /************************/
        !          2065: /*  Function memcmp()  */
        !          2066: /************************/
        !          2067: 
        !          2068: int
        !          2069: memcmp(b1,b2,len)                     /* [email protected] -- 11/16/90 */
        !          2070: register char *b1, *b2;
        !          2071: register unsigned int len;
        !          2072: {
        !          2073: 
        !          2074:     if (len) do {             /* examine each byte (if any) */
        !          2075:       if (*b1++ != *b2++)
        !          2076:         return (*((uch *)b1-1) - *((uch *)b2-1));  /* exit when miscompare */
        !          2077:        } while (--len);
        !          2078: 
        !          2079:     return(0);        /* no miscompares, yield 0 result */
        !          2080: }
        !          2081: 
        !          2082: #endif  /* ZMEM */
        !          2083: 
        !          2084: #ifdef __TURBOC__
        !          2085: 
        !          2086: /************************/
        !          2087: /*  Function fcalloc()  */
        !          2088: /************************/
        !          2089: 
        !          2090: /* Turbo C malloc() does not allow dynamic allocation of 64K bytes
        !          2091:  * and farmalloc(64K) returns a pointer with an offset of 8, so we
        !          2092:  * must fix the pointer. Warning: the pointer must be put back to its
        !          2093:  * original form in order to free it.
        !          2094:  * For MSC, use halloc instead of this function (see tailor.h).
        !          2095:  */
        !          2096: void far * fcalloc(items, size)
        !          2097:     unsigned items; /* number of items */
        !          2098:     unsigned size;  /* item size */
        !          2099: {
        !          2100:     void far * buf = farmalloc((ulg)items*size + 16L);
        !          2101:     /* Normalize the pointer to seg:0 */
        !          2102:     *((int*)&buf+1) += ((unsigned)((uch*)buf-0) + 15) >> 4;
        !          2103:     *(int*)&buf = 0;
        !          2104:     return buf; /* buf stays NULL if alloc failed */
        !          2105: }
        !          2106: 
        !          2107: #endif /* __TURBOC__ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.