|
|
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__ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.