Annotation of coherent/b/bin/zip/fileio.c, revision 1.1.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.