home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / shape / part18 < prev    next >
Text File  |  1989-05-31  |  55KB  |  2,003 lines

  1. Subject:  v19i031:  A software configuration management system, Part18/33
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Axel Mahler <unido!coma!axel>
  7. Posting-number: Volume 19, Issue 31
  8. Archive-name: shape/part18
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 18 (of 33)."
  19. # Contents:  src/afs/aflib.c src/afs/afretr.c src/afsit/rcsit.c
  20. # Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:10 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'src/afs/aflib.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'src/afs/aflib.c'\"
  24. else
  25. echo shar: Extracting \"'src/afs/aflib.c'\" \(16973 characters\)
  26. sed "s/^X//" >'src/afs/aflib.c' <<'END_OF_FILE'
  27. X/*
  28. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  29. X *  and U. Pralle
  30. X * 
  31. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  32. X * WARRANTY for any part of this software to work correctly or as described
  33. X * in the manuals. We do not accept any liability for any kind of damage
  34. X * caused by use of this software, such as loss of data, time, money, or 
  35. X * effort.
  36. X * 
  37. X * Permission is granted to use, copy, modify, or distribute any part of
  38. X * this software as long as this is done without asking for charge, and
  39. X * provided that this copyright notice is retained as part of the source
  40. X * files. You may charge a distribution fee for the physical act of
  41. X * transferring a copy, and you may at your option offer warranty
  42. X * protection in exchange for a fee.
  43. X * 
  44. X * Direct questions to: Tech. Univ. Berlin
  45. X *              Wilfried Koch
  46. X *              Sekr. FR 5-6 
  47. X *              Franklinstr. 28/29
  48. X *              D-1000 Berlin 10, West Germany
  49. X * 
  50. X *              Tel: +49-30-314-22972
  51. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  52. X */
  53. X/*LINTLIBRARY*/
  54. X/*
  55. X *    Shape/AFS
  56. X *
  57. X *    aflib.c -- Miscellaneous functions
  58. X *
  59. X *    Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
  60. X *                      (andy@db0tui62.BITNET)
  61. X *
  62. X *    $Header: aflib.c[1.6] Wed Feb 22 16:27:41 1989 andy@coma published $
  63. X *
  64. X *    EXPORT:
  65. X *
  66. X *      af_errno -- global variable holding the actual error code
  67. X *    af_serr -- report error without writing error protocol
  68. X *    af_err -- write error protocol
  69. X *    af_wng -- print out warning message
  70. X *      af_perror -- print AFS-error
  71. X *      af_regtmpfile -- register tmp file
  72. X *      af_unregtmpfile -- unregister tmp file
  73. X *      af_reglckfile -- register lock file
  74. X *      af_cpfile -- copy files
  75. X *      af_cleanup -- do cleanup (e.g. upon signal)
  76. X *      af_malloc -- allocate memory
  77. X *      af_realloc -- reallocate memoty
  78. X *      af_free -- free allocated memory segment
  79. X *      af_frmemlist -- free list of allocated memory segments
  80. X *      af_bsearch -- binary search on ordered list of strings
  81. X *      af_checkread -- check read permissions of AF-file
  82. X *      af_checkperm -- check access permissions for AF-file
  83. X */
  84. X
  85. X#include <stdio.h>
  86. X#include <string.h>
  87. X#ifdef SUNOS_4_0
  88. X#include <strings.h>
  89. X#endif
  90. X#ifdef SYSLOG
  91. X#include <syslog.h>
  92. X#endif
  93. X
  94. X#include "typeconv.h"
  95. X#include "afsys.h"
  96. X#include "afs.h"
  97. X#include "afarchive.h"
  98. X
  99. X#ifdef MEMDEBUG
  100. Xextern FILE *memprot;
  101. X#endif
  102. X#ifdef TMPDEBUG
  103. Xextern FILE *tmpprot;
  104. X#endif
  105. X
  106. Xchar  *getlogin();
  107. X
  108. X/*=========================================================================
  109. X *     af_serr -- report error without writing error protocol
  110. X *
  111. X *=========================================================================*/
  112. X
  113. Xextern int errno;
  114. X
  115. XEXPORT int af_errno, af_nodiag = FALSE;
  116. X
  117. XEXPORT void af_serr (routine, called, errcd)
  118. X     char  *routine;
  119. X     char  *called;
  120. X     int   errcd;
  121. X{
  122. X  af_nodiag = TRUE;
  123. X  af_err (routine, called, errcd);
  124. X  af_nodiag = FALSE;
  125. X}    
  126. X
  127. X/*=========================================================================
  128. X *     af_err -- write error protocol
  129. X *
  130. X *=========================================================================*/
  131. X
  132. Xstatic char diagstr[265]; /* for diagnistics of AF_EMISC */
  133. X
  134. Xstatic char *errors[] = 
  135. X  {
  136. X    "", "", "",
  137. X    "permission denied",                /*  3 */
  138. X    "archive file has changed since last read",        /*  4 */
  139. X    "archive file is locked for writing",        /*  5 */
  140. X    "no additional space in binary pool",        /*  6 */
  141. X    "specified revision must not be a busy version",    /*  7 */
  142. X    "specified revision is a derived object",        /*  8 */
  143. X    "illegal format of var or uda string",        /*  9 */
  144. X    "invalid key",                    /* 10 */
  145. X    "invalid set",                    /* 11 */
  146. X    "invalid user",                    /* 12 */
  147. X    "bad version number",                /* 13 */
  148. X    "invalid location of archive",            /* 14 */
  149. X    "miscellaneous errors",                /* 15 */
  150. X    "invalid mode",                    /* 16 */
  151. X    "AFS subdirectory missing or not writable",        /* 17 */
  152. X    "key does not exist in set",            /* 18 */
  153. X    "invalid position in set",                /* 19 */
  154. X    "specified revision does not exist",        /* 20 */
  155. X    "specified object is no busy version",        /* 21 */
  156. X    "specified object is no derived object",        /* 22 */
  157. X    "version is not locked or locked by someone else",    /* 23 */
  158. X    "specified object is no regular file",        /* 24 */
  159. X    "specified object has no versions",            /* 25 */
  160. X    "user defined attribute does not exist",        /* 26 */
  161. X    "saved versions cannot be modified",        /* 27 */
  162. X    "invalid state transition",                /* 28 */
  163. X    "string too long",                    /* 29 */
  164. X    "too many user defined attributes",            /* 30 */
  165. X    "wrong state",                    /* 31 */
  166. X    "error during delta operation",            /* 32 */
  167. X    "Archive file inconsistent",            /* 33 */
  168. X    "internal error",                    /* 34 */
  169. X    "no AFS file",                    /* 35 */
  170. X  };
  171. X
  172. X
  173. XEXPORT void af_err (routine, called, errcd)
  174. X     char  *routine;
  175. X     char  *called;
  176. X     int   errcd;
  177. X{
  178. X#ifndef SYSLOG
  179. X  FILE *errfile;
  180. X  char *af_asctime();
  181. X#endif
  182. X
  183. X  if (af_nodiag)
  184. X    {
  185. X      af_errno = errcd;
  186. X      if (af_errno == AF_EMISC)
  187. X    (void) strcpy (diagstr, called);
  188. X      return; /* do nothing */
  189. X    }
  190. X
  191. X#ifdef SYSLOG
  192. X  if (!openlog ("AFS", LOG_PID, LOG_LOCAL1))
  193. X#else
  194. X  if ((errfile = fopen (AF_ERRLOG, "a")) == (FILE *)0)
  195. X#endif
  196. X    {
  197. X      fprintf (stderr, "AFS: cannot open Error-logfile\n");
  198. X      return;
  199. X    }
  200. X  (void) chmod (AF_ERRLOG, 0666);
  201. X
  202. X#ifdef SYSLOG
  203. X  switch (errcd)
  204. X    {
  205. X    case AF_ESYSERR: syslog (LOG_ERR, "%s called af_%s: %s error in %s (%m)", 
  206. X                 getlogin(), routine, errors [abs(errcd)], called);
  207. X                     break;
  208. X    case AF_EINCONSIST:
  209. X    case AF_ENOAFSFILE:
  210. X    case AF_EINTERNAL: syslog (LOG_ERR, "%s called af_%s: %s (%s)", getlogin(),
  211. X                   routine, errors [abs(errcd)], called);
  212. X                      break;
  213. X    case AF_EMISC: syslog (LOG_ERR, "%s called af_%s: %s ", getlogin(),
  214. X               routine, called);
  215. X                   (void) strcpy (diagstr, called);
  216. X                   break;
  217. X    default: syslog (LOG_ERR, "%s called af_%s: %s", getlogin(), 
  218. X             routine, errors [abs(errcd)]);
  219. X    }
  220. X#else
  221. X  fprintf (errfile, "%s pid[%d] %s",af_gethostname(),getpid (), af_asctime ());
  222. X  switch (errcd)
  223. X    {
  224. X    case AF_ESYSERR: fprintf (errfile, "\t%s called af_%s: %s error in %s\n", 
  225. X                 (char *) getlogin(), routine, errors [abs(errcd)], called);
  226. X                     break;
  227. X    case AF_EINCONSIST:
  228. X    case AF_ENOAFSFILE:
  229. X    case AF_EINTERNAL: fprintf (errfile, "\t%s called af_%s: %s (%s)\n", (char *) getlogin(), routine, errors [abs(errcd)], called);
  230. X                       break;
  231. X    case AF_EMISC: fprintf (errfile, "\t%s called af_%s: %s\n", (char *) getlogin(), routine, called);
  232. X                   (void) strcpy (diagstr, called);
  233. X                   break;
  234. X    default: fprintf (errfile, "\t%s called af_%s: %s\n", (char *) getlogin(), routine, errors [abs(errcd)]);
  235. X    }
  236. X#endif
  237. X
  238. X#ifdef SYSLOG
  239. X  closelog ();
  240. X#else
  241. X  (void) fclose (errfile);
  242. X#endif
  243. X
  244. X  af_errno = errcd;
  245. X  return;
  246. X}
  247. X
  248. X/*=========================================================================
  249. X *     af_wng -- write warning to error protocol
  250. X *
  251. X *=========================================================================*/
  252. X
  253. XEXPORT void af_wng (routine, comment)
  254. X     char  *routine, *comment;
  255. X{
  256. X#ifndef SYSLOG
  257. X  FILE *errfile;
  258. X  char *af_asctime();
  259. X#endif
  260. X
  261. X#ifdef SYSLOG
  262. X  if (!openlog ("AFS", LOG_PID, LOG_LOCAL1))
  263. X#else
  264. X  if ((errfile = fopen (AF_ERRLOG, "a")) == (FILE *)0)
  265. X#endif
  266. X    {
  267. X      fprintf (stderr, "AFS: cannot open Error-logfile\n");
  268. X      return;
  269. X    }
  270. X  (void) chmod (AF_ERRLOG, 0666);
  271. X
  272. X#ifdef SYSLOG
  273. X  syslog (LOG_WARNING, "%s called af_%s: %s", getlogin(), routine, comment);
  274. X#else
  275. X  fprintf (errfile, "%s pid[%d] %s", af_gethostname(), getpid (), af_asctime ());
  276. X  fprintf (errfile, "\t%s called af_%s: %s\n", (char *) getlogin(), routine, comment);
  277. X#endif
  278. X
  279. X#ifdef SYSLOG
  280. X  closelog ();
  281. X#else
  282. X  (void) fclose (errfile);
  283. X#endif
  284. X  return;
  285. X}
  286. X
  287. X
  288. X/*=========================================================================
  289. X *     af_perror -- print AFS-error message
  290. X *
  291. X *=========================================================================*/
  292. X
  293. XEXPORT void af_perror (string)
  294. X     char  *string;
  295. X{
  296. X  switch (af_errno)
  297. X    {
  298. X    case AF_ESYSERR: perror (string);
  299. X                     break;
  300. X    case AF_EMISC: fprintf (stderr, "%s: %s\n", string, diagstr);
  301. X                  break;
  302. X    default: fprintf (stderr, "%s: %s\n", string, errors [abs(af_errno)]);
  303. X    }
  304. X}
  305. X
  306. X/**************************************************************************/
  307. X
  308. X/*================================================================
  309. X *      list of tmp files
  310. X *
  311. X *================================================================*/
  312. X
  313. Xstatic char *tmpfilelist[NOFILE];
  314. X
  315. XLOCAL void rmtmpfiles ()
  316. X{
  317. X  register i;
  318. X
  319. X  for (i=0; i < NOFILE; i++)
  320. X    if (tmpfilelist[i] != (char *)0)
  321. X      (void) af_unlink (tmpfilelist[i]);
  322. X}
  323. X
  324. XEXPORT void af_regtmpfile (name) /* registrate tmp file */
  325. X     char *name;
  326. X{
  327. X  register int i;
  328. X
  329. X#ifdef TMPDEBUG
  330. X  fprintf (tmpprot, "TMP: register %s\n", name);
  331. X#endif
  332. X  /* look for free space in list */
  333. X  for (i=0; i < NOFILE; i++)
  334. X    if (tmpfilelist[i] == (char *)0)
  335. X      {
  336. X    tmpfilelist[i] = name;
  337. X    break;
  338. X      }
  339. X  if (i == NOFILE) /* list is full */
  340. X    af_wng ("regtmpfile", "tmpfile list is full -- couldn't register");
  341. X}
  342. X
  343. XEXPORT void af_unregtmpfile (name) /* remove tmp file entry */
  344. X     char *name;
  345. X{
  346. X  register i;
  347. X#ifdef TMPDEBUG
  348. X  fprintf (tmpprot, "TMP: unregister %s\n", name);
  349. X#endif
  350. X  for (i=0; i < NOFILE; i++)
  351. X    if (tmpfilelist[i] == name)
  352. X      {
  353. X    tmpfilelist[i] = (char *)0;
  354. X    break;
  355. X      }
  356. X  if (i == NOFILE) /* name not found */
  357. X    af_wng ("unregtmpfile", "name of tmpfile has not been registered before");
  358. X}  
  359. X
  360. X/*=========================================================================
  361. X *     af_reglckfile -- register lock file
  362. X *
  363. X *=========================================================================*/
  364. X
  365. Xstatic char *lckfilename;
  366. X
  367. XEXPORT af_reglckfile (name)
  368. X     char *name;
  369. X{
  370. X  lckfilename = af_entersym (name);
  371. X}
  372. X
  373. XLOCAL rmlckfiles ()
  374. X{
  375. X  (void) unlink (lckfilename);
  376. X}
  377. X
  378. X/*=========================================================================
  379. X *     af_cpfile -- copy files
  380. X *
  381. X *=========================================================================*/
  382. X
  383. XEXPORT af_cpfile (source, size, dest)
  384. X     char *source;
  385. X     off_t size;
  386. X     char *dest;
  387. X{
  388. X  char   cont[BUFSIZ];
  389. X  int    bufsiz = BUFSIZ;
  390. X  FILE   *sfile, *dfile;
  391. X  
  392. X  if ((sfile = fopen (source, "r")) == (FILE *)0)
  393. X    {
  394. X      free (cont);
  395. X      return (ERROR);
  396. X    }
  397. X  if ((dfile = fopen (dest, "w")) == (FILE *) 0)
  398. X    {
  399. X      free (cont);
  400. X      (void) fclose (sfile);
  401. X      return (ERROR);
  402. X    }
  403. X
  404. X  while (size > 0)
  405. X    {
  406. X      if (size >= BUFSIZ)
  407. X    size -= BUFSIZ;
  408. X      else
  409. X    {
  410. X      bufsiz = size;
  411. X      size = 0;
  412. X    }
  413. X      if (!fread (cont, sizeof(char), bufsiz, sfile))
  414. X    {
  415. X      (void) fclose (sfile);
  416. X      (void) fclose (dfile);
  417. X      return (ERROR);
  418. X    }
  419. X      if (!fwrite (cont, sizeof(char), bufsiz, dfile))
  420. X    {
  421. X      (void) fclose (sfile);
  422. X      (void) fclose (dfile);
  423. X      return (ERROR);
  424. X    }
  425. X    }
  426. X
  427. X  (void) fclose (sfile);
  428. X  (void) fclose (dfile);
  429. X  return (AF_OK);
  430. X}
  431. X
  432. X
  433. X/**************************************************************************/
  434. X
  435. X/*=========================================================================
  436. X *     af_cleanup -- do cleanup
  437. X *
  438. X *=========================================================================*/
  439. X
  440. XEXPORT af_cleanup ()
  441. X{
  442. X  /* remove tmp files */
  443. X  rmtmpfiles ();
  444. X  rmlckfiles ();
  445. X}
  446. X
  447. X/*=========================================================================
  448. X *     af_malloc -- allocate memory and registrate it
  449. X *     af_realloc -- reallocate memory and registrate it
  450. X *
  451. X * all memory allocated for data in an archive is preceeded by a pointer
  452. X * pointing to the prevoiusly allocated memory segment.
  453. X * So we get a chain of allocated memory segments.
  454. X * ( probably not portable )
  455. X *
  456. X *=========================================================================*/
  457. X
  458. XEXPORT char *af_malloc (list, size)
  459. X     Af_revlist *list;
  460. X     unsigned   size;
  461. X{
  462. X  char **mem, *malloc();
  463. X
  464. X  if ((mem = (char **)malloc ((unsigned) (size + sizeof (mem)))) == (char **)0)
  465. X    return (char *)0;
  466. X#ifdef MEMDEBUG
  467. X      fprintf (memprot, "%x (alloc) %d bytes\n", mem, size + sizeof (mem));
  468. X#endif
  469. X
  470. X  *mem = list->af_mem;
  471. X  list->af_mem = (char *)mem;
  472. X
  473. X  mem++; /* increment by sizeof ptr */
  474. X
  475. X  return ((char *)mem);
  476. X}
  477. X
  478. X
  479. XEXPORT char *af_realloc (list, ptr, size)
  480. X     Af_revlist *list;
  481. X     char       *ptr;
  482. X     unsigned   size;
  483. X{
  484. X  char **mem, **segptr, **nextptr, *realloc();
  485. X
  486. X  if ((mem = (char **)realloc (ptr, (unsigned) (size + sizeof (mem)))) == (char **)0)
  487. X    return (char *)0;
  488. X#ifdef MEMDEBUG
  489. X      fprintf (memprot, "realloc: old - %x , new - %x %d bytes\n", ptr, mem, size + sizeof (mem));
  490. X#endif
  491. X
  492. X  if ((char *)mem == ptr - sizeof ((char *)0)) /* no registration necessary */
  493. X    return ((char *)mem);
  494. X
  495. X  segptr = &(list->af_mem); /* remove the implicitely freed memory segment */
  496. X  while (*segptr != ptr - sizeof ((char *)0))
  497. X    segptr = (char **)*segptr;
  498. X  nextptr = (char **)*segptr;
  499. X  *segptr = *nextptr;
  500. X
  501. X  *mem = list->af_mem; /* registrate new segment */
  502. X  list->af_mem = (char *)mem;
  503. X
  504. X  mem++; /* increment by sizeof ptr */
  505. X
  506. X  return ((char *)mem);
  507. X}
  508. X
  509. XEXPORT void af_free (list, ptr)
  510. X     Af_revlist *list;
  511. X     char       *ptr;
  512. X{
  513. X  char **segptr, **nextptr;
  514. X
  515. X#ifdef MEMDEBUG
  516. X      fprintf (memprot, "%x (free)\n", ptr - sizeof ((char *)0));
  517. X#endif
  518. X  free (ptr - sizeof ((char *)0));
  519. X
  520. X  segptr = &(list->af_mem); /* remove memory segment from registration list */
  521. X  while (*segptr != ptr - sizeof ((char *)0))
  522. X    segptr = (char **)*segptr;
  523. X  nextptr = (char **)*segptr;
  524. X  *segptr = *nextptr;
  525. X}
  526. X
  527. X
  528. XEXPORT void af_frmemlist (list)
  529. X     Af_revlist *list;
  530. X{
  531. X  char **ptr;
  532. X
  533. X  ptr = &(list->af_mem);
  534. X  while ((char *)*ptr)
  535. X    {
  536. X#ifdef MEMDEBUG
  537. X      fprintf (memprot, "%x (free)\n", *ptr);
  538. X#endif
  539. X      free (*ptr);
  540. X      ptr = (char **)*ptr;
  541. X    }
  542. X  list->af_mem = (char *)0;
  543. X}
  544. X
  545. X/*========================================================================
  546. X * af_bsearch -- do binary search on ordered list of strings
  547. X *               returns position (-1 if target not found)
  548. X *
  549. X *========================================================================*/
  550. X
  551. XEXPORT af_bsearch (list, size, target)
  552. X     char **list;
  553. X     int  size;
  554. X     char *target;
  555. X{
  556. X  int hi = size-1, lo=0, pos, res;
  557. X
  558. X  pos = (hi+lo)/2;
  559. X  while (hi >= lo)
  560. X    {
  561. X      if ((res = strcmp (target, list[pos])) == 0)
  562. X    return (pos);
  563. X      else
  564. X    {      
  565. X      if (res < 0)
  566. X        hi = pos - 1;
  567. X      else /* res > 0 */
  568. X        lo = pos + 1;
  569. X      pos = (hi+lo)/2;
  570. X    }
  571. X    }
  572. X  /* the target string was not found */
  573. X  return (ERROR);
  574. X}
  575. X
  576. X
  577. X/*====================================================================
  578. X *   af_checkread -- see if AF-file is readable
  579. X *
  580. X *====================================================================*/
  581. X
  582. XEXPORT af_checkread (key)
  583. X     Af_key *key;
  584. X{
  585. X  Uid_t uid, auuid, ownuid;
  586. X  Gid_t augid, owngid;
  587. X  int   i, ngroups, gidset[NGROUPS];
  588. X
  589. X  if ((VATTR(key).af_mode & 0004) == 0004) /* readable for world */
  590. X    return (AF_OK);
  591. X
  592. X  if ((VATTR(key).af_mode & 0040) == 0040) /* readable for group */
  593. X    {
  594. X      /* this then part is BSD specific */
  595. X      ngroups = getgroups (NGROUPS, gidset);
  596. X      augid = af_getgid (VATTR(key).af_auname, VATTR(key).af_auhost);
  597. X      owngid = af_getgid (CATTR(key).af_ownname, CATTR(key).af_ownhost);
  598. X      for (i=0; i < ngroups; i++)
  599. X    {
  600. X      if ((augid == (Gid_t)gidset[i]) || (owngid == (Gid_t)gidset[i]))
  601. X        return (AF_OK);
  602. X    }
  603. X    }
  604. X
  605. X  if ((VATTR(key).af_mode & 0400) == 0400) /* readable by owner */
  606. X    {
  607. X      uid = getuid();
  608. X      auuid = af_getuid (VATTR(key).af_auname, VATTR(key).af_auhost);
  609. X      ownuid = af_getuid (CATTR(key).af_ownname, CATTR(key).af_ownhost);
  610. X      if ((auuid == uid) || (ownuid == uid))
  611. X    return (AF_OK);
  612. X    }
  613. X
  614. X  return (ERROR);
  615. X}
  616. X
  617. X
  618. X/*====================================================================
  619. X *   af_checkperm -- check access permissions for AF-file
  620. X *
  621. X *====================================================================*/
  622. X
  623. XEXPORT af_checkperm (key, mode)
  624. X     Af_key *key;
  625. X     int    mode;
  626. X{
  627. X  Uid_t uid = getuid(), lockeruid;
  628. X  bool ok = FALSE;
  629. X
  630. X  if (mode & AF_OWNER)
  631. X    {
  632. X      if (uid == af_getuid (CATTR(key).af_ownname, CATTR(key).af_ownhost))
  633. X    ok = TRUE;
  634. X    }
  635. X  if (!ok && (mode & AF_LOCKHOLDER))
  636. X    {
  637. X      if ((lockeruid = af_getuid (VATTR(key).af_lckname, 
  638. X                  VATTR(key).af_lckhost)) == uid)
  639. X    ok = TRUE;
  640. X      else
  641. X    {
  642. X      /* if object is locked by someone else */
  643. X      if (lockeruid != (Uid_t) ERROR) 
  644. X        goto exit;
  645. X    }
  646. X    }
  647. X  if (!ok && (mode & AF_AUTHOR))
  648. X    {
  649. X      if (uid == af_getuid (VATTR(key).af_auname, VATTR(key).af_auhost))
  650. X    ok = TRUE;
  651. X    }
  652. X  if (!ok && (mode & AF_WORLD))
  653. X    {
  654. X      ok = TRUE;
  655. X    }
  656. X  
  657. X exit:
  658. X  /* if access is not ok, or AFS subdir is not writable */
  659. X  if (!ok)
  660. X    SFAIL ("checkperm", "", AF_EACCES, ERROR);
  661. X  if (!(key->af_ldes->af_extent & AF_UXWRITE))
  662. X    SFAIL ("checkperm", "", AF_ENOAFSDIR, ERROR);
  663. X  return (AF_OK);
  664. X}
  665. END_OF_FILE
  666. if test 16973 -ne `wc -c <'src/afs/aflib.c'`; then
  667.     echo shar: \"'src/afs/aflib.c'\" unpacked with wrong size!
  668. fi
  669. # end of 'src/afs/aflib.c'
  670. fi
  671. if test -f 'src/afs/afretr.c' -a "${1}" != "-c" ; then 
  672.   echo shar: Will not clobber existing file \"'src/afs/afretr.c'\"
  673. else
  674. echo shar: Extracting \"'src/afs/afretr.c'\" \(16910 characters\)
  675. sed "s/^X//" >'src/afs/afretr.c' <<'END_OF_FILE'
  676. X/*
  677. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  678. X *  and U. Pralle
  679. X * 
  680. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  681. X * WARRANTY for any part of this software to work correctly or as described
  682. X * in the manuals. We do not accept any liability for any kind of damage
  683. X * caused by use of this software, such as loss of data, time, money, or 
  684. X * effort.
  685. X * 
  686. X * Permission is granted to use, copy, modify, or distribute any part of
  687. X * this software as long as this is done without asking for charge, and
  688. X * provided that this copyright notice is retained as part of the source
  689. X * files. You may charge a distribution fee for the physical act of
  690. X * transferring a copy, and you may at your option offer warranty
  691. X * protection in exchange for a fee.
  692. X * 
  693. X * Direct questions to: Tech. Univ. Berlin
  694. X *              Wilfried Koch
  695. X *              Sekr. FR 5-6 
  696. X *              Franklinstr. 28/29
  697. X *              D-1000 Berlin 10, West Germany
  698. X * 
  699. X *              Tel: +49-30-314-22972
  700. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  701. X */
  702. X/*LINTLIBRARY*/
  703. X/*
  704. X *    Shape/AFS
  705. X *
  706. X *    afretr.c - retrieve interface 
  707. X *
  708. X *    Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP
  709. X *                       andy@db0tui62.BITNET)
  710. X *
  711. X *    $Header: afretr.c[1.4] Wed Feb 22 16:27:50 1989 andy@coma published $
  712. X *
  713. X *    EXPORT:
  714. X *    af_bpfind -- find derived files by attributes
  715. X *    af_find -- find source files by attributes
  716. X *    af_getkey -- find single file by unique attributes
  717. X *    af_dropkey -- release memory associated with filekey 
  718. X *    af_initattrs -- initialize attribute buffer
  719. X */
  720. X
  721. X#include <stdio.h>
  722. X#include <string.h>
  723. X#ifdef SUNOS_4_0
  724. X#include <strings.h>
  725. X#endif
  726. X#include <sys/types.h>
  727. X#include <sys/stat.h>
  728. X/* #include <sys/dir.h> */
  729. X
  730. X#include "typeconv.h"
  731. X#include "afsys.h"
  732. X#include "afs.h"
  733. X#include "afarchive.h"
  734. X
  735. Xextern int af_errno;
  736. X
  737. Xextern Af_hashent af_hashentry;
  738. X
  739. X/*================= collect_lists ====================================*/
  740. X
  741. XLOCAL Af_revlist **collect_lists (pathname, name, type, revlist, nlists)
  742. X     char       *pathname, *name, *type;
  743. X     Af_revlist **revlist;
  744. X     int        *nlists; /* out */
  745. X{
  746. X  DIR           *dirp;
  747. X  struct direct *dirent;
  748. X  char          *afpath, *afname, *aftype, dirpath[MAXNAMLEN*4];
  749. X  char          fullname[MAXNAMLEN*4], *realloc();
  750. X  bool          seconddir = FALSE, mode;
  751. X  int           listsiz, i;
  752. X  Af_revlist    *af_readattrs();
  753. X
  754. X  listsiz = AF_SEGLEN;
  755. X  *nlists = 0;
  756. X
  757. X  /* open named directory  */
  758. X  if ((dirp = opendir (pathname)) == (DIR *)0)
  759. X    FAIL ("collect_lists", "opendir", AF_ESYSERR, (Af_revlist **)0);
  760. X
  761. X  (void) strcpy (dirpath, pathname);
  762. X
  763. Xloop:
  764. X  /* lookup all files */
  765. X  while ((dirent = readdir (dirp)) != (struct direct *)0)
  766. X    {
  767. X      (void) sprintf (fullname, "%s/%s\0", dirpath, dirent->d_name);
  768. X
  769. X      /* if entry belongs to binary pool */
  770. X      if (af_isbpfile (dirent->d_name))
  771. X    continue;
  772. X
  773. X      afname = af_entersym (af_afname (fullname));
  774. X      aftype = af_entersym (af_aftype (fullname));
  775. X
  776. X      /* if ((no name given || name equal) && (no type || type equal)) */
  777. X      if ( ((name[0] == '*') || !strcmp (name, afname)) &&
  778. X       ((type[0] == '*') || !strcmp (type, aftype))    )
  779. X    {
  780. X      (*nlists)++;
  781. X      if (*nlists >= listsiz)
  782. X        {
  783. X          /* realloc memory for revlist */
  784. X          if ((revlist = (Af_revlist **)realloc ((char *)revlist, (unsigned) (sizeof((Af_revlist *)0)*(listsiz + AF_SEGLEN)))) == (Af_revlist **)0)
  785. X        FAIL ("collect_lists","realloc", AF_ESYSERR, (Af_revlist **)0);
  786. X          listsiz += AF_SEGLEN;
  787. X        }
  788. X      afpath = af_entersym (af_afpath (fullname));
  789. X      mode = TRUE;
  790. X      if ((revlist[(*nlists)-1] = 
  791. X           af_readattrs (afpath, afname, aftype, &mode))
  792. X                                                == (Af_revlist *)0)
  793. X        {
  794. X          if (af_errno == AF_ENOAFSFILE)
  795. X        {
  796. X          (*nlists)--;
  797. X          continue;
  798. X        }
  799. X          else
  800. X        return ((Af_revlist **)0);
  801. X        }
  802. X      if (mode)
  803. X        {
  804. X          /* see if list is already in "revlists" */
  805. X          /* this loop may be time-consuming */
  806. X          i = 0;
  807. X          while (i < (*nlists)-1)
  808. X        {
  809. X          if ((revlist[i]->af_list[0].af_name == afname) &&
  810. X              (revlist[i]->af_cattrs.af_syspath == afpath) &&
  811. X              (revlist[i]->af_list[0].af_type == aftype))
  812. X            {
  813. X              (*nlists)--;
  814. X              break;
  815. X            }
  816. X          i++;
  817. X        }
  818. X        }
  819. X    }
  820. X    }
  821. X  closedir (dirp);
  822. X
  823. X  if (!seconddir)
  824. X    {
  825. X      (void) sprintf (dirpath, "%s%c%s\0", pathname, '/', AF_SUBDIR);
  826. X      /* open AFS subdirectory if it exists */
  827. X      if ((dirp = opendir (dirpath)) != (DIR *)0)
  828. X    {
  829. X      seconddir = TRUE;
  830. X      goto loop;
  831. X    }
  832. X    }
  833. Xreturn (revlist);
  834. X}
  835. X
  836. X/*====================================================================
  837. X *    af_abufcmp -- compare attrbuf with version attributes
  838. X *                  returns TRUE if attrs do not match
  839. X *
  840. X *====================================================================*/
  841. X
  842. XLOCAL af_abufcmp (attrbuf, key)
  843. X     Af_attrs *attrbuf;
  844. X     Af_key   *key;
  845. X{
  846. X  int match, j;
  847. X
  848. X  /* if (attribute is set && attributes does not match) -- return ERROR */
  849. X  
  850. X  /*** generation number ***/
  851. X  if ((attrbuf->af_gen != AF_NOVNUM) && (attrbuf->af_gen != VATTR(key).af_gen))
  852. X    return (ERROR);
  853. X  
  854. X  /*** revision number ***/
  855. X  if ((attrbuf->af_rev != AF_NOVNUM) && (attrbuf->af_rev != VATTR(key).af_rev))
  856. X    return (ERROR);
  857. X
  858. X  /*** variant attribute ***/
  859. X  if ((attrbuf->af_variant[0]) &&
  860. X      (strcmp (attrbuf->af_variant, NOTNIL(VATTR(key).af_variant))))
  861. X    return (ERROR);
  862. X
  863. X  /*** state ***/
  864. X  if ((attrbuf->af_state != AF_NOSTATE) &&
  865. X      (attrbuf->af_state != VATTR(key).af_state))
  866. X    return (ERROR);
  867. X
  868. X  /*** owner ***/
  869. X  if ( (attrbuf->af_owner.af_username[0]) &&
  870. X       (strcmp (attrbuf->af_owner.af_username, CATTR(key).af_ownname)) )
  871. X    return (ERROR);
  872. X  if ( (attrbuf->af_owner.af_userhost[0]) &&
  873. X       (strcmp (attrbuf->af_owner.af_userhost, CATTR(key).af_ownhost)) )
  874. X    return (ERROR);
  875. X  
  876. X  /*** author ***/
  877. X  if ( (attrbuf->af_author.af_username[0]) &&
  878. X       (strcmp (attrbuf->af_author.af_username, VATTR(key).af_auname)) )
  879. X    return (ERROR);
  880. X  if ( (attrbuf->af_author.af_userhost[0]) &&
  881. X       (strcmp (attrbuf->af_author.af_userhost, VATTR(key).af_auhost)) )
  882. X    return (ERROR);
  883. X  
  884. X  /*** size ***/
  885. X  if ((attrbuf->af_size != AF_NOSIZE) &&
  886. X      (attrbuf->af_size != VATTR(key).af_fsize) )
  887. X    return (ERROR);
  888. X
  889. X  /*** mode ***/
  890. X  if ((attrbuf->af_mode != AF_NOMODE) &&
  891. X      (attrbuf->af_mode != VATTR(key).af_mode))
  892. X    return (ERROR);
  893. X
  894. X  /*** locker ***/
  895. X  if ( (attrbuf->af_locker.af_username[0]) &&
  896. X       (strcmp (attrbuf->af_locker.af_username,
  897. X        NOTNIL(VATTR(key).af_lckname))) )
  898. X    return (ERROR);
  899. X  if ( (attrbuf->af_locker.af_userhost[0]) &&
  900. X       (strcmp (attrbuf->af_locker.af_userhost,
  901. X        NOTNIL(VATTR(key).af_lckhost))) )
  902. X    return (ERROR);
  903. X  
  904. X  /*** date of last modification ***/
  905. X  if ((attrbuf->af_mtime != AF_NOTIME) &&
  906. X      (attrbuf->af_mtime != VATTR(key).af_mtime) )
  907. X    return (ERROR);
  908. X
  909. X  /*** date of last access ***/
  910. X  if ((attrbuf->af_atime != AF_NOTIME) &&
  911. X      (attrbuf->af_atime != VATTR(key).af_atime) )
  912. X    return (ERROR);
  913. X
  914. X  /*** date of last status change ***/
  915. X  if ((attrbuf->af_ctime != AF_NOTIME) &&
  916. X      (attrbuf->af_ctime != VATTR(key).af_ctime) )
  917. X    return (ERROR);
  918. X
  919. X  /*** saving date ***/
  920. X  if ((attrbuf->af_stime != AF_NOTIME) &&
  921. X      (attrbuf->af_stime != VATTR(key).af_stime) )
  922. X    return (ERROR);
  923. X  
  924. X  /*** date of last lock change ***/
  925. X  if ((attrbuf->af_stime != AF_NOTIME) &&
  926. X      (attrbuf->af_stime != VATTR(key).af_stime) )
  927. X    return (ERROR);
  928. X  
  929. X  /*** user defined attributes ***/
  930. X  if (attrbuf->af_udattrs[0] != (char *)0)
  931. X    {
  932. X      /* if list of user defined attributes is not empty or there */
  933. X                                                /* are attributes */
  934. X      match = TRUE;
  935. X      if ((attrbuf->af_udattrs[0][0] != '\0') || (VATTR(key).af_udanum != 0))
  936. X    {
  937. X      /* test all given entries */
  938. X      j=0;
  939. X      while ((attrbuf->af_udattrs[j] != (char *)0) 
  940. X         && (match = !af_match (attrbuf->af_udattrs[j],
  941. X                    &(VATTR(key).af_uhtab))))
  942. X        j++;
  943. X    } /* if */
  944. X      if (match == FALSE)
  945. X    return (ERROR);
  946. X    } /* if */
  947. Xreturn (AF_OK);
  948. X}
  949. X
  950. X
  951. X/*====================================================================
  952. X *    af_bpfind
  953. X *
  954. X *====================================================================*/
  955. X
  956. XEXPORT af_bpfind (attrbuf, set)
  957. X     Af_attrs *attrbuf;
  958. X     Af_set   *set;     /* out */
  959. X{
  960. X  Af_revlist *bplist, *af_rbplist();
  961. X  int        i, maxindex;
  962. X  char       *pathname, *getwd(), *malloc();
  963. X  Af_key     key;
  964. X
  965. X  /* init set */
  966. X  set->af_nkeys = 0;
  967. X  set->af_setlen = 0;
  968. X  set->af_klist = (Af_key *)0;
  969. X
  970. X  /* build pathname (default is current directory) */
  971. X  pathname = af_uniqpath (attrbuf->af_syspath);
  972. X
  973. X  if ((bplist = af_rbplist (pathname)) == (Af_revlist *)0)
  974. X    if (af_errno == AF_ENOAFSDIR)
  975. X      return (0);
  976. X    else
  977. X      return (ERROR);
  978. X
  979. X  /* alloacte memory for set */
  980. X  if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof (Af_key) * bplist->af_nrevs))) == (Af_key *)0)
  981. X    FAIL ("bpfind", "malloc", AF_ESYSERR, ERROR);
  982. X  set->af_setlen = bplist->af_nrevs;
  983. X
  984. X  /* add all desired bpfiles to set */
  985. X  maxindex = bplist->af_nrevs;
  986. X  for (i=0; i < maxindex; i++)
  987. X    {
  988. X      /* skip invalid bpfiles */
  989. X      if (!(bplist->af_list[i].af_class & AF_VALID))
  990. X    {
  991. X      maxindex++;
  992. X      continue;
  993. X    }
  994. X      if (((attrbuf->af_name[0] != '*') &&
  995. X       (strcmp (attrbuf->af_name, bplist->af_list[i].af_name))) ||
  996. X      ((attrbuf->af_type[0] != '*') &&
  997. X       (strcmp (attrbuf->af_type, NOTNIL(bplist->af_list[i].af_type)))))
  998. X    continue;
  999. X
  1000. X      key.af_ldes = bplist;
  1001. X      key.af_lpos = i;
  1002. X      if (af_abufcmp (attrbuf, &key))
  1003. X    continue;
  1004. X      
  1005. X      /* else add bpfile to set */
  1006. X      set->af_klist[set->af_nkeys].af_ldes = bplist;
  1007. X      set->af_klist[set->af_nkeys].af_lpos = i;
  1008. X      set->af_nkeys++;
  1009. X      bplist->af_refcount++;
  1010. X      bplist->af_list[i].af_nlinks++;
  1011. X    }
  1012. X  /* if set is empty */
  1013. X  if (set->af_nkeys == 0)
  1014. X    {
  1015. X      free ((char *)set->af_klist);
  1016. X      set->af_setlen = 0;
  1017. X    }
  1018. X
  1019. X  if (bplist->af_refcount <= 0)
  1020. X    (void) af_detlist (bplist);
  1021. X
  1022. X  return (set->af_nkeys);
  1023. X}
  1024. X
  1025. X
  1026. X/*====================================================================
  1027. X *    af_find
  1028. X *
  1029. X *====================================================================*/
  1030. X
  1031. XEXPORT af_find (attrbuf, set)
  1032. X     Af_attrs *attrbuf;
  1033. X     Af_set   *set;     /* out */
  1034. X{
  1035. X  char          *pathname, *getwd(), *malloc();
  1036. X  register int  i;
  1037. X  int           nlists, maxindex;
  1038. X  Af_revlist    *af_readattrs(), **revlist;
  1039. X  Af_key        key;
  1040. X  bool          mode = FALSE;
  1041. X
  1042. X  /* alloc memory for revlist */
  1043. X  if ((revlist = (Af_revlist **)malloc ((unsigned) (sizeof((Af_revlist *)0)*AF_SEGLEN))) == (Af_revlist **)0)
  1044. X    FAIL ("find", "malloc", AF_ESYSERR, ERROR);
  1045. X
  1046. X  /* init set */
  1047. X  set->af_nkeys = 0;
  1048. X  set->af_setlen = 0;
  1049. X  set->af_klist = (Af_key *)0;
  1050. X
  1051. X  /* build pathname (default is current directory) */
  1052. X  pathname = af_uniqpath (attrbuf->af_syspath);
  1053. X
  1054. X  if ((attrbuf->af_name[0] == '*') || (attrbuf->af_type[0] == '*'))
  1055. X    {
  1056. X      if ((revlist = collect_lists (pathname, attrbuf->af_name,
  1057. X                    attrbuf->af_type, revlist, &nlists))
  1058. X      == (Af_revlist **)0)
  1059. X    return (ERROR);
  1060. X    }
  1061. X  else
  1062. X    {
  1063. X      if (!attrbuf->af_name[0] && !attrbuf->af_type[0])
  1064. X    {
  1065. X      free ((char *)revlist);
  1066. X      return (set->af_nkeys); /* no Af-files found */
  1067. X    }
  1068. X      if ((revlist[0] =
  1069. X       af_readattrs (pathname, attrbuf->af_name,
  1070. X             attrbuf->af_type, &mode)) == (Af_revlist *)0)
  1071. X    {
  1072. X      free ((char *)revlist);
  1073. X      if (af_errno == AF_ENOAFSFILE)
  1074. X        nlists = 0;
  1075. X      else
  1076. X        return (ERROR);
  1077. X    }
  1078. X      else
  1079. X    nlists = 1;
  1080. X    }
  1081. X
  1082. X  if (nlists == 0)
  1083. X    return (set->af_nkeys); /* no Af-files found */
  1084. X
  1085. X  /* alloacte memory for set */
  1086. X  if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof (Af_key) * AF_SEGLEN))) == (Af_key *)0)
  1087. X    FAIL ("find", "malloc", AF_ESYSERR, ERROR);
  1088. X  set->af_setlen = AF_SEGLEN;
  1089. X
  1090. X  /* lookup all revisions in all lists */
  1091. X  /* this part is implemented quite dull up to now */
  1092. X  /*     -- the number of "if"'s should be reduced */
  1093. X  for (;nlists > 0; nlists--)
  1094. X    {
  1095. X      maxindex = revlist[nlists-1]->af_nrevs;
  1096. X      for (i = 0; i < maxindex; i++)
  1097. X    {
  1098. X      /* skip holes in the list */
  1099. X      if (!(revlist[nlists-1]->af_list[i].af_class & AF_VALID))
  1100. X        {
  1101. X          maxindex++;
  1102. X          continue;
  1103. X        }
  1104. X
  1105. X      /* test all attributes -- returnes true if attrs do not match */
  1106. X      key.af_ldes = revlist[nlists-1];
  1107. X      key.af_lpos = i;
  1108. X      if (af_abufcmp (attrbuf, &key))
  1109. X        continue;
  1110. X
  1111. X      /********************************************/
  1112. X      /********** put AF-file into set ************/
  1113. X      /********************************************/
  1114. X
  1115. X      /* if set is full, enlarge it */
  1116. X      if (set->af_nkeys == set->af_setlen)
  1117. X        {
  1118. X          if ((set->af_klist = 
  1119. X           (Af_key *)realloc ((char *)set->af_klist, (unsigned) (sizeof(Af_key) * (set->af_setlen + AF_SEGLEN)))) == (Af_key *)0)
  1120. X        FAIL ("find", "realloc", AF_ESYSERR, ERROR);
  1121. X          set->af_setlen += AF_SEGLEN;
  1122. X        }
  1123. X
  1124. X      /* add revision to key-set */
  1125. X      set->af_klist[set->af_nkeys].af_ldes = revlist[nlists-1];
  1126. X      set->af_klist[set->af_nkeys].af_lpos = i;
  1127. X      set->af_nkeys++;
  1128. X      revlist[nlists-1]->af_refcount++;
  1129. X      revlist[nlists-1]->af_list[i].af_nlinks++;
  1130. X    } /* for all revisions in archive */
  1131. X
  1132. X      /* if revlist does not contribute to hit set */
  1133. X      if (revlist[nlists-1]->af_refcount <= 0)
  1134. X    (void) af_detlist (revlist[nlists-1]);
  1135. X
  1136. X    } /* for all archives */
  1137. X
  1138. X  /* if set is empty */
  1139. X  if (set->af_nkeys == 0)
  1140. X    {
  1141. X      free ((char *)set->af_klist);
  1142. X      set->af_setlen = 0;
  1143. X    }
  1144. X
  1145. X  free ((char *)revlist);
  1146. X  return (set->af_nkeys);
  1147. X}
  1148. X
  1149. X
  1150. X/*====================================================================
  1151. X *    af_getkey
  1152. X *
  1153. X *====================================================================*/
  1154. X
  1155. XEXPORT af_getkey (syspath, name, type, gen, rev, variant, key)
  1156. X     char   *syspath, *name, *type;
  1157. X     int    gen, rev;
  1158. X     /*ARGSUSED*/
  1159. X     char   *variant; /* unused */
  1160. X     Af_key *key;
  1161. X{
  1162. X  Af_revlist *list, *af_readattrs();
  1163. X  char *path;
  1164. X  bool mode = FALSE;
  1165. X
  1166. X  /* build pathname (default is current directory) */
  1167. X  path = af_uniqpath (syspath);
  1168. X
  1169. X  if ((list = af_readattrs (path, name, type, &mode)) == (Af_revlist *)0)
  1170. X    SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1171. X  key->af_ldes = list;
  1172. X  /* handle special cases */
  1173. X  if ((gen < 0) || (rev < 0))
  1174. X    {
  1175. X      switch (gen)
  1176. X    {
  1177. X    case AF_BUSYVERS: if (af_buildkey (list, gen, rev, key) == ERROR)
  1178. X                        SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1179. X                      break;
  1180. X    case AF_LASTVERS: if ((rev != AF_LASTVERS) || (list->af_nrevs == 0))
  1181. X                         SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1182. X                      /* if busy version is valid */
  1183. X                      key->af_lpos = list->af_listlen-1;
  1184. X              while (!(VATTR(key).af_class & AF_VALID) || 
  1185. X                 (VATTR(key).af_state == AF_BUSY))
  1186. X                {
  1187. X                  if (key->af_lpos-- == 0)
  1188. X                SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1189. X                }
  1190. X              break;
  1191. X    case AF_FIRSTVERS: if ((rev != AF_FIRSTVERS) || (list->af_nrevs == 0))
  1192. X                         SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1193. X               key->af_lpos = 0;
  1194. X               while ((VATTR(key).af_state == AF_BUSY) ||
  1195. X                  (!(VATTR(key).af_class & AF_VALID)))
  1196. X                 {
  1197. X                   if (key->af_lpos++ == list->af_listlen-1)
  1198. X                 SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1199. X                 }
  1200. X               break;
  1201. X    default: SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1202. X    }
  1203. X    }
  1204. X  else
  1205. X    {
  1206. X      if (af_buildkey (list, gen, rev, key) == ERROR)
  1207. X    SFAIL ("getkey", "", AF_ENOREV, ERROR);
  1208. X    }
  1209. X
  1210. X  list->af_refcount++;
  1211. X  VATTR(key).af_nlinks++;
  1212. X  return (AF_OK);
  1213. X}
  1214. X
  1215. X
  1216. X/*====================================================================
  1217. X *    af_dropkey
  1218. X *
  1219. X *====================================================================*/
  1220. X
  1221. XEXPORT af_dropkey (key)
  1222. X     Af_key *key;
  1223. X{
  1224. X  if (af_keytest (key))
  1225. X    SFAIL ("dropkey", "", AF_EINVKEY, ERROR);
  1226. X
  1227. X  /* decrease reference count in corresponding archive and in attrbuf */
  1228. X  if (--(key->af_ldes)->af_refcount <= 0)
  1229. X    (void) af_detlist (key->af_ldes);
  1230. X  else
  1231. X    VATTR(key).af_nlinks--;
  1232. X  return (AF_OK);
  1233. X}
  1234. X
  1235. X
  1236. X/*====================================================================
  1237. X *    af_initattrs
  1238. X *
  1239. X *====================================================================*/
  1240. X
  1241. XEXPORT af_initattrs (attrs)
  1242. X     Af_attrs *attrs;
  1243. X{
  1244. X  attrs->af_host[0] = '\0';
  1245. X  attrs->af_syspath[0] = '\0';
  1246. X  attrs->af_name[0] = '*';
  1247. X  attrs->af_name[1] = '\0';
  1248. X  attrs->af_type[0] = '*';
  1249. X  attrs->af_type[1] = '\0';
  1250. X  attrs->af_gen = AF_NOVNUM;
  1251. X  attrs->af_rev = AF_NOVNUM;
  1252. X  attrs->af_variant[0] = '\0';
  1253. X  attrs->af_state = AF_NOSTATE;
  1254. X  attrs->af_owner.af_username[0] = '\0';
  1255. X  attrs->af_owner.af_userhost[0] = '\0';
  1256. X  attrs->af_author.af_username[0] = '\0';
  1257. X  attrs->af_author.af_userhost[0] = '\0';
  1258. X  attrs->af_size = AF_NOSIZE;
  1259. X  attrs->af_mode = AF_NOMODE;
  1260. X  attrs->af_locker.af_username[0] = '\0';
  1261. X  attrs->af_locker.af_userhost[0] = '\0';
  1262. X  attrs->af_mtime = AF_NOTIME;
  1263. X  attrs->af_atime = AF_NOTIME;
  1264. X  attrs->af_ctime = AF_NOTIME;
  1265. X  attrs->af_stime = AF_NOTIME;
  1266. X  attrs->af_ltime = AF_NOTIME;
  1267. X  attrs->af_udattrs[0] = (char *)0;
  1268. X}
  1269. X
  1270. END_OF_FILE
  1271. if test 16910 -ne `wc -c <'src/afs/afretr.c'`; then
  1272.     echo shar: \"'src/afs/afretr.c'\" unpacked with wrong size!
  1273. fi
  1274. # end of 'src/afs/afretr.c'
  1275. fi
  1276. if test -f 'src/afsit/rcsit.c' -a "${1}" != "-c" ; then 
  1277.   echo shar: Will not clobber existing file \"'src/afsit/rcsit.c'\"
  1278. else
  1279. echo shar: Extracting \"'src/afsit/rcsit.c'\" \(16773 characters\)
  1280. sed "s/^X//" >'src/afsit/rcsit.c' <<'END_OF_FILE'
  1281. X/*
  1282. X * $Header: rcsit.c,v 1.20 87/05/04 21:50:53 src Exp $
  1283. X *---------------------------------------------------------
  1284. X * $Source: /src/tools/rcs/src/rcsit/RCS/rcsit.c,v $
  1285. X * $Revision: 1.20 $
  1286. X * $Date: 87/05/04 21:50:53 $
  1287. X * $State: Exp $
  1288. X * $Author: src $
  1289. X * $Locker: src $
  1290. X *---------------------------------------------------------
  1291. X * Michael Cooper (mcooper@usc-oberon.arpa)
  1292. X * University of Southern California,
  1293. X * University Computing Services,
  1294. X * Los Angeles, California,   90089-0251
  1295. X * (213) 743-3469
  1296. X *---------------------------------------------------------
  1297. X *
  1298. X * $Log:    rcsit.c,v $
  1299. X * Revision 1.20  87/05/04  21:50:53  src
  1300. X * added -F - flag. This option causes an additional header field for
  1301. X * inclusion of compile-time options into object-files to be inserted
  1302. X * into the C-source. The man-entry is also updated.
  1303. X * 
  1304. X * Revision 1.19  86/06/12  20:29:43  src
  1305. X * The previous version was unable to look up templates in the 
  1306. X * directory $TEMPLATES, when -t - option is absent but the
  1307. X * environment-variable TEMPLATES is set. Fixed that. If no -t - option
  1308. X * was given, but $TEMPLATES is non NULL, then -t is assumed and
  1309. X * $TEMPLATES is used as path to template-files.
  1310. X * 
  1311. X * Revision 1.18  85/11/26  17:03:32  mcooper
  1312. X * Change message telling of what header was added.
  1313. X * 
  1314. X * Revision 1.17  85/11/26  16:40:55  mcooper
  1315. X * Changed the default -t option to FALSE.
  1316. X * Added specifying directory to look for .template.*
  1317. X * files in via -tdirectory.
  1318. X * 
  1319. X * Revision 1.16  85/11/11  21:35:34  mcooper
  1320. X * Added call to access() to see if the file
  1321. X * could be read.
  1322. X * 
  1323. X * Revision 1.15  85/11/11  21:22:33  mcooper
  1324. X * Changed comment char for fortran files
  1325. X * from "*" to "c".  This is what RCS uses.
  1326. X * 
  1327. X * Revision 1.14  85/11/11  20:08:43  mcooper
  1328. X * Added descriptions for fortran (.f) files.
  1329. X * 
  1330. X * Revision 1.13  85/11/11  19:52:17  mcooper
  1331. X * Modified default header templates to not bother specifying
  1332. X * the RCS file name of the file.  co(1) worries about it.
  1333. X * 
  1334. X * Revision 1.12  85/10/27  19:10:07  mcooper
  1335. X * Fixed bug that would not use template files if a file
  1336. X * type was forced with -c, -h, etc.
  1337. X * 
  1338. X * Revision 1.11  85/10/27  18:48:27  mcooper
  1339. X * Extended template file.  You can now have template
  1340. X * files describing all the types of files that
  1341. X * rcsit "knows" about.  The file $HOME/.template.*
  1342. X * (where ``*'' is a ``.'' suffix rcsit can guess at or
  1343. X * the type of file that is specified with an override)
  1344. X * is checked for existance.  If not present, the default
  1345. X * header (built into rcsit) will be used.
  1346. X * 
  1347. X * Revision 1.10  85/10/27  16:15:53  mcooper
  1348. X * Added printing of what rcsit is doing if tflag is
  1349. X * true.  Also added new headers.
  1350. X * 
  1351. X * Revision 1.9  85/10/27  14:47:39  mcooper
  1352. X * Added new template feature.  If the file
  1353. X * .template exists in the users HOME directory,
  1354. X * then that file is used as the header file instead
  1355. X * of the defaults for each type of file.  This can
  1356. X * be disabled with the -t option in case the file
  1357. X * is say a shell script.  With the template feature
  1358. X * turned off, the auto guessing is re-inabled.
  1359. X * Also, rcsit now removes its temporary files.
  1360. X * 
  1361. X * Revision 1.8  85/09/28  14:11:45  mcooper
  1362. X * Added feature: if the environment variable RCSDIR is
  1363. X * present, rcsit will attempt to make a symbolic
  1364. X * link to the directory when the -I flag is used.
  1365. X * This is done only when -I is specified AND the 
  1366. X * directory RCS is not present.  You may disable this
  1367. X * feature with the -d option.  Note also that if RCSDIR
  1368. X * is not in the environment and the above conditions
  1369. X * are true, that a normal directory called RCS will
  1370. X * be created.
  1371. X * 
  1372. X * Revision 1.7  85/09/19  15:59:53  mcooper
  1373. X * Kludge part 2 -- If you specify a ci -l of a
  1374. X * man file, then the header is messed up. 
  1375. X * Fix: After initializing the comment string,
  1376. X * unlink the file and then run co -l.
  1377. X * 
  1378. X * Revision 1.6  85/09/19  15:39:57  mcooper
  1379. X * Now knows about ``Manual'' type files.
  1380. X * 
  1381. X * Revision 1.5  85/09/19  14:23:24  mcooper
  1382. X * Added lineprint() function to print things out
  1383. X * nicely.  Fixed bug for Manual type files.  Due
  1384. X * to the fact that RCS does not not the suffixes of
  1385. X * manuals, it therefor does not know what kind of
  1386. X * comment string to use.  Thus, I kludge by running
  1387. X * a ``rcs -c`... ' file'' to tell rcs the comment
  1388. X * string.
  1389. X * 
  1390. X * Revision 1.4  85/09/19  13:28:22  mcooper
  1391. X * Fixed bug in auto_guess.  Would not continue through function
  1392. X * when file type was ``Makefile''.
  1393. X * 
  1394. X * Revision 1.3  85/09/19  13:19:50  mcooper
  1395. X * Added ``Shell Script'' file type.
  1396. X * 
  1397. X * Revision 1.2  85/09/19  10:08:36  mcooper
  1398. X * Added code to run RCS commands (rcs & ci) on files.
  1399. X * Fixed bug that limited number of command line files specified to
  1400. X * nine.  Several other minor fixes and improvements.
  1401. X * 
  1402. X * Revision 1.1  85/09/17  11:33:33  mcooper
  1403. X * Initial revision
  1404. X * 
  1405. X */
  1406. X
  1407. X/*
  1408. X * rcsit --     Prepare files for RCS.  rcsit puts the correct headings
  1409. X *        at the top of files to prepare them for RCS headings
  1410. X *        and log tracking.
  1411. X *
  1412. X * Michael Cooper    (mcooper@usc-oberon.arpa)
  1413. X * University Computing Services, USC
  1414. X *
  1415. X * 9-16-85
  1416. X */
  1417. X
  1418. X#include <sys/file.h>
  1419. X#include <stdio.h>
  1420. X#include <ctype.h>
  1421. X#include <strings.h>
  1422. X
  1423. X#ifdef NULL
  1424. X#undef NULL
  1425. X#endif
  1426. X#define NULL        '\0'
  1427. X#define LENGTH        512        /* length of line */
  1428. X#define TRUE        1
  1429. X#define FALSE        0
  1430. X
  1431. X#ifdef DEBUG
  1432. X int debugon = TRUE;
  1433. X#else
  1434. X int debugon = FALSE;
  1435. X#endif
  1436. X
  1437. Xstatic char     *progname;        /* program name */
  1438. Xstatic char     *rcsdir;
  1439. X
  1440. X/*
  1441. X * Messages to be printed for the user.
  1442. X */
  1443. Xstatic char    *msg_name;        
  1444. Xstatic char     *m_stdc = "Standard C",
  1445. X                *m_stdcflg = "Standard C with compile flags",
  1446. X        *m_include = "C Include",
  1447. X        *m_fortran = "Fortran",
  1448. X        *m_pascal = "Pascal",
  1449. X        *m_make    = "Makefile",
  1450. X        *m_shell = "Shell Script",
  1451. X        *m_manual = "Manual";
  1452. X
  1453. X/*
  1454. X * The headers to put at the beginning of the file(s).
  1455. X * Notice that the words Header and Log do not appear here
  1456. X * because RCS will put in the keyword substitutions when rcsit.c
  1457. X * is co'ed.
  1458. X */
  1459. Xstatic char    *header;
  1460. X#ifdef AFSIT
  1461. Xstatic char    *h_stdc = 
  1462. X    "#ifndef lint\nstatic char *AFSid = \"$%s$\";\n#endif\n/*\n * $%s$\n */\n\n";
  1463. Xstatic char    *h_stdcflg = 
  1464. X    "#ifndef lint\nstatic char *AFSid = \"$%s$\";\n#ifdef CFFLGS\n\
  1465. Xstatic char *ConfFlg = CFFLGS;\n\t/* should be defined from within\
  1466. X Makefile */\n#endif\n#endif\n/*\n * $%s$\n */\n\n";
  1467. X#else
  1468. Xstatic char    *h_stdc = 
  1469. X    "#ifndef lint\nstatic char *RCSid = \"$%s$\";\n#endif\n/*\n * $%s$\n */\n\n";
  1470. Xstatic char    *h_stdcflg = 
  1471. X    "#ifndef lint\nstatic char *RCSid = \"$%s$\";\n#ifdef CFFLGS\n\
  1472. Xstatic char *ConfFlg = CFFLGS;\n\t/* should be defined from within\
  1473. X Makefile */\n#endif\n#endif\n/*\n * $%s$\n */\n\n";
  1474. X#endif
  1475. Xstatic char    *h_include = 
  1476. X    "/*\n * $%s$\n *\n * $%s$\n */\n\n";
  1477. Xstatic char    *h_make =
  1478. X    "#\n# $%s$\n#\n# $%s$\n#\n";
  1479. Xstatic char     *h_manual =
  1480. X    "...\n... $%s$\n... \n... $%s$\n...\n";
  1481. Xstatic char     *h_fortran =
  1482. X    "c\nc $%s$\nc\nc $%s$\nc\n";
  1483. X
  1484. X/*
  1485. X * Template file names
  1486. X */
  1487. Xstatic char    *template_c     = ".template.c";    /* .c template */
  1488. Xstatic char     *template_h     = ".template.h";    /* .h template */
  1489. Xstatic char     *template_f     = ".template.f";    /* .f template */
  1490. Xstatic char     *template_p     = ".template.p";    /* .p template */
  1491. Xstatic char     *template_man     = ".template.man";    /* man template */
  1492. Xstatic char    *template_make    = ".template.make";    /* make template */
  1493. Xstatic char    *template_sh    = ".template.sh";    /* sh script template */
  1494. Xstatic char    *tpath;                    /* path to template */
  1495. Xstatic char    tfile[BUFSIZ];                /* template file */
  1496. Xstatic char    tbuf[BUFSIZ];                /* current tfile */
  1497. X
  1498. X/*
  1499. X * Command line flags
  1500. X */
  1501. Xint    Iflag    = FALSE;            /* run ci(1) */
  1502. Xint    rcsflag = FALSE;            /* run rcs(1) */
  1503. Xint    aflag    = TRUE;                /* do auto guess */
  1504. Xint    dflag    = TRUE;                /* creat RCS dir. */
  1505. Xint    qflag    = FALSE;            /* be quiet! */
  1506. Xint     cflag    = FALSE;            /* std c file */
  1507. Xint    fflag    = FALSE;            /* fortran file */
  1508. Xint     Fflag   = FALSE;                        /* insert C-Flags header */
  1509. Xint    pflag    = FALSE;            /* pascal file */
  1510. Xint    hflag    = FALSE;            /* include file */
  1511. Xint    sflag    = FALSE;            /* shell script */
  1512. Xint     mflag    = FALSE;            /* Makefile */
  1513. Xint    Mflag    = FALSE;            /* manual */
  1514. Xint    tflag    = FALSE;            /* template flag */
  1515. X
  1516. Xmain(argc, argv)
  1517. Xint    argc;
  1518. Xchar     *argv[];
  1519. X{
  1520. X    int x;
  1521. X    char    tmp[LENGTH];
  1522. X    char    *file;
  1523. X    char    *flags;
  1524. X    char     tmpfile[32];
  1525. X    char    *cp;
  1526. X    char     *mktemp();
  1527. X    char    *gettmp();
  1528. X    char    *getenv();
  1529. X    FILE     *fd, 
  1530. X        *fdtmp,
  1531. X        *fopen();
  1532. X
  1533. X    progname = (cp = rindex (argv[0], '/')) ? ++cp : argv[0];
  1534. X    sprintf (tmpfile, "/tmp/%sXXXXXX", progname);
  1535. X    for (x = 1; x < argc; x++) {
  1536. X        if (argv[x][0] != '-')
  1537. X            break;
  1538. X        switch (argv[x][1]) {
  1539. X            case 'a':
  1540. X                aflag = FALSE;
  1541. X                break;
  1542. X            case 'q':
  1543. X                qflag = TRUE;
  1544. X                break;
  1545. X            case 'd':
  1546. X                dflag = FALSE;
  1547. X                break;
  1548. X            case 'f':
  1549. X                fflag = TRUE;
  1550. X                break;
  1551. X                        case 'F':
  1552. X                Fflag = TRUE;
  1553. X                cflag = TRUE; /* Only for C-files yet */
  1554. X                break;
  1555. X            case 'h':
  1556. X                hflag = TRUE;
  1557. X                break;
  1558. X            case 's':
  1559. X                sflag = TRUE;    
  1560. X                break;
  1561. X            case 'm':
  1562. X                mflag = TRUE;
  1563. X                break;
  1564. X            case 'M':
  1565. X                Mflag = TRUE;
  1566. X                break;
  1567. X            case 'i':
  1568. X            case 'I':
  1569. X                Iflag = TRUE;
  1570. X                flags = &argv[x][2];
  1571. X                break;
  1572. X            case 'r':
  1573. X            case 'R':
  1574. X                rcsflag = TRUE;
  1575. X                flags = &argv[x][2];
  1576. X                break;
  1577. X            case 't':
  1578. X                tflag = TRUE;
  1579. X                tpath = &argv[x][2];
  1580. X                break;
  1581. X            case 'c':
  1582. X                cflag = TRUE;
  1583. X                break;
  1584. X            default:
  1585. X                fatal("Unknown flag %s.",argv);
  1586. X        }
  1587. X    }
  1588. X    argc -= (x - 1);
  1589. X    argv += (x - 1);
  1590. X
  1591. X    if((hflag && (mflag || Mflag || cflag)) ||
  1592. X        (mflag && (hflag || cflag || Mflag)) ||
  1593. X        (Mflag && (cflag || hflag || mflag)) ||
  1594. X        (cflag && (hflag || Mflag || mflag))) {
  1595. X            fatal("Only ONE of -c,-f,-m,-M,-h,-s may be specified.");
  1596. X    }
  1597. X    if(Iflag && rcsflag) {
  1598. X            fatal("Only ONE of ``-i'' and ``-r'' may be specified.");
  1599. X    }
  1600. X
  1601. X    if(cflag || hflag || mflag || Mflag || fflag || sflag)
  1602. X        aflag = FALSE;
  1603. X
  1604. X    if((rcsdir = getenv("RCSDIR")) == NULL)
  1605. X        rcsdir = "RCS";
  1606. X    if(Iflag && dflag)
  1607. X        checkdir();    /* Make RCS directory for ci */
  1608. X    if((!tflag) && ((tpath = getenv ("TEMPLATE")) != NULL))
  1609. X            tflag = TRUE;   /* fixed by axel@coma.uucp */
  1610. X    if((*tpath == NULL) && ((tpath = getenv("TEMPLATE")) == NULL))
  1611. X        if((tpath = getenv("HOME")) == NULL)
  1612. X            fatal("Cannot find environment variable HOME or TEMPLATE");
  1613. X
  1614. X    /*
  1615. X     * make tmp file once.
  1616. X     */
  1617. X    mktemp(tmpfile);
  1618. X
  1619. X    while (--argc) {    /* Main loop */
  1620. X        file = *++argv;
  1621. X        debug(sprintf(tmp, "...file (*++argv) = %s...", file));
  1622. X
  1623. X        if(access(file, 4) != 0)
  1624. X            fatal("Cannot access %s.  No read permission OR file does not exist.",
  1625. X                file);
  1626. X        if((fdtmp = fopen(tmpfile, "w")) == NULL) {
  1627. X            fatal("Cannot open tmpfile (%s).", tmpfile);
  1628. X        }
  1629. X
  1630. X        if(aflag)
  1631. X            auto_guess(file); /* try and guess file type */
  1632. X        else
  1633. X            set_flags();      /* check and set flags */
  1634. X
  1635. X        if(tflag) {
  1636. X            /*
  1637. X             * first get names of templates, then create
  1638. X             * path name to it.
  1639. X             */
  1640. X            get_temp();
  1641. X            sprintf(tfile, "%s/%s", tpath, tbuf);
  1642. X        }
  1643. X        if(access(tfile, 0) == 0 && tflag) {
  1644. X            if(!qflag || debugon)
  1645. X                printf("Adding %s header file to %s...",
  1646. X                    msg_name, file);
  1647. X            copy(tfile, tmpfile, "w");
  1648. X            copy(file, tmpfile, "a");
  1649. X        } else {
  1650. X            if(!qflag || debugon)
  1651. X                printf(
  1652. X                "Adding default header (%s format) to %s...",
  1653. X                    msg_name, file);
  1654. X            /*
  1655. X             * put the Keywords into header string
  1656. X             */
  1657. X#ifdef AFSIT
  1658. X            sprintf(tmp, header, "__Header", "__Log");
  1659. X#else
  1660. X            sprintf(tmp, header, "Header", "Log");
  1661. X#endif
  1662. X            fputs(tmp, fdtmp);
  1663. X            /*
  1664. X             * fclose'em, just in case.
  1665. X             */
  1666. X            fclose(fdtmp);
  1667. X            copy(file, tmpfile, "a");
  1668. X        }
  1669. X        unlink(file);
  1670. X        copy(tmpfile, file, "w");
  1671. X        unlink(tmpfile);
  1672. X
  1673. X        if(!qflag || debugon)
  1674. X            printf("done.\n");
  1675. X        if (Fflag)
  1676. X          puts ("-> Don't forget to define CFFLGS on compiler\
  1677. X commandline <-\n");
  1678. X
  1679. X        if(Iflag){
  1680. X            rcs("ci", file, flags);
  1681. X            if(Mflag){    /* kludge to tell rcs about manuals */
  1682. X                rcs("rcs", file, "c'... '");
  1683. X                /*
  1684. X                 * kludge part 2 - if the user tried a ci
  1685. X                 * with a -l option, then the header is
  1686. X                 * messed up in the currently checked out
  1687. X                 * man file.  So we have to co the file to 
  1688. X                 * clean up the header.  Plus we use the
  1689. X                 * -l option of co to insure file locking.
  1690. X                 */
  1691. X                if(checkfor("l", flags)){
  1692. X                    unlink(file);
  1693. X                    rcs("co", file, "l");
  1694. X                }
  1695. X            }
  1696. X        }
  1697. X        if(rcsflag)
  1698. X            rcs("rcs", file, flags);
  1699. X    }
  1700. X}
  1701. X
  1702. X/*
  1703. X * debug - print (useless) debugging info.
  1704. X */
  1705. Xdebug(msg)
  1706. Xchar *msg;
  1707. X{
  1708. X#ifdef DEBUG
  1709. X    fprintf(stderr, msg);
  1710. X    putchar ('\n');
  1711. X#endif
  1712. X}
  1713. X
  1714. X/*
  1715. X * auto_guess - try and be intelligent and guess type of file
  1716. X *        by looking at the suffix or the whole name
  1717. X *        in the case of a makefile.
  1718. X */
  1719. X
  1720. Xauto_guess(file)
  1721. Xchar    *file;
  1722. X{
  1723. X    char *suffix;
  1724. X    char *rindex();
  1725. X
  1726. X    suffix = rindex(file, '.')+1;
  1727. X    if((strcmp(file, "makefile") == 0) || (strcmp(file, "Makefile") == 0) ||
  1728. X        (strcmp(suffix, "mk") == 0)) {    /* sys V std suffix */
  1729. X        mflag = TRUE;
  1730. X        sflag = FALSE;
  1731. X        cflag = FALSE;
  1732. X        hflag = FALSE;
  1733. X        Mflag = FALSE;
  1734. X        fflag = FALSE;
  1735. X    }
  1736. X    if((strcmp(suffix, "sh") == 0) || (strcmp(suffix, "csh") == 0)) {
  1737. X        sflag = TRUE;
  1738. X        cflag = FALSE;
  1739. X        hflag = FALSE;
  1740. X        mflag = FALSE;
  1741. X        Mflag = FALSE;
  1742. X        fflag = FALSE;
  1743. X    }
  1744. X    if(strcmp(suffix, "c") == 0){
  1745. X        cflag = TRUE;
  1746. X        hflag = FALSE;
  1747. X        mflag = FALSE;
  1748. X        Mflag = FALSE;
  1749. X        sflag = FALSE;
  1750. X        fflag = FALSE;
  1751. X    }
  1752. X    if(strcmp(suffix, "h") == 0){
  1753. X        hflag = TRUE;
  1754. X        cflag = FALSE;
  1755. X        mflag = FALSE;
  1756. X        Mflag = FALSE;
  1757. X        sflag = FALSE;
  1758. X        fflag = FALSE;
  1759. X    }
  1760. X    if(strcmp(suffix, "f") == 0){
  1761. X        fflag = TRUE;
  1762. X        hflag = FALSE;
  1763. X        cflag = FALSE;
  1764. X        mflag = FALSE;
  1765. X        Mflag = FALSE;
  1766. X        sflag = FALSE;
  1767. X    }
  1768. X    if(isdigit(*suffix) != 0) {
  1769. X        Mflag = TRUE;
  1770. X        hflag = FALSE;
  1771. X        cflag = FALSE;
  1772. X        mflag = FALSE;
  1773. X        sflag = FALSE;
  1774. X        fflag = FALSE;
  1775. X    }
  1776. X    set_flags();
  1777. X    if(!qflag || debugon)
  1778. X        printf("Hmm.  This file looks like a %s file.\n", msg_name);
  1779. X}
  1780. X
  1781. X/*
  1782. X * set_flags - set & check flags
  1783. X */
  1784. Xset_flags()
  1785. X{
  1786. X    if(cflag || hflag || mflag || Mflag || sflag || fflag) {
  1787. X        if(cflag) {
  1788. X            msg_name = m_stdc;
  1789. X            header = h_stdc;
  1790. X        }
  1791. X        if (Fflag) { /* This is more than just cflag - axel@coma */
  1792. X                msg_name = m_stdcflg;
  1793. X            header = h_stdcflg;
  1794. X        }
  1795. X        if(hflag) {
  1796. X            msg_name = m_include;
  1797. X            header = h_include;
  1798. X        }
  1799. X        if(mflag) {
  1800. X            msg_name = m_make;
  1801. X            header = h_make;
  1802. X        }
  1803. X        if(Mflag) {
  1804. X            msg_name = m_manual;
  1805. X            header = h_manual;
  1806. X        }
  1807. X        if(sflag) {
  1808. X            msg_name = m_shell;
  1809. X            header = h_make;
  1810. X        }
  1811. X        if(fflag) {
  1812. X            msg_name = m_fortran;
  1813. X            header = h_fortran;
  1814. X        }
  1815. X    } else {
  1816. X        cflag = TRUE;
  1817. X        set_flags();
  1818. X    }
  1819. X}
  1820. X
  1821. X/*
  1822. X * copy from -> to
  1823. X */
  1824. X
  1825. Xcopy(from, to, mode)
  1826. Xchar *from;
  1827. Xchar *to;
  1828. Xchar *mode;
  1829. X{
  1830. X    FILE *fdfrom, *fdto, *fopen();
  1831. X    char tmp[LENGTH];
  1832. X    char s[LENGTH];
  1833. X
  1834. X    if((fdfrom = fopen(from, "r")) == NULL) {
  1835. X        fatal("Cannot open %s for reading.",from);
  1836. X    }
  1837. X    if((fdto = fopen(to, mode)) == NULL) {
  1838. X        fatal("Cannot open %s for \"%s\".",to,mode);
  1839. X    }
  1840. X    while(fgets(s, sizeof(s), fdfrom) != NULL)
  1841. X        fputs(s, fdto);
  1842. X    fclose(fdfrom);
  1843. X    fclose(fdto);
  1844. X}
  1845. X
  1846. X/*
  1847. X * Run RCS's rcsprog on file with flags.
  1848. X */
  1849. X
  1850. Xrcs(rcsprog, file, flags)
  1851. Xchar *rcsprog;
  1852. Xchar *file;
  1853. Xchar *flags;
  1854. X{
  1855. X    char buf[LENGTH];
  1856. X    char tmp[LENGTH];
  1857. X
  1858. X    if(!checkfor("q", flags) && qflag)
  1859. X        flags = "q";
  1860. X    if(strcmp(flags, NULL) == 0)
  1861. X        sprintf(buf, "%s %s", rcsprog, file);
  1862. X    else
  1863. X        sprintf(buf, "%s -%s %s", rcsprog, flags, file);
  1864. X    debug(sprintf(tmp,"Running ``%s''...\n", buf));
  1865. X    if(!qflag)
  1866. X        lineprint(sprintf(tmp, "Start of ``%s''", buf));
  1867. X    system(buf);
  1868. X    if(!qflag)
  1869. X        lineprint(sprintf(tmp, "End of ``%s''", buf));
  1870. X}
  1871. X
  1872. X/*
  1873. X * checkdir - make RCS directory if not present.
  1874. X */
  1875. X
  1876. Xcheckdir()
  1877. X{
  1878. X    if(access("RCS", 0) != 0){
  1879. X        if(!qflag || debugon)
  1880. X            printf("Cannot find \"RCS\" directory.  Creating...\n");
  1881. X        if(strcmp(rcsdir, "RCS") != 0) { 
  1882. X            if(symlink(rcsdir, "RCS") != 0)
  1883. X                fatal("Symbolic link of %s to RCS failed.", 
  1884. X                    rcsdir);
  1885. X        } else {
  1886. X            if(mkdir(rcsdir, 0755) != 0)
  1887. X                fatal("Cannot create \"%s\" directory.", 
  1888. X                    rcsdir);
  1889. X        }
  1890. X    }
  1891. X}
  1892. X
  1893. X/*
  1894. X * checkfor(x, str) -- check for x in str.  Return 1 (TRUE) if exists.
  1895. X *            Otherwise 0 (FALSE).
  1896. X */
  1897. X
  1898. Xcheckfor(x, str)
  1899. Xchar     *x;
  1900. Xchar     *str;
  1901. X{
  1902. X    while(*str) {
  1903. X        if(strcmp(str, x) == 0)
  1904. X            return(TRUE);
  1905. X        *str++;
  1906. X    }
  1907. X    return(FALSE);
  1908. X}
  1909. X
  1910. X/*
  1911. X * lineprint - print msg in a nice line
  1912. X */
  1913. X
  1914. Xlineprint(msg)
  1915. Xchar *msg;
  1916. X{
  1917. X    int len, left, right, x;
  1918. X
  1919. X    len = strlen(msg);
  1920. X    right = (75-len)/2;
  1921. X    left = right;
  1922. X    for(x = 0; x < right; ++x)
  1923. X        putchar('-');
  1924. X    printf("[ %s ]", msg);
  1925. X    for(x = 0; x < left; ++x)
  1926. X        putchar('-');
  1927. X    putchar('\n');
  1928. X}
  1929. X
  1930. X/*
  1931. X * fatal - print error and then exit(1).
  1932. X */
  1933. Xfatal(format, str)
  1934. Xchar *format;
  1935. X{
  1936. X    static char namefmt[100];
  1937. X
  1938. X    sprintf(namefmt, "%s: %s\n", progname, format);
  1939. X    _doprnt(namefmt, &str, stderr);
  1940. X    exit(1);
  1941. X}
  1942. X
  1943. X/*
  1944. X * zap str with NULL's
  1945. X */
  1946. X
  1947. Xzap(str)
  1948. Xchar str[];
  1949. X{
  1950. X    int i, x;
  1951. X
  1952. X    i = strlen(str);
  1953. X    for(x = 0; x <= i; )
  1954. X        str[x++] = NULL;
  1955. X}
  1956. X
  1957. X/*
  1958. X * get template names
  1959. X */
  1960. X
  1961. Xget_temp()
  1962. X{
  1963. X    zap(tbuf);
  1964. X    if(mflag)
  1965. X        strcpy(tbuf, template_make);
  1966. X    if(Mflag)
  1967. X        strcpy(tbuf, template_man);
  1968. X    if(hflag)
  1969. X        strcpy(tbuf, template_h);
  1970. X    if(cflag)
  1971. X        strcpy(tbuf, template_c);
  1972. X    if(sflag)
  1973. X        strcpy(tbuf, template_sh);
  1974. X    if(fflag)
  1975. X        strcpy(tbuf, template_f);
  1976. X}
  1977. END_OF_FILE
  1978. if test 16773 -ne `wc -c <'src/afsit/rcsit.c'`; then
  1979.     echo shar: \"'src/afsit/rcsit.c'\" unpacked with wrong size!
  1980. fi
  1981. # end of 'src/afsit/rcsit.c'
  1982. fi
  1983. echo shar: End of archive 18 \(of 33\).
  1984. cp /dev/null ark18isdone
  1985. MISSING=""
  1986. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  1987.     if test ! -f ark${I}isdone ; then
  1988.     MISSING="${MISSING} ${I}"
  1989.     fi
  1990. done
  1991. if test "${MISSING}" = "" ; then
  1992.     echo You have unpacked all 33 archives.
  1993.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1994. else
  1995.     echo You still need to unpack the following archives:
  1996.     echo "        " ${MISSING}
  1997. fi
  1998. ##  End of shell archive.
  1999. exit 0
  2000.