home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / zoo / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-08-16  |  36.0 KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i012:  File archive program, Part03/07
  5. Message-ID: <967@uunet.UU.NET>
  6. Date: 18 Aug 87 02:01:12 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1121
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: iuvax!bsu-cs!dhesi@seismo.CSS.GOV (Rahul Dhesi)
  12. Posting-number: Volume 11, Issue 12
  13. Archive-name: zoo/Part03
  14.  
  15. #! /bin/sh
  16. #
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create:
  21. #    needed.c
  22. #    nextfile.c
  23. #    nixtime.i
  24. #    options.c
  25. #    options.h
  26. #    parse.c
  27. #    parse.h
  28. export PATH; PATH=/bin:/usr/bin:$PATH
  29. if test -f 'needed.c'
  30. then
  31.     echo shar: "will not over-write existing file 'needed.c'"
  32. else
  33. sed 's/^X//' << \SHAR_EOF > 'needed.c'
  34. X#ifndef LINT
  35. Xstatic char sccsid[]="@(#) needed.c 1.6 87/05/29 12:54:43";
  36. X#endif /* LINT */
  37. X
  38. X/*
  39. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  40. X*/
  41. X#include "options.h"
  42. X/* Accepts a filename from an archive and returns 1 if a command-line
  43. X   argument filename matches it.  Otherwise returns 0. Returns
  44. X   1 if no arguments were supplied (so by default, all files will
  45. X   be extracted */
  46. X
  47. X#include "zoo.h"
  48. X
  49. X#ifdef NEEDCTYP
  50. X#include <ctype.h>              /* for tolower() */
  51. X#endif
  52. X
  53. X#include <stdio.h>               /* solely to define NULL */
  54. X#include "various.h"
  55. X#include "zoofns.h"
  56. X#include "debug.h"
  57. X
  58. Xextern int next_arg;          /* filenames start at this position */
  59. Xextern int arg_count;         /* count of arguments supplied to program */
  60. Xextern char **arg_vector;     /* vector of arguments supplied to program */
  61. X/* Uses FIRST_ARG in zoo.h, so must be recompiled when switching
  62. X   between Ooz and Zoo */
  63. X
  64. Xint needed(pathname)
  65. Xchar *pathname;
  66. X{
  67. X   register int i;
  68. X   register char *arg;
  69. X   char *justname;
  70. X
  71. X   if (arg_count <= FIRST_ARG)         /* if no filenames supplied */
  72. X      return (1);                       /* .. then all files are needed */
  73. X    justname = nameptr(pathname);            /* filename without any pathname */
  74. X
  75. X   /* count backwards and stop if '+' is encountered */
  76. X   for (i = arg_count-1;  i >= next_arg; i--) {
  77. X      arg = arg_vector[i];
  78. X#ifdef FOLD
  79. X      strlwr(pathname); strlwr(arg);
  80. X#endif
  81. X      if (strcmp(arg,"+") == 0)
  82. X         return (0);
  83. X
  84. X      /* If the argument contains a slash, the match fails if the
  85. X         path prefixes don't match */
  86. X      if (strchr(arg, *PATH_CH) != NULL) {      /* found slash */
  87. X         char *p;
  88. X         char arg_prefix[PATHSIZE];
  89. X         char path_prefix[PATHSIZE];
  90. X         strcpy(arg_prefix,arg);
  91. X         strcpy(path_prefix,pathname);
  92. X         p = findlast(arg_prefix, PATH_CH);
  93. X         if (p != NULL)
  94. X            *p = '\0';
  95. X         p = findlast(path_prefix, PATH_CH);
  96. X         if (p != NULL)
  97. X            *p = '\0';
  98. X         if (!match_half(path_prefix, arg_prefix)) {
  99. X            continue;                     /* no match this time in loop */
  100. X         }
  101. X      }
  102. X
  103. X      /*
  104. X      We reach here either if the pattern had no slashes, or if it
  105. X      had a slash but the path prefixes matched.  Now we test to see 
  106. X      if the filename parts match.
  107. X      */
  108. X      if (match_half (justname, nameptr(arg)))
  109. X         return (1);
  110. X
  111. X      /* try for a character range */
  112. X      if (match_half (arg, "?-?")) {             /* character range given */
  113. X         if (arg[0] <= *justname && arg[2] >= *justname)
  114. X            return (1);
  115. X      }
  116. X   }
  117. X   return (0);
  118. X
  119. X} /* needed */
  120. X
  121. X/***********************/
  122. X/*
  123. Xmatch_half() compares a pattern with a string.  Wildcards accepted in
  124. Xthe pattern are:  "*" for zero or more arbitrary characters;  "?"
  125. Xfor any one characters.  Unlike the MS-DOS wildcard match, "*" is
  126. Xcorrectly handled even if it isn't at the end of the pattern. ".'
  127. Xis not special.
  128. X
  129. XOriginally written by Jeff Damens of Columbia University Center for
  130. XComputing Activities.  Taken from the source code for C-Kermit version
  131. X4C.
  132. X*/
  133. X
  134. Xint match_half (string, pattern) 
  135. Xregister char *string, *pattern;
  136. X{
  137. X   char *psave,*ssave;        /* back up pointers for failure */
  138. X   psave = ssave = NULL;
  139. X   while (1) {
  140. X#ifdef IGNORECASE
  141. X      for (; 
  142. X         tolower(*pattern) == tolower(*string); 
  143. X         pattern++,string++                        )  /* skip first */
  144. X#else
  145. X      for (; *pattern == *string; pattern++,string++)  /* skip first */
  146. X#endif /* IGNORECASE */
  147. X
  148. X         if (*string == '\0') 
  149. X            return(1);                          /* end of strings, succeed */
  150. X      if (*string != '\0' && *pattern == '?') {
  151. X         pattern++;                             /* '?', let it match */
  152. X         string++;
  153. X      } else if (*pattern == '*') {             /* '*' ... */
  154. X         psave = ++pattern;                     /* remember where we saw it */
  155. X         ssave = string;                        /* let it match 0 chars */
  156. X      } else if (ssave != NULL && *ssave != '\0') {   /* if not at end  */
  157. X         /* ...have seen a star */
  158. X         string = ++ssave;                      /* skip 1 char from string */
  159. X         pattern = psave;                       /* and back up pattern */
  160. X      } else 
  161. X         return(0);                             /* otherwise just fail */
  162. X   }
  163. X}
  164. X
  165. SHAR_EOF
  166. fi
  167. if test -f 'nextfile.c'
  168. then
  169.     echo shar: "will not over-write existing file 'nextfile.c'"
  170. else
  171. sed 's/^X//' << \SHAR_EOF > 'nextfile.c'
  172. X#ifndef LINT
  173. Xstatic char sccsid[]="@(#) nextfile.c 1.4 87/05/29 12:54:55";
  174. X#endif /* LINT */
  175. X
  176. X#include "options.h"
  177. X/*
  178. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  179. X*/
  180. X/*
  181. XFunctions to collect filenames from command line etc.  Nextfile() is
  182. Xused by both Atoz and Zoo.  Wildcard expansion by nextfile() is specific to 
  183. XMS-DOS and this implementation is specific to Microsoft C.  If the symbol 
  184. XPORTABLE is defined, nextfile() becomes effectively a no-op that will return
  185. Xthe original filespec the first time and NULL subsequently.
  186. X*/
  187. X
  188. X#define  FMAX  3        /* Number of different filename patterns */
  189. X
  190. X#include <stdio.h>      /* solely to define NULL */
  191. X#include "various.h"
  192. X#include "zoo.h"        /* solely to define PATHSIZE */
  193. X
  194. X#ifdef PORTABLE
  195. X#ifndef SPECNEXT
  196. X/* If portable version, nextfile() is effectively a no-op and any wildcard
  197. Xexpansion must be done by the runtime system before the command line
  198. Xis received by this program
  199. X*/
  200. Xchar *nextfile (what, filespec, fileset)
  201. Xint what;                        /* whether to initialize or match      */
  202. Xregister char *filespec;         /* filespec to match if initializing   */
  203. Xregister int fileset;            /* which set of files                  */
  204. X{
  205. X   static int first_time [FMAX+1];
  206. X   static char saved_fspec [FMAX+1][PATHSIZE];  /* our own copy of filespec */
  207. X
  208. X   if (what == 0) {
  209. X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
  210. X      first_time[fileset] = 1;
  211. X      return (NULL);
  212. X   }
  213. X
  214. X   if (first_time[fileset]) {
  215. X      first_time[fileset] = 0;
  216. X      return (saved_fspec[fileset]);
  217. X   } else {
  218. X      return (NULL);
  219. X   }
  220. X}
  221. X#endif /* SPECNEXT */
  222. X#else
  223. X/* if not PORTABLE  then */
  224. X
  225. X#include "intdos.h"     /* registers for MS-DOS interrupts              */
  226. X#include "dta.h"        /* format of MS-DOS disk transfer area (dta)    */
  227. X#include "assert.h"     /* macro definition:  assert() macro            */
  228. X
  229. Xvoid setdta (struct dta_t *);
  230. Xvoid fcbpath (struct dta_t *, char *, char *);
  231. X
  232. X
  233. X/*******************/
  234. X/*
  235. Xnextfile() returns the name of the next source file matching a filespec.
  236. X
  237. XINPUT
  238. X   what: A flag specifying what to do.  If "what" is 0, nextfile() 
  239. X      initializes itself.  If "what" is 1, nextfile() returns the next 
  240. X      matching filename.  
  241. X   filespec:  The filespec, usually containing wildcard characters, that 
  242. X      specifies which files are needed.  If "what" is 0, filespec must be 
  243. X      the filespec for which matching filenames are needed.  If "what" is 1, 
  244. X      nextfile() does not use "filespec" and "filespec" should be NULL to 
  245. X      avoid an assertion error during debugging.
  246. X   fileset:  nextfile() can keep track of more than one set of filespecs.
  247. X      The fileset specifies which filespec is being matched and therefore
  248. X      which set of files is being considered.  "fileset" can be in the
  249. X      range 0:FMAX.  Initialization of one fileset does not affect the
  250. X      other filesets.
  251. X
  252. XOUTPUT
  253. X   IF what == 0 THEN
  254. X      return value is NULL
  255. X   ELSE IF what == 1 THEN
  256. X      IF a matching filename is found THEN
  257. X         return value is pointer to matching filename including supplied path
  258. X      ELSE
  259. X         IF at least one file matched previously but no more match THEN
  260. X            return value is NULL
  261. X         ELSE IF supplied filespec never matched any filename THEN
  262. X            IF this is the first call with what == 1 THEN
  263. X               return value is pointer to original filespec
  264. X            ELSE
  265. X               return value is NULL
  266. X            END IF
  267. X         END IF
  268. X      END IF
  269. X   END IF
  270. X
  271. XNOTE
  272. X
  273. X   Initialization done when "what"=0 is not dependent on the correctness
  274. X   of the supplied filespec but simply initializes internal variables
  275. X   and makes a local copy of the supplied filespec.  If the supplied
  276. X   filespec was illegal, the only effect is that the first time that
  277. X   nextfile() is called with "what"=1, it will return the original 
  278. X   filespec instead of a matching filename.  That the filespec was
  279. X   illegal will become obvious when the caller attempts to open the
  280. X   returned filename for input/output and the open attempt fails.
  281. X
  282. XUSAGE HINTS
  283. X
  284. Xnextfile() can be used in the following manner:
  285. X
  286. X      char *filespec;                  -- will point to filespec
  287. X      char *this_file;                 -- will point to matching filename
  288. X      filespec = parse_command_line(); -- may contain wildcards
  289. X      FILE *stream;
  290. X   
  291. X      nextfile (0, filespec, 0);          -- initialize fileset 0
  292. X      while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
  293. X         stream = fopen (this_file, "whatever");
  294. X         if (stream == NULL)
  295. X            printf ("could not open %s\n", this_file);
  296. X         else
  297. X            perform_operations (stream);
  298. X      }
  299. X*/             
  300. X               
  301. Xchar *nextfile (what, filespec, fileset)
  302. Xint what;                        /* whether to initialize or match      */
  303. Xregister char *filespec;         /* filespec to match if initializing   */
  304. Xregister int fileset;            /* which set of files                  */
  305. X{
  306. X   static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
  307. X   static int first_time [FMAX+1];
  308. X   static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
  309. X   static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
  310. X   union REGS regs;
  311. X
  312. X   assert(fileset >= 0 && fileset <= FMAX);
  313. X   if (what == 0) {
  314. X      assert(filespec != NULL);
  315. X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
  316. X      first_time[fileset] = 1;
  317. X      return (NULL);
  318. X   }
  319. X
  320. X   setdta (&new_dta[fileset]);   /* set new dta -- our very own */      
  321. X   assert(what == 1);
  322. X   assert(filespec == NULL);
  323. X   assert(first_time[fileset] == 0 || first_time[fileset] == 1);
  324. X
  325. X   if (first_time[fileset]) {             /* first time -- initialize etc. */
  326. X      /* find first matching file */
  327. X      regs.h.ah = 0x4e;                   /* FindFirst DOS call      */
  328. X      regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
  329. X      regs.x.cx = 0;                      /* search attributes       */
  330. X      intdos (®s, ®s);
  331. X   } else {
  332. X      /* find next matching file */
  333. X      regs.h.ah = 0x4f;                   /* FindNext DOS call       */
  334. X      intdos (®s, ®s);
  335. X   }
  336. X
  337. X   if (regs.x.carry != 0) {            /* if error status                  */
  338. X      if (first_time[fileset]) {       /*   if file never matched then     */
  339. X         first_time[fileset] = 0;
  340. X         return (saved_fspec[fileset]);/*      return original filespec    */
  341. X      } else {                         /*   else                           */
  342. X         first_time[fileset] = 0;      /*                                  */
  343. X         return (NULL);                /*      return (NULL) for no more   */
  344. X      }
  345. X   } else {                                        /* a file matched */
  346. X      first_time[fileset] = 0;         
  347. X      /* add path info  */
  348. X      fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]); 
  349. X      return (pathholder[fileset]);                /* matching path  */
  350. X   }
  351. X} /* nextfile */
  352. X
  353. X/*******************/
  354. X/* This function sets the dta to a new dta */
  355. Xvoid setdta (dta)
  356. Xstruct dta_t *dta;
  357. X{
  358. X   union REGS regs;
  359. X   regs.h.ah = 0x1a;                /* SetDTA Call       */
  360. X   regs.x.dx = (unsigned int) dta;  /* new DTA address   */
  361. X   intdos (®s, ®s);
  362. X}
  363. X
  364. X/*******************/
  365. X/* 
  366. Xfcbpath() accepts a pointer to the Disk Transfer Area (the DTA format is
  367. Xdescribed on page 131 of Tandy-1000 programmers reference manual), a
  368. Xcharacter pointer to a pathname that may contain wildcards, and a character
  369. Xpointer to a buffer.  Copies into buffer the path prefix from the pathname
  370. Xand the filename prefix from the DTA so that it forms a complete path
  371. X*/
  372. X
  373. Xvoid fcbpath (dta, old_path, new_path)
  374. Xstruct dta_t *dta;
  375. Xchar *old_path;
  376. Xregister char *new_path;
  377. X{
  378. X   register int i;
  379. X   int length, start_pos;
  380. X      
  381. X   strcpy(new_path, old_path);               /* copy the whole thing first */
  382. X   length = strlen(new_path);
  383. X   i = length - 1;                           /* i points to end of path */
  384. X   while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
  385. X      i--;
  386. X   /* either we found a "/", "\", or ":", or we reached the beginning of
  387. X      the name.  In any case, i points to the last character of the
  388. X      path part. */
  389. X   start_pos = i + 1;
  390. X   for (i = 0; i < 13; i++)
  391. X      new_path[start_pos+i] = dta->fname[i];
  392. X   new_path[start_pos+13] = '\0';
  393. X}
  394. X#endif /* PORTABLE */
  395. X
  396. SHAR_EOF
  397. fi
  398. if test -f 'nixtime.i'
  399. then
  400.     echo shar: "will not over-write existing file 'nixtime.i'"
  401. else
  402. sed 's/^X//' << \SHAR_EOF > 'nixtime.i'
  403. X#ifndef LINT
  404. Xstatic char nixtimeid[]="@(#) nixtime.i 1.2 87/05/03 16:00:16";
  405. X#endif /* LINT */
  406. X
  407. X/*
  408. XTime handling routines for UNIX systems.  These are included by the file
  409. Xmachine.c as needed.
  410. X
  411. XThe contents of this file are hereby released to the public domain.
  412. X
  413. X                                    -- Rahul Dhesi  1986/12/31
  414. X*/
  415. X
  416. Xstruct tm *localtime();
  417. X
  418. X/*****************
  419. XFunction gettime() gets the date and time of the file handle supplied.
  420. XDate and time is in MSDOS format.
  421. X*/
  422. Xgettime(handle,date,time)
  423. Xint handle, *date, *time;
  424. X{
  425. X   struct stat buf;           /* buffer to hold file information */
  426. X   struct tm *tm;             /* will hold year/month/day etc. */
  427. X   if (fstat (handle, &buf) == -1) {
  428. X      prterror ('w', "Could not get file time\n");
  429. X      *date = *time = 0;
  430. X   } else {
  431. X      tm = localtime (&buf.st_mtime); /* get info about file mod time */
  432. X      *date = tm->tm_mday + ((tm->tm_mon + 1) << 5) + 
  433. X         ((tm->tm_year - 80) << 9);
  434. X      *time = tm->tm_sec / 2 + (tm->tm_min << 5) +
  435. X         (tm->tm_hour << 11);
  436. X   }
  437. X
  438. X}
  439. X
  440. X/*****************
  441. XFunction setutime() sets the date and time of the filename supplied.
  442. XDate and time is in MSDOS format.  It assumes the existence of a function
  443. Xgettz() that returns the the difference (localtime - gmt) in seconds.
  444. X*/
  445. Xint setutime(path,date,time)
  446. Xchar *path;
  447. Xunsigned int date, time;
  448. X{
  449. X   int year, month, day, hour, min, sec, daycount;
  450. X   long longtime; 
  451. X   /* no. of days to beginning of month for each month */
  452. X   static int dsboy[12] = { 0, 31, 59, 90, 120, 151, 181, 212,
  453. X                              243, 273, 304, 334};
  454. X
  455. X   /* part of following code is common to zoolist.c -- if memory 
  456. X   space is tight, try to share the code */
  457. X   year  =  (((unsigned int) date >> 9) & 0x7f) + 1980;
  458. X   month =  ((unsigned int) date >> 5) & 0x0f;
  459. X   day   =  date        & 0x1f;
  460. X
  461. X   hour =  ((unsigned int) time >> 11)& 0x1f;
  462. X   min   =  ((unsigned int) time >> 5) & 0x3f;
  463. X   sec   =  ((unsigned int) time & 0x1f) * 2;
  464. X
  465. X#ifdef DEBUG
  466. X   printf (setutime:  "year=%d  month=%d  day=%d  hour=%d  min=%d  sec=%d\n",
  467. X           year, month, day, hour, min, sec);
  468. X#endif
  469. X
  470. X   /* Calculate days since 1970/01/01 */
  471. X   daycount = 365 * (year - 1970) +    /* days due to whole years */
  472. X               (year - 1970) / 4 +     /* days due to leap years */
  473. X               dsboy[month-1] +        /* days since beginning of this year */
  474. X               day-1;                  /* days since beginning of month */
  475. X
  476. X   if (year % 4 == 0 && 
  477. X       year % 400 != 0 && month >= 3)  /* if this is a leap year and month */
  478. X      daycount++;                      /* is March or later, add a day */
  479. X
  480. X   /* Knowing the days, we can find seconds */
  481. X   longtime = daycount * 24L * 60L * 60L    +
  482. X          hour * 60L * 60L   +   min * 60   +    sec;
  483. X
  484. X   longtime = longtime + gettz();      /* adjust for timezone */
  485. X
  486. X   /* special case:  if MSDOS format date and time were zero, then we set
  487. X   time to be zero here too. */
  488. X   if (date == 0 && time == 0)
  489. X      longtime = 0;
  490. X
  491. X   /* longtime is now the time of the file, in seconds, since
  492. X   1970/01/01 00:00:00.  Now we set both access and modification times */
  493. X   {
  494. X      long utimbuf[2];
  495. X      utimbuf[0] = utimbuf[1] = longtime;
  496. X      return (utime (path, utimbuf));
  497. X   }
  498. X}
  499. SHAR_EOF
  500. fi
  501. if test -f 'options.c'
  502. then
  503.     echo shar: "will not over-write existing file 'options.c'"
  504. else
  505. sed 's/^X//' << \SHAR_EOF > 'options.c'
  506. X#ifndef LINT
  507. Xstatic char sccsid[]="@(#) options.c 1.2 87/05/03 16:00:21";
  508. X#endif /* LINT */
  509. X
  510. X/*
  511. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  512. X*/
  513. X/*
  514. XHere we define routines specific to only a few systems.  Routines are
  515. Xselected based on defined symbols.  Routines specific to only one
  516. Xsystem are in machine.c for the appropriate system.
  517. X*/
  518. X
  519. X#include "options.h"
  520. X#include <stdio.h>
  521. X#include "various.h"
  522. X#include "zoo.h"
  523. X#include "zoofns.h"
  524. X#include "errors.i"
  525. X
  526. X#ifdef REN_LINK         
  527. X/* rename using link() followed by unlink() */
  528. X/* 
  529. XThe following code assumes that if unlink() returns nonzero, then the
  530. Xattempt to unlink failed.  If unlink() ever returns nonzero after actually
  531. Xunlinking the file, then the file being renamed will be lost!!!  Test this 
  532. Xthoroughly.  It is assumed that link() and unlink() return zero if no
  533. Xerror else nonzero.
  534. X*/
  535. Xint chname (newname, oldname)
  536. Xchar *newname, *oldname;
  537. X{
  538. X   int status;
  539. X   if (link (oldname, newname) == 0) { /* if we can create new name */
  540. X      status = unlink (oldname);          /*   unlink old one */
  541. X      if (status != 0) {                  /*   if unlink of old name failed */
  542. X         unlink (newname);                /*     cancel new link */
  543. X         return (-1);                     /*     return error */
  544. X      } else
  545. X         return (0);
  546. X   }
  547. X   else                    /* couldn't create new link */
  548. X      return (-1);
  549. X}
  550. X#else
  551. X/* else not REN_LINK */
  552. X
  553. Xint chname (newname, oldname)
  554. Xchar *newname, *oldname;
  555. X{
  556. X#ifdef REN_NORM
  557. X   if (rename(newname, oldname) != 0)     /* normal order */
  558. X#else
  559. X   if (rename(oldname, newname) != 0)     /* reverse order */
  560. X#endif
  561. X      return (-1);
  562. X   else
  563. X      return (0);
  564. X}
  565. X#endif /* end of not REN_LINK */
  566. X
  567. SHAR_EOF
  568. fi
  569. if test -f 'options.h'
  570. then
  571.     echo shar: "will not over-write existing file 'options.h'"
  572. else
  573. sed 's/^X//' << \SHAR_EOF > 'options.h'
  574. X/* @(#) options.h 1.16 87/05/03 16:00:25 */
  575. X
  576. X/*
  577. XThe contents of this file are hereby released to the public domain.
  578. X
  579. X                           -- Rahul Dhesi 1986/11/14
  580. X*/
  581. X
  582. X/* 
  583. XThis file defines various symbols and macros that are needed to ensure
  584. Xsystem-independence.  The basic philosophy is to use a distinct symbol for
  585. Xeach attribute that varies from machine to machine.  Then, for each new
  586. Xsystem, we define symbols corresponding to its attributes.  Thus, ideally,
  587. Xthe only place in Zoo code that we actually use the name of a machine is in
  588. Xthis file, portable.h, and possibly in machine.h and options.c.  Everywhere
  589. Xelse in the code we only use names of attributes.  If you need to define a
  590. Xnew machine name, please refer first to the guidelines in the implementor's 
  591. Xdocumentation.
  592. X
  593. XMachine names:
  594. X
  595. XMSC          Microsoft C under MS-DOS
  596. XDLC        Datalight C under MS-DOS
  597. XSYS_V        UNIX System V release 2.1
  598. XVMS          VAX/VMS 4.4
  599. XBSD4_3        4.3BSD
  600. XMCH_AMIGA     AmigaDOS with Aztec/Manx C compiler
  601. X
  602. XAttributes of systems:
  603. X
  604. XCHEKDIR
  605. X   Test each supplied filename and if it is a directory or other special
  606. X   type of file, do not try to add it to an archive.  If CHEKDIR is
  607. X   defined, then machine.c must also include function isadir() that
  608. X   tests a supplied handle and returns 1 if it corresponds to a
  609. X   directory or other special type of file.
  610. XCHEKUDIR
  611. X   Like CHEKDIR but use function isuadir() that tests a pathname, not
  612. X   a handle.  Only one of CHEKDIR, CHEKUDIR may be defined.
  613. XDISK_CH
  614. X    If defined, must hold the value of a character that separates a
  615. X   disk name from the rest of the pathname.  All characters up to and
  616. X   including this character will be removed from a pathname before it
  617. X   is stored in an archive.  Usually a colon (':').
  618. XEXISTS
  619. X    If defined, is assumed to be a macro that accepts a filename and
  620. X    returns an int value of 1 if the file exists and 0 if it doesn't.
  621. X   If not defined, existence of files is tested by attempting to open
  622. X   them for read or write access.
  623. XLINT_ARGS
  624. X   Use ANSI-style function argument lists in declarations
  625. XLINT
  626. X   If defined, SCCS identifier strings will not be included in the
  627. X   generated code.  This will make the code smaller and will also
  628. X   avoid complaints from lint about unused variables.  This symbol
  629. X   should be defined in the Makefile, NOT in `options.h', otherwise
  630. X   it will not be fully effective.
  631. XFLAT
  632. X   include files are all in one place (no sys/anything)
  633. XFOLD
  634. X   fold filenames to lowercase.  Define this for case-insensitive filesystems
  635. XFPUTCHAR
  636. X    If defined, a library function fputchar() is assumed available
  637. X    that is like fput() but is a function, not a macro, to save
  638. X    space.  If not defined Zoo uses its own fputchar() functio.
  639. XPORTABLE
  640. X   use portable functions --- define for every system except MS-DOS
  641. XPURIFY
  642. X   When filenames are being read from standard input, ignore all
  643. X   characters begining with the first blank or tab encountered.
  644. X   This will allow filenames to be fed from a program that produces
  645. X   lines containing filenames followed by other information that
  646. X   should be ignored.  Should be defined for most non-**IX systems.
  647. XDONT_SORT
  648. X   don't sort filename arguments -- files will be stored in the
  649. X   exact order in which names are supplied on the command line
  650. XNOENUM
  651. X   compiler does not support enumerations
  652. XDUMB_ASS
  653. X   dumb assertions must be used because the preprocessor doesn't define 
  654. X   the symbols __FILE__ and __LINE__  (which hold the name of the current
  655. X   file and the number of the current line)
  656. XFNLIMIT
  657. X   Pathname length limit for this system
  658. XNEEDCTYP
  659. X   the header file ctype.h is needed because functions such as tolower() are
  660. X   defined only as macros
  661. XNIXTIME
  662. X   If defined, a function setutime() must be defined that will set the
  663. X   date and time of a file whose pathname is supplied.  If not defined,
  664. X   a function settime() must be defined that will do the same for
  665. X   a file handle.
  666. XGETUTIME
  667. X   If defined, a function getutime() must be defined that will return
  668. X   the MS-DOS format date and time of the specified filename.  If this
  669. X   symbol is not defined, then a function gettime() must be defined
  670. X   that will do the same for a supplied handle instead of a filename.
  671. XNOFCNTL
  672. X   if defined, system expects "file.h" to be included rather than "fcntl.h"
  673. XNOSIGNAL
  674. X   don't use signals because library doesn't support them
  675. XPATH_CH
  676. X   the character that should separate the directory name from the filename
  677. X   in the listing of the contents of an archive.  String value.
  678. XPATH_SEP 
  679. X   the set of characters that may separate preceding directory/device 
  680. X   information from the filename.  String value.
  681. XEXT_SEP is the union of PATH_SEP and the set of characters separating a 
  682. X   filename extension from the rest of the filename.  String value.
  683. XEXT_CH
  684. X   character that separates base part of filename from extension.  Char value.
  685. XMEMSET
  686. X    If defined, a library function memset() is assumed available that 
  687. X    conforms to that available under System V.  If not defined, Zoo uses 
  688. X    its own memset() function.
  689. XEXT_DFLT
  690. X   default extension for archives.  String.  Usually ".zoo"
  691. XNIXFNAME
  692. X   if defined, PATH_CH, PATH_SEP, EXT_SEP, EXT_CH, and EXT_DFLT get defined 
  693. X   to conform to UNIX conventions and should not be separately defined
  694. XFORCESLASH
  695. X   if defined any backslashes in names of files will be converted to
  696. X   slashes before the files are added to an archive.  This is useful
  697. X   for MSDOS-like systems that accept both slashes and backslashes,
  698. X   since the standard archive format allows only slashes as directory
  699. X   separators.
  700. XREN_LINK
  701. X   rename a file by using link() followed by unlink() (e.g. Xenix, System V)
  702. XREN_NORM
  703. X   use normal rename function:  "int rename(new, old)" (e.g. Microsoft C)
  704. XREN_REV
  705. X   use reverse rename function:  "int rename(old, new)" (e.g. 4.3BSD)
  706. X   Note:  define exactly one of REN_LINK, REN_NORM, and REN_REV.
  707. XSETMODE
  708. X   change mode of standard output to binary when piping output, then change
  709. X   it back to text.  Macros MODE_BIN(handle) and MODE_TEXT(handle) must also
  710. X   be defined.
  711. XSETBUF
  712. X   Standard output should be set to be unbuffered so output shows up
  713. X   quickly.  Currently used only in Fiz, not in Zoo.
  714. XSPECNEXT
  715. X   If defined, a machine-dependent function nextfile() must be defined that
  716. X   will expand wildcards in a supplied pathname. If not defined, any 
  717. X   wildcard expansion must have been done before the command line parameters 
  718. X   are supplied to the program.
  719. XSTRLWR
  720. X    If defined, a library function strlwr() is assumed available that converts
  721. X    a supplied string to lowercase and returns a pointer it.  If not
  722. X    defined, Zoo uses its own strlwr() function.
  723. XTELL
  724. X    If defined, a library function tell() is assumed available that returns
  725. X    the current file pointer position for a file handle.  If not
  726. X    defined, Zoo uses its own tell() function.
  727. X*/
  728. X
  729. X/* ZOO is always defined currently */
  730. X#define ZOO
  731. X
  732. X#ifdef SYS_V
  733. X#define EXISTS(f)        (access(f, 00) == 0)
  734. X#define MEMSET
  735. X#define FNLIMIT 14
  736. X#define CHEKDIR
  737. X#define NIXTIME
  738. X#define NIXFNAME
  739. X#define NEEDCTYP
  740. X#define NOENUM
  741. X#define PORTABLE
  742. X#define REN_LINK
  743. X#define SETBUF
  744. X#endif
  745. X
  746. X#ifdef MSC
  747. X/* #define STRDUP */
  748. X/* #define FPUTCHAR */
  749. X/* #define TELL */
  750. X/* #define EXISTS(f)   (access(f, 00) == 0)  made code size bigger */
  751. X/* #define MEMSET */
  752. X/* #define STRLWR */
  753. X#define PURIFY
  754. X#define DISK_CH ':'
  755. X#define IGNORECASE
  756. X#define WILDCARD "*.*"
  757. X#define FOLD
  758. X#define FORCESLASH
  759. X#define FNLIMIT 12
  760. X#define NEEDCTYP
  761. X#define CUR_DIR "."
  762. X#define PATH_CH "/"
  763. X#define PATH_SEP ":/\\"
  764. X#define EXT_CH '.'
  765. X#define EXT_SEP  ":/\\."
  766. X#define EXT_DFLT ".zoo"
  767. X#define SETMODE
  768. X#define MODE_BIN(handle)      setmode(handle, O_BINARY)
  769. X#define MODE_TEXT(handle)     setmode(handle, O_TEXT)
  770. X#define LINT_ARGS
  771. X#define REN_NORM
  772. X
  773. X#ifdef  PORTABLE
  774. X#define SPECNEXT
  775. X#define NIXTIME
  776. X#endif
  777. X
  778. X#endif  /* MSC */
  779. X
  780. X#ifdef DLC
  781. X#define STRDUP
  782. X#define STRLWR
  783. X/* #define EXISTS */
  784. X#define NOSIGNAL
  785. X#define PURIFY
  786. X#define DISK_CH ':'
  787. X#define IGNORECASE
  788. X/* #define WILDCARD "*.*" */
  789. X#define FOLD
  790. X#define FORCESLASH
  791. X#define FNLIMIT 12
  792. X#define NEEDCTYP
  793. X#define CUR_DIR "."
  794. X#define PATH_CH "/"
  795. X#define PATH_SEP ":/\\"
  796. X#define EXT_CH '.'
  797. X#define EXT_SEP  ":/\\."
  798. X#define EXT_DFLT ".zoo"
  799. X#define SETMODE
  800. X/* #define LINT_ARGS */
  801. X#define REN_REV
  802. X#define SPECNEXT
  803. X#define NIXTIME
  804. X#endif    /* DLC */
  805. X
  806. X#ifdef BSD4_3
  807. X#define EXISTS(f)        (access(f, 00) == 0)
  808. X#define FNLIMIT 1023
  809. X#define CHEKDIR
  810. X#define NIXTIME
  811. X#define NIXFNAME
  812. X#define NEEDCTYP
  813. X#define PORTABLE
  814. X#define NOENUM
  815. X#define REN_REV
  816. X#define SETBUF
  817. X#endif
  818. X
  819. X#ifdef VMS
  820. X#define FNLIMIT 78
  821. X#define PATH_SEP ":]"
  822. X#define EXT_CH '.'
  823. X#define EXT_SEP ":]."
  824. X#define EXT_DFLT ".zoo"
  825. X#define NOENUM
  826. X#define FLAT
  827. X#define PORTABLE
  828. X#define DUMB_ASS
  829. X#define NOFCNTL
  830. X#endif
  831. X
  832. X#ifdef MCH_AMIGA
  833. X#define PURIFY
  834. X#define DISK_CH ':'
  835. X#define SPECNEXT
  836. X#define WILDCARD "*"
  837. X#define IGNORECASE
  838. X#define FNLIMIT 30
  839. X#define NEEDCTYP
  840. X#define CUR_DIR "."
  841. X#define PATH_CH "/"
  842. X#define PATH_SEP ":/"
  843. X#define EXT_CH   '.'
  844. X#define EXT_SEP  ":/."
  845. X#define EXT_DFLT ".zoo"
  846. X#define PORTABLE
  847. X#define NOSIGNAL
  848. X#define REN_REV
  849. X#define NOENUM
  850. X#define SETBUF
  851. X#define CHEKUDIR
  852. X#define GETUTIME
  853. X#define NIXTIME
  854. X#endif
  855. X
  856. X#ifdef NIXFNAME
  857. X#define CUR_DIR "."
  858. X#define PATH_CH "/"
  859. X#define PATH_SEP "/"
  860. X#define EXT_CH '.'
  861. X#define EXT_SEP  "/."
  862. X#define EXT_DFLT ".zoo"
  863. X#endif
  864. X
  865. X#ifdef GENERIC
  866. X/* #define SPECNEXT */
  867. X#define IGNORECASE
  868. X#define FNLIMIT 11
  869. X#define NEEDCTYP
  870. X#define CUR_DIR "."
  871. X#define PATH_CH "/"
  872. X#define PATH_SEP ":/"
  873. X#define EXT_CH   '.'
  874. X#define EXT_SEP  ":/."
  875. X#define EXT_DFLT ".zoo"
  876. X#define PORTABLE
  877. X#define NOSIGNAL
  878. X/* REN_LINK is UNIX-specific.  Can't find a generic rename() function */
  879. X#define REN_LINK
  880. X/* #define FLAT */
  881. X#define NOENUM
  882. X#define SETBUF
  883. X#define CHEKUDIR
  884. X#define GETUTIME
  885. X#define NIXTIME
  886. X#endif
  887. SHAR_EOF
  888. fi
  889. if test -f 'parse.c'
  890. then
  891.     echo shar: "will not over-write existing file 'parse.c'"
  892. else
  893. sed 's/^X//' << \SHAR_EOF > 'parse.c'
  894. X#ifndef LINT
  895. Xstatic char sccsid[]="@(#) parse.c 1.10 87/05/29 12:55:08";
  896. X#endif /* LINT */
  897. X
  898. X/*
  899. XThe contents of this file are hereby released to the public domain.
  900. X
  901. X                                 -- Rahul Dhesi 1986/11/14
  902. X
  903. X*/
  904. X
  905. X#include "options.h"
  906. X#include "zoo.h"
  907. X#include <stdio.h>
  908. X#include "various.h"
  909. X#include "zoofns.h"
  910. X
  911. X#include "parse.h"
  912. X#include "assert.h"
  913. X
  914. X/*
  915. Xparse() accepts a filename and return its component parts in a structure.
  916. XThe component parts are:  disk drive, path prefix, root name of filename, 
  917. Xand extension.  
  918. X
  919. XIf DISK_CH is not defined, it is assumed that filenames may be
  920. Xpreceded with a disk prefix terminated by the character DISK_CH.
  921. XThe first character of the disk prefix, followed by DISK_CH,
  922. Xis returned in the drive field.
  923. X
  924. XIf the symbol DISK_CH is defined, a null string is returned in the
  925. Xdisk field.
  926. X*/
  927. Xvoid parse (path_st, fname)
  928. Xregister struct path_st *path_st;
  929. Xchar *fname;
  930. X{
  931. X   char tempname[LFNAMESIZE];       /* working copy of supplied fname */
  932. X   char *namep;                   /* points to relevant part of tempname */
  933. X
  934. X   char *p;
  935. X   strcpy (tempname, fname);
  936. X
  937. X#ifdef DEBUG
  938. Xprintf ("parse:  supplied name is [%s].\n", tempname);
  939. X#endif
  940. X
  941. X#ifndef DISK_CH
  942. X   path_st->drive[0] = '\0';
  943. X   namep = tempname;           /* points to pathname+filename */
  944. X#else
  945. X   path_st->drive[0] = '\0';
  946. X   p = strchr (tempname, DISK_CH);      /* point to first ':' */
  947. X
  948. X   if (p != NULL) {
  949. X      path_st->drive[0] = *tempname;/* use only first char of drive name */
  950. X      path_st->drive[1] = DISK_CH;
  951. X      path_st->drive[2] = '\0';
  952. X      namep = ++p;                /* point to pathname+filename */
  953. X   } else {
  954. X      path_st->drive[0] = '\0';
  955. X      namep = tempname;           /* points to pathname+filename */
  956. X   }
  957. X#endif /* end of not DISK_CH */
  958. X   
  959. X   /* Note:  findlast() finds last occurrence in the subject string of 
  960. X      any one of a set of chars */
  961. X
  962. X   /* save the long filename */
  963. X   p = findlast (namep, PATH_SEP);
  964. X
  965. X   /* if path separator found, copy next char onwards; else entire string */
  966. X   strncpy (path_st->lfname,
  967. X               (p != NULL) ? p+1 : namep,
  968. X               LFNAMESIZE);
  969. X   path_st->lfname[LFNAMESIZE-1] = '\0';     /* force null termination */
  970. X
  971. X#ifdef DEBUG
  972. Xprintf ("parse:  path = [%s] long filename = [%s]\n", 
  973. X         namep, path_st->lfname);
  974. X#endif
  975. X
  976. X/* Separate out the extension */
  977. Xp = findlast (namep, EXT_SEP);                        /* look for . or /        */
  978. Xif (p != NULL && *p != EXT_CH)                        /* found .?                    */
  979. X    p = NULL;                                                /* ... if not, ignore / */
  980. X
  981. X#ifdef DEBUG
  982. Xif (p == NULL)
  983. X   printf ("parse:  no extension found for [%s]\n", namep);
  984. Xelse
  985. X   printf ("parse:  extension for [%s] is [%s]\n", namep, p);
  986. X#endif
  987. X   
  988. X   path_st->ext[0] = '\0';                      /* assume no extension  */
  989. X   if (p != NULL) {                             /* found extension      */
  990. X      strncpy (path_st->ext, (p+1), EXTLEN);    /* save extension       */
  991. X      path_st->ext[EXTLEN] = '\0';              /* force termination    */
  992. X      *p = '\0';                                /* null out extension   */
  993. X   }
  994. X
  995. X   /* separate out root of filename if any */
  996. X   p = findlast (namep, PATH_SEP);
  997. X
  998. X   if (p != NULL) {
  999. X      ++p;
  1000. X      strncpy (path_st->fname, p, ROOTSIZE);  /* save filename        */
  1001. X      *p = '\0';               /* null out filename */
  1002. X   } else {
  1003. X      strncpy (path_st->fname, namep, ROOTSIZE);
  1004. X      *namep = '\0';                   /* null out filename    */
  1005. X   }
  1006. X   path_st->fname[ROOTSIZE] = '\0';           /* force termination    */
  1007. X
  1008. X   /* what remains, whether null or not, is the path prefix */
  1009. X   path_st->dir[0] = '\0';             /* in case *namep is '\0' */
  1010. X
  1011. X   strncpy (path_st->dir, namep, PATHSIZE);
  1012. X
  1013. X   /* remove trailing path-separater from directory name, but don't
  1014. X      remove it if it is also the leading separater */
  1015. X   { 
  1016. X      int n;
  1017. X      n = strlen(path_st->dir);
  1018. X      if (n != 1)
  1019. X         path_st->dir[n-1] = '\0';
  1020. X   }
  1021. X
  1022. X#ifdef DEBUG
  1023. Xprintf ("parse:  path prefix = [%s].\n", namep);
  1024. X#endif
  1025. X   /* if extension is null, and if long filename contains more than
  1026. X      ROOTSIZE  characters, transfer some of them to extension */
  1027. X   if (path_st->ext[0] == '\0' && strlen(path_st->lfname) > ROOTSIZE) {
  1028. X      strncpy(path_st->ext, &path_st->lfname[ROOTSIZE], EXTLEN);
  1029. X      path_st->ext[3] = '\0';
  1030. X   }
  1031. X}
  1032. X
  1033. X/*******************/
  1034. X/* 
  1035. Xfindlast() finds last occurrence in provided string of any of the characters
  1036. Xexcept the null character in the provided set.
  1037. X
  1038. XIf found, return value is pointer to character found, else it is NULL.
  1039. X*/
  1040. X
  1041. Xchar *findlast (str, set)
  1042. Xregister char *str;        /* subject string     */
  1043. Xchar *set;                 /* set of characters to look for */
  1044. X
  1045. X{
  1046. X   register char *p;
  1047. X
  1048. X   if (str == NULL || set == NULL || *str == '\0' || *set == '\0')
  1049. X      return (NULL);
  1050. X
  1051. X   p = lastptr (str);   /* pointer to last char of string */
  1052. X   assert(p != NULL);
  1053. X
  1054. X   while (p != str && strchr (set, *p) == NULL) {
  1055. X      --p;
  1056. X   }                 
  1057. X
  1058. X   /* either p == str or we found a character or both */
  1059. X   if (strchr (set, *p) == NULL)
  1060. X      return (NULL);
  1061. X   else
  1062. X      return (p);
  1063. X}
  1064. X
  1065. X/*******************/
  1066. X/*
  1067. Xlastptr() returns a pointer to the last non-null character in the string, if
  1068. Xany.  If the string is null it returns NULL
  1069. X*/
  1070. X
  1071. Xchar *lastptr (str)
  1072. Xregister char *str;                 /* string in which to find last char */
  1073. X{
  1074. X   register char *p;
  1075. X   if (str == NULL)
  1076. X      prterror ('f', "lastptr:  received null pointer\n");
  1077. X   if (*str == '\0')
  1078. X      return (NULL);
  1079. X   p = str;
  1080. X   while (*p != '\0')            /* find trailing null char */
  1081. X      ++p;
  1082. X   --p;                          /* point to just before it */
  1083. X   return (p);
  1084. X}
  1085. SHAR_EOF
  1086. fi
  1087. if test -f 'parse.h'
  1088. then
  1089.     echo shar: "will not over-write existing file 'parse.h'"
  1090. else
  1091. sed 's/^X//' << \SHAR_EOF > 'parse.h'
  1092. X/* @(#) parse.h 1.2 87/05/03 16:01:02 */
  1093. X
  1094. X/*
  1095. XThe contents of this file are hereby released to the public domain.
  1096. X
  1097. X                           -- Rahul Dhesi 1986/11/14
  1098. X*/
  1099. X
  1100. X/*
  1101. Xdefines structure used in call to parse()
  1102. X*/
  1103. X#define XTRA  2         /* extra space to avoid off-by-one errors */
  1104. X
  1105. X
  1106. Xstruct path_st {
  1107. X   char drive[2+1+XTRA];            /* drive name            */
  1108. X   char dir[PATHSIZE+1+XTRA];       /* path prefix           */
  1109. X   char fname[8+1+XTRA];            /* root name of filename */
  1110. X   char lfname[LFNAMESIZE+1+XTRA];  /* long filename    */
  1111. X   char ext[EXTLEN+1+XTRA];         /* extension        */
  1112. X};
  1113. X
  1114. X#ifdef LINT_ARGS
  1115. Xvoid parse (struct path_st *, char *);
  1116. X#else
  1117. Xvoid parse();
  1118. X#endif
  1119. X
  1120. SHAR_EOF
  1121. fi
  1122. exit 0
  1123. #    End of shell archive
  1124. -- 
  1125. Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
  1126.  
  1127. -- 
  1128.  
  1129. Rich $alz
  1130. Cronus Project, BBN Labs            rsalz@bbn.com
  1131. Moderator, comp.sources.unix            sources@uunet.uu.net
  1132.