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

  1. Subject:  v19i029:  A software configuration management system, Part16/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 29
  8. Archive-name: shape/part16
  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 16 (of 33)."
  19. # Contents:  src/afs/afenviron.c src/misc/citeattr.c src/vc/vlmisc.c
  20. # Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:08 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'src/afs/afenviron.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'src/afs/afenviron.c'\"
  24. else
  25. echo shar: Extracting \"'src/afs/afenviron.c'\" \(15493 characters\)
  26. sed "s/^X//" >'src/afs/afenviron.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 *    afenviron.c -- communication with the UNIX-Filesystem
  58. X *
  59. X *    Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
  60. X *                      (andy@db0tui62.BITNET)
  61. X *
  62. X *    $Header: afenviron.c[1.6] Wed Feb 22 16:27:29 1989 andy@coma published $
  63. X *
  64. X *    EXPORT:
  65. X *      af_uniqpath -- build unified pathname
  66. X *    af_setarchpath -- name directory where archives shall be stored
  67. X *      af_isarchive -- test if a given file is an archive
  68. X *    af_garname -- build name for archive file
  69. X *    af_garown -- get owner of archive file
  70. X *    af_gbpname -- build name for binary pool db-file
  71. X *    af_gtmpname -- build name for tmp file
  72. X *    af_gbusname -- build name of busy version
  73. X *    af_afpath -- build af-syspath from UNIX-filename
  74. X *    af_afname -- build af-filename from UNIX-filename
  75. X *    af_aftype -- build af-filetype from UNIX-filename
  76. X *    af_unixname -- build UNIX-filename from af-filename/type
  77. X *      af_gmaxbpsize -- get max. number of files in binary pool
  78. X *      af_bpfilename -- return filename for binary pool file
  79. X *      af_rbphashname -- get unique filename for file in binary pool
  80. X *    af_getuid -- returns uid of user if from local host
  81. X *    af_getgid -- returns gid of user if from local host
  82. X *    af_getuser -- returns name and host of caller
  83. X */
  84. X
  85. X#include <stdio.h>
  86. X#include <pwd.h>
  87. X#include <string.h>
  88. X#ifdef SUNOS_4_0
  89. X#include <strings.h>
  90. X#endif
  91. X#include <sys/file.h>
  92. X#include <sys/types.h>
  93. X#include <sys/stat.h>
  94. X
  95. X#include "typeconv.h"
  96. X#include "afsys.h"
  97. X#include "afs.h"
  98. X#include "afarchive.h"
  99. X
  100. Xchar  *malloc();
  101. X
  102. X/*================================================================
  103. X *    af_uniqpath -- build unified pathname
  104. X *
  105. X *================================================================*/
  106. X
  107. XEXPORT char *af_uniqpath (path)
  108. X     char *path;
  109. X{
  110. X  static char uniqpath[4*MAXNAMLEN], tmppath[4*MAXNAMLEN];
  111. X  char        *p, *u, *getwd();
  112. X
  113. X  if ((path == (char *)0) || (path[0] == '\0') || ((path[0] == '.' && path[1] == '\0')))
  114. X    return (getwd (uniqpath));
  115. X
  116. X  /* build absolute pathname if only a relative one is given */
  117. X  if (path[0] != '/')
  118. X    {
  119. X      if (!strcmp (path, ".."))
  120. X    {
  121. X      (void) getwd (uniqpath);
  122. X      if ((p = rindex (uniqpath, '/')) == uniqpath)
  123. X        uniqpath[1] = '\0';
  124. X      else
  125. X        *p = '\0';
  126. X      return (uniqpath);
  127. X    }
  128. X      (void) getwd (tmppath);
  129. X      (void) strcat (tmppath, "/");
  130. X      (void) strcat (tmppath, path);
  131. X      p = tmppath;
  132. X    }
  133. X  else
  134. X    p = path;
  135. X
  136. X  /* eliminate things like "/usr/./bin" and "/usr/../usr/bin" */
  137. X  u = uniqpath;
  138. X  *u = '/';
  139. X  while (*p)
  140. X    {
  141. X      if ((p[0] == '/') && (p[1] == '.'))
  142. X    {
  143. X      if ((p[2] == '/') || (p[2] == '\0'))
  144. X        {
  145. X          p = &p[2];
  146. X          continue;
  147. X        }
  148. X      else
  149. X        if ((p[2] == '.') && ((p[3] == '/') || (p[3] == '\0')))
  150. X          {
  151. X        if (u != uniqpath)
  152. X          do { *u = '\0'; u--; } while (*u != '/');
  153. X        p = &p[3];
  154. X        continue;
  155. X          }
  156. X    }
  157. X      u++;
  158. X      *u = p[1];
  159. X      p++;
  160. X    }
  161. X  
  162. X  /* cut slash if present at the end */
  163. X  u--;
  164. X  if ((u != uniqpath) && (*u == '/'))
  165. X    *u = '\0';
  166. X  else
  167. X    u[1] = '\0';
  168. X
  169. X  return (uniqpath);
  170. X}
  171. X
  172. Xstatic char archpath[4*MAXNAMLEN] = "\0";
  173. X
  174. X/*================================================================
  175. X *    af_setarchpath
  176. X *
  177. X *================================================================*/
  178. X
  179. XEXPORT af_setarchpath (pathname)
  180. X     char *pathname;
  181. X{
  182. X  if (pathname == (char *)0)
  183. X    archpath[0] = '\0';
  184. X  else
  185. X    (void) strcpy (archpath, af_uniqpath (pathname));
  186. X}
  187. X
  188. X
  189. X/*====================================================================
  190. X * af_isarchive -- test if a given file is an archive
  191. X *
  192. X *====================================================================*/
  193. X
  194. XEXPORT af_isarchive (name)
  195. X     char *name;
  196. X{
  197. X  char ext;
  198. X
  199. X  if (!name || strncmp (name, AF_AFSFILEID, AF_IDSTRLEN))
  200. X    return (FALSE);
  201. X
  202. X  ext = name[strlen (name) - sizeof (char)];
  203. X  if ((ext != AF_ARCHEXT) && (ext != AF_DATAEXT))
  204. X    return (FALSE);
  205. X
  206. X  return (TRUE);
  207. X}
  208. X
  209. X
  210. X/*================================================================
  211. X *    af_garname
  212. X *
  213. X *================================================================*/
  214. X
  215. XEXPORT char *af_garname (pathname, name, type)
  216. X     char *pathname;
  217. X     char *name, *type;
  218. X{
  219. X  char arname[MAXNAMLEN*4];
  220. X
  221. X  /* see if there is an explicit pathname where archives shall be stored */
  222. X  if (archpath[0])
  223. X    (void) strcpy (arname, archpath);
  224. X  else
  225. X    (void) sprintf (arname, "%s/%s\0", NOTNIL(pathname), AF_SUBDIR);
  226. X
  227. X  if ((type != (char *)0) && (type[0] != '\0'))
  228. X    (void) sprintf (&arname[strlen (arname)], "/%s%s.%s%c\0",
  229. X         AF_AFSFILEID, NOTNIL(name), NOTNIL(type), AF_ARCHEXT);
  230. X  else
  231. X    (void) sprintf (&arname[strlen (arname)], "/%s%s%c\0",
  232. X         AF_AFSFILEID, NOTNIL(name), AF_ARCHEXT);
  233. X
  234. X  return (af_entersym (arname));
  235. X} /* af_garname */ 
  236. X
  237. X
  238. X/*================================================================
  239. X *    af_garown
  240. X *
  241. X *================================================================*/
  242. X
  243. XEXPORT Af_user *af_garown (archname, writeok)
  244. X     char    *archname;
  245. X     bool    *writeok; /* out */
  246. X{
  247. X  char ardirname[MAXNAMLEN*4], *namptr;
  248. X  struct stat ibuf;
  249. X
  250. X  /* build name of directory, where the archive is located */
  251. X  (void) strcpy (ardirname, archname);
  252. X
  253. X  /* cut name */
  254. X  namptr = rindex (ardirname, '/');
  255. X  *namptr = '\0';
  256. X
  257. X  *writeok = FALSE;
  258. X  if (stat (ardirname, &ibuf) == ERROR)
  259. X    return ((Af_user *)0);
  260. X  else
  261. X    if (!af_sysaccess (ardirname, W_OK))
  262. X      *writeok = TRUE;
  263. X
  264. X  return (af_getuser (ibuf.st_uid));
  265. X} /* af_garown */ 
  266. X
  267. X
  268. X/*================================================================
  269. X *    af_gbpname
  270. X *
  271. X *================================================================*/
  272. X
  273. XEXPORT char *af_gbpname (pathname)
  274. X     char *pathname;
  275. X{
  276. X  char bpname[MAXNAMLEN*4];
  277. X
  278. X  /* see if there is an explicit pathname where archives shall be stored */
  279. X  if (archpath[0])
  280. X    (void) strcpy (bpname, archpath);
  281. X  else
  282. X    (void) sprintf (bpname, "%s/%s/\0", pathname, AF_SUBDIR);
  283. X
  284. X  if (af_sysaccess (bpname, R_OK))
  285. X    return ((char *)0);
  286. X
  287. X  (void) strcat (bpname, AF_BPOOLNAME);
  288. X
  289. X  return (af_entersym (bpname));
  290. X} /* af_garname */ 
  291. X
  292. X
  293. X/*================================================================
  294. X *    af_gtmpname
  295. X *
  296. X *================================================================*/
  297. X
  298. Xstatic int count=0;
  299. X
  300. XEXPORT char *af_gtmpname (pathname, filename)
  301. X     /*ARGSUSED*/
  302. X     char *pathname; /* unused up to now */
  303. X     char *filename;
  304. X{
  305. X  char tmpname[MAXNAMLEN*4];
  306. X  
  307. X  (void) sprintf (tmpname, "%s/%s%d%d\0", AF_TMPDIR, filename, getpid(), count++);
  308. X  return (af_entersym (tmpname));
  309. X} /* af_gtmpname */
  310. X
  311. X
  312. X/*================================================================
  313. X *    af_gbusname
  314. X *
  315. X *================================================================*/
  316. X
  317. XEXPORT char *af_gbusname (pathname, name, type)
  318. X     char *pathname;
  319. X     char *name, *type;
  320. X{
  321. X  char busyname[MAXNAMLEN*4];
  322. X   
  323. X  (void) sprintf (busyname, "%s/%s", pathname, name);
  324. X  if ((type != (char *)0) && (type[0] != '\0'))
  325. X      {
  326. X    (void) strcat (busyname, ".");
  327. X    (void) strcat (busyname, type);
  328. X      }
  329. X  return (af_entersym (busyname));
  330. X} /* af_gbusname */ 
  331. X
  332. X
  333. X
  334. X/*================================================================
  335. X *    af_afpath
  336. X *
  337. X *================================================================*/
  338. X
  339. XEXPORT char *af_afpath (unixname)
  340. X     char *unixname;
  341. X{
  342. X  char *nameptr;
  343. X  static char afpath[MAXNAMLEN];
  344. X
  345. X  if (unixname)
  346. X    (void) strcpy (afpath, unixname);
  347. X  else
  348. X    afpath[0] = '\0';
  349. X
  350. X  /* cut name */
  351. X  if ((nameptr = rindex (afpath, '/')) != (char *)0)
  352. X    nameptr[0] = '\0';
  353. X  else
  354. X    {
  355. X      afpath[0] = '\0';
  356. X      return (afpath);
  357. X    }
  358. X
  359. X  /* cut AFS subdirectory name if present */
  360. X  if (((nameptr = rindex (afpath, '/')) != (char *)0) && 
  361. X       !strcmp (AF_SUBDIR, nameptr+1))
  362. X    nameptr[0] = '\0';
  363. X  else
  364. X    if (!strcmp (AF_SUBDIR, afpath))
  365. X      afpath[0] = '\0';
  366. X
  367. X  return (afpath);
  368. X}
  369. X
  370. X/*================================================================
  371. X *    af_afname
  372. X *
  373. X *================================================================*/
  374. X
  375. XEXPORT char *af_afname (unixname)
  376. X     char *unixname;
  377. X{
  378. X  char *typeptr, *nameptr;
  379. X  static char afname[MAXNAMLEN];
  380. X
  381. X  if (!unixname)
  382. X    {
  383. X      afname[0] = '\0';
  384. X      return (afname);
  385. X    }
  386. X
  387. X  /* set nameptr to beginning of name */
  388. X  if ((nameptr = rindex (unixname, '/')) == (char *)0)
  389. X    nameptr = unixname;
  390. X  else
  391. X    nameptr++;
  392. X
  393. X  if (af_isarchive (nameptr))
  394. X    {
  395. X      (void) strcpy (afname, nameptr + strlen (AF_AFSFILEID));
  396. X      afname[strlen (afname) - sizeof (char)] = '\0';
  397. X    }
  398. X  else
  399. X    (void) strcpy (afname, nameptr);
  400. X
  401. X  /* special handling for "." and ".." */
  402. X  if (!strcmp (afname, ".") || !strcmp (afname, ".."))
  403. X    return (afname);
  404. X
  405. X  /* if a UNIX type-extension is given -- cut it, except the dot is */
  406. X  /*                                      at position 0 (e.g. .cshrc) */
  407. X  if ((typeptr = rindex (afname, '.')) != (char *)0)
  408. X    if (typeptr != afname)
  409. X      typeptr[0] = '\0';
  410. X
  411. X  return (afname);
  412. X}
  413. X
  414. X/*================================================================
  415. X *    af_aftype
  416. X *
  417. X *================================================================*/
  418. X
  419. XEXPORT char *af_aftype (unixname)
  420. X     char *unixname;
  421. X{
  422. X  char *typeptr, *nameptr;
  423. X  static char aftype[MAXTYPLEN];
  424. X  bool isarch = FALSE;
  425. X
  426. X  if (!unixname)
  427. X    {
  428. X      aftype[0] = '\0';
  429. X      return (aftype);
  430. X    }
  431. X
  432. X  /* set nameptr to beginning of name */
  433. X  if ((nameptr = rindex (unixname, '/')) == (char *)0)
  434. X    nameptr = unixname;
  435. X  else
  436. X    nameptr++;
  437. X
  438. X  if (af_isarchive (nameptr))
  439. X    {
  440. X      nameptr += strlen (AF_AFSFILEID);
  441. X      isarch = TRUE;
  442. X    }
  443. X
  444. X  /* if there is no UNIX type-extension */
  445. X  if ((typeptr = rindex (nameptr, '.')) == (char *)0)
  446. X    aftype[0] = '\0';
  447. X  else
  448. X    {
  449. X      /* if the found dot indicates a "hidden file" (eg. .cshrc) */
  450. X      if (typeptr == nameptr)
  451. X    aftype[0] = '\0';
  452. X      else
  453. X    {
  454. X      (void) strcpy (aftype, typeptr + sizeof(char));
  455. X      /* if the named file is an archive, cut the name-extension */
  456. X      if (isarch)
  457. X        aftype [strlen (aftype) - sizeof (char)] = '\0';
  458. X    }
  459. X    }
  460. X  return (aftype);
  461. X}
  462. X
  463. X
  464. X/*================================================================
  465. X *    af_unixname
  466. X *
  467. X *================================================================*/
  468. X
  469. XEXPORT char *af_unixname (path, name, type)
  470. X     char *path, *name, *type;
  471. X{
  472. X  static char unixname[4*MAXNAMLEN];
  473. X
  474. X  if ((path == (char *)0) || (path[0] == '\0'))
  475. X    (void) strcpy (unixname, NOTNIL(name));
  476. X  else
  477. X    (void) sprintf (unixname, "%s/%s\0", path, name);
  478. X
  479. X  if ((type != (char *)0) && (type[0] != '\0'))
  480. X    {
  481. X      (void) strcat (unixname, ".");
  482. X      (void) strcat (unixname, type);
  483. X    }
  484. X  return (unixname);
  485. X}
  486. X
  487. X
  488. X/*================================================================
  489. X *      af_gmaxbpsize -- get max. number of files in binary pool
  490. X *
  491. X *================================================================*/
  492. X
  493. XEXPORT int af_gmaxbpsize (name)
  494. X     /*ARGSUSED*/
  495. X     char *name; /* unused up to now */
  496. X{
  497. X  char *envval, *getenv();
  498. X
  499. X  if (envval = getenv (AF_ENVBPSIZE))
  500. X    return (atoi (envval));
  501. X  else
  502. X    return AF_MAXBPSIZE;
  503. X}
  504. X
  505. X
  506. X/*================================================================
  507. X *    af_bpfilename
  508. X *
  509. X *================================================================*/
  510. X
  511. XEXPORT char *af_bpfilename (pathname, name)
  512. X     char *pathname, *name;
  513. X{
  514. X  static char bpname[MAXNAMLEN];
  515. X
  516. X  (void) sprintf (bpname, "%s/%s/%s\0", pathname, AF_SUBDIR, name);
  517. X  return (bpname);
  518. X}
  519. X
  520. X/*================================================================
  521. X * af_rbphashname -- get unique filename for file in binary pool
  522. X *
  523. X *================================================================*/
  524. X
  525. XEXPORT char *af_rbphashname (name, type, gen, rev, variant, list, count)
  526. X     char *name, *type, *variant;
  527. X     int  gen, rev;
  528. X     /*ARGSUSED*/
  529. X     Af_revlist *list; /* unused up to now */
  530. X     int count;
  531. X{
  532. X  char hashname[MAXNAMLEN];
  533. X
  534. X  (void) sprintf (hashname, "%s%s.%s[%d.%d]%s%d\0", AF_BPFILEID, 
  535. X       name, type, gen, rev, variant, count);
  536. X
  537. X  return (af_entersym (hashname));
  538. X}
  539. X
  540. X
  541. X/*========================================================================
  542. X *    af_getuid - returns uid of user if from local host
  543. X *                  AF_ERROR if user is unknown
  544. X *                  AF_REMOTE if user is not local
  545. X *
  546. X *========================================================================*/
  547. X
  548. XEXPORT Uid_t af_getuid (name, host)
  549. X     char *name, *host;
  550. X{
  551. X  struct passwd *pwent;
  552. X
  553. X  if (name == (char *)0) /* in this case, name and host are null pointers */
  554. X    return ((Uid_t) ERROR);
  555. X
  556. X  if (strcmp (af_gethostname(), host))
  557. X    return ((Uid_t) AF_REMOTE);
  558. X
  559. X  if ((pwent = getpwnam (name)) == (struct passwd *)0)
  560. X    FAIL ("getuid", "cannot get user ID", AF_EINTERNAL, (Uid_t) ERROR);
  561. X
  562. X  return (pwent->pw_uid);
  563. X}
  564. X
  565. X
  566. X/*========================================================================
  567. X *    af_getgid - returns gid of user if from local host
  568. X *                  AF_ERROR if user is unknown
  569. X *                  AF_REMOTE if user is not local
  570. X *
  571. X *========================================================================*/
  572. X
  573. XEXPORT Gid_t af_getgid (name, host)
  574. X     char *name, *host;
  575. X{
  576. X  struct passwd *pwent;
  577. X
  578. X  if (name == (char *)0) /* in this case, name and host are null pointers */
  579. X    return ((Gid_t) ERROR);
  580. X
  581. X  if (strcmp (af_gethostname(), host))
  582. X    return ((Gid_t) AF_REMOTE);
  583. X
  584. X  if ((pwent = getpwnam (name)) == (struct passwd *)0)
  585. X    FAIL ("getgid", "cannot get group ID", AF_EINTERNAL, (Gid_t) ERROR);
  586. X
  587. X  return (pwent->pw_gid);
  588. X}
  589. X
  590. X
  591. X/*========================================================================
  592. X *    af_getuser - returns name and host of caller
  593. X *
  594. X *========================================================================*/
  595. X
  596. Xstatic Uid_t   calleruid;
  597. Xstatic Af_user caller;
  598. Xstatic bool    initcaller = FALSE;
  599. X
  600. XEXPORT Af_user *af_getuser (uid)
  601. X     Uid_t uid;
  602. X{
  603. X  static Af_user result;
  604. X  struct passwd *pwent;
  605. X  if (!initcaller) /* if caller struct is not yet initialized */
  606. X    {
  607. X      calleruid = getuid();
  608. X      (void) strcpy (caller.af_userhost, af_gethostname ()); 
  609. X      if ((pwent = getpwuid ((int) calleruid)) == (struct passwd *)0)
  610. X    SFAIL ("getuser", "", AF_EINVUSER, (Af_user *)0);
  611. X      (void) strcpy (caller.af_username, pwent->pw_name);
  612. X      initcaller = TRUE;
  613. X    }
  614. X  if (uid == calleruid)
  615. X    return (&caller);
  616. X
  617. X  (void) strcpy (result.af_userhost, af_gethostname ()); 
  618. X  if ((pwent = getpwuid ((int) uid)) == (struct passwd *)0)
  619. X    SFAIL ("getuser", "", AF_EINVUSER, (Af_user *)0);
  620. X  (void) strcpy (result.af_username, pwent->pw_name);
  621. X
  622. X  return (&result);
  623. X}
  624. END_OF_FILE
  625. if test 15493 -ne `wc -c <'src/afs/afenviron.c'`; then
  626.     echo shar: \"'src/afs/afenviron.c'\" unpacked with wrong size!
  627. fi
  628. # end of 'src/afs/afenviron.c'
  629. fi
  630. if test -f 'src/misc/citeattr.c' -a "${1}" != "-c" ; then 
  631.   echo shar: Will not clobber existing file \"'src/misc/citeattr.c'\"
  632. else
  633. echo shar: Extracting \"'src/misc/citeattr.c'\" \(14280 characters\)
  634. sed "s/^X//" >'src/misc/citeattr.c' <<'END_OF_FILE'
  635. X/*
  636. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  637. X *  and U. Pralle
  638. X * 
  639. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  640. X * WARRANTY for any part of this software to work correctly or as described
  641. X * in the manuals. We do not accept any liability for any kind of damage
  642. X * caused by use of this software, such as loss of data, time, money, or 
  643. X * effort.
  644. X * 
  645. X * Permission is granted to use, copy, modify, or distribute any part of
  646. X * this software as long as this is done without asking for charge, and
  647. X * provided that this copyright notice is retained as part of the source
  648. X * files. You may charge a distribution fee for the physical act of
  649. X * transferring a copy, and you may at your option offer warranty
  650. X * protection in exchange for a fee.
  651. X * 
  652. X * Direct questions to: Tech. Univ. Berlin
  653. X *              Wilfried Koch
  654. X *              Sekr. FR 5-6 
  655. X *              Franklinstr. 28/29
  656. X *              D-1000 Berlin 10, West Germany
  657. X * 
  658. X *              Tel: +49-30-314-22972
  659. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  660. X */
  661. Xstatic char *AFSid = "$Header: citeattr.c[1.6] Thu Feb 23 21:24:18 1989 axel@coma published $";
  662. X
  663. X/*
  664. X * Log for /u/shape/dist-tape/src/misc/citeattr.c[1.1]
  665. X *     Thu Feb 23 21:24:18 1989 axel@coma save $
  666. X *  --- empty log message ---
  667. X *  citeattr.c[1.2] Thu Feb 23 21:24:18 1989 axel@coma save $
  668. X *  --- empty log message ---
  669. X *  citeattr.c[1.3] Thu Feb 23 21:24:18 1989 axel@coma save $
  670. X *  --- empty log message ---
  671. X *  citeattr.c[1.4] Thu Feb 23 21:24:18 1989 axel@coma published $
  672. X *  Threw out silly #ifdef BSD43 s.
  673. X *  I think there are also other changes concerning attribute citations.
  674. X *  
  675. X *  citeattr.c[1.5] Thu Feb 23 21:24:18 1989 axel@coma published $
  676. X *  --- empty log message ---
  677. X *  citeattr.c[1.6] Thu Feb 23 21:24:18 1989 axel@coma published $
  678. X *  --- empty log message ---
  679. X */
  680. X
  681. X#include <pwd.h>
  682. X#include <grp.h>
  683. X#include <stdio.h>
  684. X#include <strings.h>
  685. X#include "afs.h"
  686. X#include "afsapp.h"
  687. X#include "anames.h"
  688. X
  689. Xchar *st_table[] = {
  690. X  "busy", "save", "proposed", 
  691. X  "published", "accessed", "frozen", 
  692. X  (char *)0 
  693. X  };
  694. X
  695. XWriteXPand (buf, bufcnt, dest, curkey) 
  696. X     char *buf; int bufcnt; FILE *dest; Af_key *curkey; {
  697. X/*
  698. X *  WriteXPand scans the char buffer 'buf' to the extent of bufcnt
  699. X *  for strings of the form '$__attribute_name'. If such a string
  700. X *  is found, the buffer contents up to the character preceding the
  701. X *  first '$' will be sent to the destination output 'dest'.
  702. X *  If an attribute with name 'atttribute_name' is set for the current
  703. X *  attribute file, the citation-string will be substituted by the value
  704. X *  of that attribute. Output of 'buf' contents resumes with the first 
  705. X *  character after the blank delimiting the 'attribute_name'.
  706. X *  There are two built-in pseudo-attributes, 'Header' and 'Log' which
  707. X *  are substituted by a version header in RCS style or a log-history
  708. X *  respectively. Lines of the log-history are preceded by a 'comment
  709. X *  leader' symbol, defined as user-defined attribute CLEAD.
  710. X *  Header and Log are ended by newline characters.
  711. X */
  712. X       short stat=0, incite=0, gotattrs=0;
  713. X       char attrcitebuf[128];
  714. X       Af_attrs allattrs;
  715. X       register int i, j, k;
  716. X       char *bufp = buf, *attrname = attrcitebuf+3,
  717. X       *spt, *ept;
  718. X
  719. X       i = 0;
  720. X
  721. X       spt = ept = buf;
  722. X
  723. X       while (i < bufcnt) {
  724. X
  725. X     switch (buf[i]) {
  726. X     /* scan attribute citation marker */
  727. X     case '$':
  728. X       if (stat) ept = &(buf[i]);
  729. X       stat = 1;
  730. X       attrcitebuf[0] = '$';
  731. X       break;
  732. X     case '_':
  733. X       switch (stat) {
  734. X       case 0:
  735. X         ept++;
  736. X         break;
  737. X       case 1: 
  738. X       case 2:
  739. X         attrcitebuf[stat++] = '_';
  740. X         break;
  741. X       }
  742. X       break;
  743. X     default:
  744. X       if (stat) 
  745. X         ept = &(buf[i+1]);
  746. X       else 
  747. X         ept++;
  748. X       stat = 0;
  749. X       break;
  750. X     }
  751. X
  752. X     if (stat == 3) { /* lets see if there's an attribute citation */
  753. X       /* assertion: i is index of 2nd '_' */
  754. X       if ((i < bufcnt-1) && (buf[i+1] != ' ')) { 
  755. X         stat = 0; 
  756. X         /* ... yes, there seems to be one */
  757. X         i++; incite = 0;
  758. X         if (af_gattrs (curkey, &allattrs) < 0) {
  759. X           af_perror ("af_gattrs");
  760. X           return;
  761. X         }
  762. X         gotattrs = 1;
  763. X         while ((!index (" \n\t$", buf[i])) && (i < bufcnt))
  764. X           attrname[incite++] = buf[i++];
  765. X         if (i < bufcnt) {
  766. X           /* i points to first char after attribute name */
  767. X           if (buf[i] == '$') { /* consider '$' part of attr-name */
  768. X         attrname[incite++] = '$'; i++;
  769. X           }
  770. X           attrname[incite] = '\0';
  771. X           /* write out everything up to beginning of cite_mark */
  772. X           fwrite (spt, sizeof (*buf), ept - spt, dest);
  773. X           spt = ept = &(buf[i]);
  774. X           if (!substitute (attrname, curkey, &allattrs, dest))
  775. X         fputs (attrcitebuf, dest);
  776. X           incite = 0;
  777. X         }
  778. X         else {
  779. X           attrname[incite] = '\0';
  780. X           fwrite (spt, sizeof (*buf), ept - spt, dest);
  781. X           spt = ept = &(buf[i]);
  782. X           if (!substitute (attrname, curkey, &allattrs, dest))
  783. X         fputs (attrcitebuf, dest);
  784. X         }
  785. X       }
  786. X       else { /* blank after citemark or buffer exceeded */
  787. X         fputs ("$__", dest);
  788. X       }
  789. X       i--;
  790. X     }
  791. X     i++;
  792. X       }
  793. X       /* Ok, we've had it -- send remaining chars to dest */
  794. X       fwrite (spt, sizeof (*buf), ept - spt, dest);
  795. X       if (gotattrs) {
  796. X     i = 0;
  797. X     while (allattrs.af_udattrs[i]) free (allattrs.af_udattrs[i++]);
  798. X       }
  799. X     }
  800. X
  801. X
  802. Xstatic substitute (attrname, afkey, afattrs, dest) 
  803. X     char *attrname; Af_key *afkey; Af_attrs *afattrs; FILE *dest; {
  804. X       /* 
  805. X    * This procedure tries to substitute the occurrence of the 
  806. X    * given attribute name by the corresponding value stored with the 
  807. X    * attribute file version denoted by afkey. The substituted 
  808. X    * value is printed on dest. If 'attrname' actually is the name
  809. X    * of an attribute and the last character in the name is '$'
  810. X    * it will be deleted. In case that attrname is not a known
  811. X    * attributename, nothing happens and a value of 0, indicating
  812. X    * that no substitution took place, will be returned. Nonzero
  813. X    * return means successful substitution.
  814. X    */
  815. X       char *ap, *p, clead[32], *note, *IsAStdAttr();
  816. X       register char *lp, *ep, *l;
  817. X       Af_attrs retbuf;
  818. X       Af_set kset;
  819. X       Af_key thiskey;
  820. X       int cgen, crev, tgen, setsz, title_printed = FALSE;
  821. X       register int k;
  822. X
  823. X       if (l = index (attrname, '$')) *l = '\0';
  824. X       if (ap = IsAStdAttr (attrname, afattrs)) {
  825. X     fputs (ap, dest);
  826. X     return TRUE;
  827. X       }
  828. X       if (strcmp (attrname, HEADER)) {
  829. X     if (strcmp (attrname, LOG)) {
  830. X       ap = af_rudattr (afkey, attrname);
  831. X       if (ap > 0) {
  832. X         fputs (ap, dest);
  833. X         free (ap);
  834. X         return TRUE;
  835. X       }
  836. X       if (l) *l = '$'; /* restore '$' if 'attrname' unknown */
  837. X       return FALSE;
  838. X     }
  839. X     else { /* fill in the logs */
  840. X       /* we've got to find all preceding versions */
  841. X       
  842. X       af_initattrs (&retbuf);    
  843. X       strcpy (retbuf.af_syspath, p=af_rsyspath (afkey));
  844. X       free (p);
  845. X       strcpy (retbuf.af_name, p=af_rname (afkey));
  846. X       free (p);
  847. X       strcpy (retbuf.af_type, p=af_rtype (afkey));
  848. X       free (p);
  849. X       af_find (&retbuf, &kset);
  850. X       af_sortset (&kset, AF_ATTVERSION);
  851. X       cgen = af_rgen (afkey);
  852. X       crev = af_rrev (afkey);
  853. X       setsz = af_nrofkeys (&kset);
  854. X       
  855. X       /* determine comment leader sym to prepend it to loglines */
  856. X       p = af_rudattr (afkey, CLEAD);
  857. X       if (p) {
  858. X         strcpy (clead, p);
  859. X       }
  860. X       else clead[0] = '\0';
  861. X       free (p);
  862. X       
  863. X       /* write log for each version up to current on dest file */
  864. X       for (k = 0 ; k < setsz; k++) {
  865. X         af_setgkey (&kset, k, &thiskey);
  866. X         if (af_rstate (&thiskey) == AF_BUSY)
  867. X           continue; /* don't consider busy version */
  868. X         if ((tgen = af_rgen (&thiskey)) > cgen)
  869. X           break;
  870. X         if ((tgen == cgen) && (af_rrev(&thiskey) > crev))
  871. X           break;
  872. X         if (!title_printed) {
  873. X           fprintf (dest, "Log for ");
  874. X           putlongheader (&thiskey, dest, clead);
  875. X           title_printed = TRUE;
  876. X         }
  877. X         else {    /* each log preceded by version header */
  878. X           fprintf (dest, "%s%s", (clead && clead[0]) ? clead : "",
  879. X            (clead && clead[0]) ? " " : "");
  880. X           putshortheader (&thiskey, dest, TRUE);
  881. X
  882. X         }
  883. X         note = af_rnote (&thiskey);
  884. X         lp = note; 
  885. X         /* break log text into separate strings */
  886. X         /* assertion: lp == 0 if no log or log is printed */
  887. X         while (lp) {
  888. X           ep = lp;
  889. X           while ((*ep != '\n') && (*ep != '\0'))
  890. X         ep++;
  891. X           if (*ep == '\n') {
  892. X         *ep++ = '\0'; /* make it end of an ordinary string */
  893. X         fprintf (dest, "%s %s\n", clead, lp);
  894. X         /* ...and let it point to next string segment */
  895. X           }
  896. X           else {
  897. X         ep = NULL; /* we're ready */
  898. X         if (k < setsz-1) /* handle 'last-newline' problem */
  899. X           fprintf (dest, "%s %s\n", clead, lp);
  900. X         else
  901. X           fprintf (dest, "%s %s", clead, lp);
  902. X           }
  903. X           lp = ep;
  904. X         }
  905. X         free (note);
  906. X         /* aw rite --- lets go for the next log entry */
  907. X       }
  908. X       af_dropset (&kset);
  909. X     }
  910. X       }
  911. X       else { /* print standard version header -- do it RCS-style */
  912. X     fprintf (dest, "%cHeader: ", '$');
  913. X     putshortheader (afkey, dest, FALSE);
  914. X       }
  915. X       return TRUE;
  916. X     }
  917. X
  918. Xstatic char *vnum (key) Af_key *key; {
  919. X  int _gen, _rev;
  920. X  static char vstr[20];
  921. X
  922. X  _gen = af_rgen (key);
  923. X  _rev = af_rrev (key);
  924. X  
  925. X  if (af_rstate (key) == AF_BUSY)
  926. X    strcpy (vstr, "busy");
  927. X  else
  928. X    sprintf (vstr, "%d.%d", _gen, _rev);
  929. X  return vstr;
  930. X}
  931. X
  932. X
  933. Xstatic putlongheader (afkey, dest, clead) 
  934. X     Af_key *afkey; FILE *dest; char *clead; {
  935. X  char *spath, *name, *type, *systime(), *UidString(), *csym;
  936. X  extern char *st_table[];
  937. X  register int i;
  938. X  Af_attrs allattrs;
  939. X
  940. X  spath = af_rsyspath (afkey);
  941. X  name = af_rname  (afkey);
  942. X  type = af_rtype (afkey);
  943. X  af_gattrs (afkey, &allattrs);
  944. X  csym = (clead && clead[0]) ? clead : "";
  945. X  for (i = 0; allattrs.af_udattrs[i]; i++) free (allattrs.af_udattrs[i]);
  946. X
  947. X  fprintf (dest, "%s/%s%s%s[%s]\n%s\t%s %s %s $\n", spath, name, 
  948. X       type[0] ? "." : "", type, vnum(afkey), csym,
  949. X       systime(), UidString (&(allattrs.af_author)),
  950. X       st_table[af_rstate(afkey)]);
  951. X  free (spath); free (name); free (type);
  952. X}
  953. X
  954. Xstatic putshortheader (afkey, dest, nl) 
  955. X     Af_key *afkey; FILE *dest; int nl; {
  956. X  char *spath, *name, *type, *systime(), *UidString();
  957. X  extern char *st_table[];
  958. X  register int i;
  959. X  Af_attrs allattrs;
  960. X
  961. X  spath = af_rsyspath (afkey);
  962. X  name = af_rname  (afkey);
  963. X  type = af_rtype (afkey);
  964. X  af_gattrs (afkey, &allattrs);
  965. X  for (i = 0; allattrs.af_udattrs[i]; i++) free (allattrs.af_udattrs[i]);
  966. X
  967. X  fprintf (dest, "%s%s%s[%s] %s %s %s $%s", name, 
  968. X       type[0] ? "." : "",type, vnum(afkey),
  969. X       systime(), UidString (&(allattrs.af_author)),
  970. X       st_table[af_rstate(afkey)], nl ? "\n" : "");
  971. X  free (spath); free (name); free (type);
  972. X}
  973. X
  974. Xstatic struct {
  975. X  char *name;
  976. X  short code;
  977. X} an_tab[] = {
  978. X  { "atime", ATIME },  /* 0 */
  979. X  { "auuid", AUUID },
  980. X  { "ctime", CTIME },
  981. X  { "generation", GEN },
  982. X  { "host", HOST },
  983. X  { "lock",  LOCK },
  984. X  { "ltime", LTIME },
  985. X  { "mode", MODE },
  986. X  { "mtime", MTIME },
  987. X  { "name",  NAME },
  988. X  { "ownuid", OWNUID },
  989. X  { "revision", REV },
  990. X  { "size", SIZE },
  991. X  { "stime", STIME },
  992. X  { "syspath", SYSPATH },
  993. X  { "type", TYPE },
  994. X  { "variant", VAR },
  995. X  { "version", VERSION },
  996. X  { "state", STATE }       /* 18 */
  997. X};
  998. X
  999. Xstatic char *IsAStdAttr (attrname, afattrs) 
  1000. X     char *attrname; Af_attrs *afattrs; {
  1001. X  extern char *st_table[];
  1002. X  char messg[80], *UidString();
  1003. X  static char rets[32];
  1004. X  register int i;
  1005. X  int anc = 0;
  1006. X
  1007. X  for (i = 0; i < AN_TABSIZ; i++) {
  1008. X    if (!(strcmp (attrname, an_tab[i].name))) {
  1009. X      anc = an_tab[i].code;
  1010. X      break;
  1011. X    }
  1012. X  }
  1013. X  if (anc) {
  1014. X    switch (anc) {
  1015. X    case HOST:
  1016. X      return afattrs->af_host;
  1017. X      break;
  1018. X    case SYSPATH:
  1019. X      return afattrs->af_syspath;
  1020. X      break;
  1021. X    case NAME:
  1022. X      return afattrs->af_name;
  1023. X      break;
  1024. X    case TYPE:
  1025. X      return afattrs->af_type;
  1026. X      break;
  1027. X    case GEN:
  1028. X      if (afattrs->af_state == AF_BUSY) return "nogen";
  1029. X      else {
  1030. X    sprintf (rets, "%d", afattrs->af_gen);
  1031. X    return rets;
  1032. X      }
  1033. X      break;
  1034. X    case REV:
  1035. X      if (afattrs->af_state == AF_BUSY) return "nogen";
  1036. X      else {
  1037. X    sprintf (rets, "%d", afattrs->af_rev);
  1038. X    return rets;
  1039. X      }
  1040. X      break;
  1041. X    case VERSION:
  1042. X      if (afattrs->af_state == AF_BUSY) return "busy";
  1043. X      else {
  1044. X    sprintf (rets, "%d.%d", afattrs->af_gen, afattrs->af_rev);
  1045. X    return rets;
  1046. X      }
  1047. X      break;
  1048. X    case VAR:
  1049. X      return (afattrs->af_variant);
  1050. X      break;
  1051. X    case STATE:
  1052. X      return st_table[afattrs->af_state];
  1053. X      break;
  1054. X    case OWNUID:
  1055. X      return UidString (&(afattrs->af_owner));
  1056. X      break;
  1057. X    case AUUID:
  1058. X      return UidString (&(afattrs->af_author));
  1059. X      break;
  1060. X    case SIZE:
  1061. X      sprintf (rets, "%d", afattrs->af_size);
  1062. X      return rets;
  1063. X      break;
  1064. X    case MODE:
  1065. X      sprintf (rets, "%o", afattrs->af_mode);
  1066. X      return rets;
  1067. X      break;
  1068. X    case LOCK:
  1069. X      if (strcmp (afattrs->af_locker.af_username, "")) {
  1070. X    sprintf (rets, "%s@%s", afattrs->af_locker.af_username, 
  1071. X         afattrs->af_locker.af_userhost);
  1072. X    return rets;
  1073. X      }
  1074. X      return "nobody";
  1075. X      break;
  1076. X    case MTIME:
  1077. X      strcpy (rets, asctime(localtime(&afattrs->af_mtime)));
  1078. X      rets[strlen(rets) - 1] = '\0';
  1079. X      return rets;
  1080. X      break;
  1081. X    case ATIME:
  1082. X      strcpy (rets, asctime(localtime(&afattrs->af_atime)));
  1083. X      rets[strlen(rets) - 1] = '\0';
  1084. X      return rets;
  1085. X      break;
  1086. X    case CTIME:
  1087. X      strcpy (rets, asctime(localtime(&afattrs->af_ctime)));
  1088. X      rets[strlen(rets) - 1] = '\0';
  1089. X      return rets;
  1090. X      break;
  1091. X    case STIME:
  1092. X      if (afattrs->af_state == AF_BUSY) return "no_date";
  1093. X      else {
  1094. X    strcpy (rets, asctime(localtime(&afattrs->af_stime)));
  1095. X    rets[strlen(rets) - 1] = '\0';
  1096. X    return rets;
  1097. X      }
  1098. X      break;
  1099. X      case LTIME:
  1100. X      strcpy (rets, asctime(localtime(&afattrs->af_ltime)));
  1101. X      rets[strlen(rets) - 1] = '\0';
  1102. X      return rets;
  1103. X      break;
  1104. X    default: /* shouldn't happen ! */
  1105. X      sprintf (messg, "illegal standard attribute code %d.", anc);
  1106. X      logerr (anc);
  1107. X    }
  1108. X  }
  1109. X  else return NULL; /* no standard attribute */
  1110. X}
  1111. X
  1112. Xchar *UidString (user) Af_user *user; {
  1113. X  static char rst[256];
  1114. X
  1115. X  rst[0] = '\0';
  1116. X  if (user) {
  1117. X    sprintf (rst, "%s@%s", user->af_username, user->af_userhost);
  1118. X  }
  1119. X  return rst;
  1120. X}
  1121. X
  1122. Xstatic char *systime () {
  1123. X  char *asctime();  
  1124. X  register char *ts;
  1125. X  struct timeval tm;
  1126. X  struct timezone tz;
  1127. X
  1128. X  gettimeofday (&tm, &tz);
  1129. X  ts = asctime (localtime (&tm));
  1130. X  ts[strlen(ts)-1] = '\0';
  1131. X  return ts;
  1132. X}
  1133. END_OF_FILE
  1134. if test 14280 -ne `wc -c <'src/misc/citeattr.c'`; then
  1135.     echo shar: \"'src/misc/citeattr.c'\" unpacked with wrong size!
  1136. fi
  1137. # end of 'src/misc/citeattr.c'
  1138. fi
  1139. if test -f 'src/vc/vlmisc.c' -a "${1}" != "-c" ; then 
  1140.   echo shar: Will not clobber existing file \"'src/vc/vlmisc.c'\"
  1141. else
  1142. echo shar: Extracting \"'src/vc/vlmisc.c'\" \(14112 characters\)
  1143. sed "s/^X//" >'src/vc/vlmisc.c' <<'END_OF_FILE'
  1144. X/*
  1145. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  1146. X *  and U. Pralle
  1147. X * 
  1148. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  1149. X * WARRANTY for any part of this software to work correctly or as described
  1150. X * in the manuals. We do not accept any liability for any kind of damage
  1151. X * caused by use of this software, such as loss of data, time, money, or 
  1152. X * effort.
  1153. X * 
  1154. X * Permission is granted to use, copy, modify, or distribute any part of
  1155. X * this software as long as this is done without asking for charge, and
  1156. X * provided that this copyright notice is retained as part of the source
  1157. X * files. You may charge a distribution fee for the physical act of
  1158. X * transferring a copy, and you may at your option offer warranty
  1159. X * protection in exchange for a fee.
  1160. X * 
  1161. X * Direct questions to: Tech. Univ. Berlin
  1162. X *              Wilfried Koch
  1163. X *              Sekr. FR 5-6 
  1164. X *              Franklinstr. 28/29
  1165. X *              D-1000 Berlin 10, West Germany
  1166. X * 
  1167. X *              Tel: +49-30-314-22972
  1168. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  1169. X */
  1170. X#ifndef lint
  1171. Xstatic char *AFSid = "$Header: vlmisc.c[3.11] Thu Feb 23 18:14:52 1989 axel@coma published $";
  1172. X#ifdef CFFLGS
  1173. Xstatic char *ConfFlg = CFFLGS;
  1174. X    /* should be defined from within Makefile */
  1175. X#endif
  1176. X#endif
  1177. X/*
  1178. X * Log for /u/shape/dist-tape/src/vc/vlmisc.c[3.5]
  1179. X *     Thu Feb 23 18:14:52 1989 axel@coma published $
  1180. X *  --- empty log message ---
  1181. X *  vlmisc.c[3.7] Thu Feb 23 18:14:52 1989 uli@coma published $
  1182. X *  --- empty log message ---
  1183. X *  vlmisc.c[3.9] Thu Feb 23 18:14:52 1989 axel@coma published $
  1184. X *  --- empty log message ---
  1185. X *  vlmisc.c[3.10] Thu Feb 23 18:14:52 1989 axel@coma save $
  1186. X *  --- empty log message ---
  1187. X *  vlmisc.c[3.11] Thu Feb 23 18:14:52 1989 axel@coma published $
  1188. X *  --- empty log message ---
  1189. X */
  1190. X
  1191. X#include <stdio.h>
  1192. X#include <pwd.h>
  1193. X#include <grp.h>
  1194. X#include <strings.h>
  1195. X#include <sys/param.h>
  1196. X#include <sys/types.h>
  1197. X#include <sys/stat.h>
  1198. X
  1199. X#include <afs.h>
  1200. X#include <afsys.h>
  1201. X
  1202. X#include "vl.h"
  1203. X
  1204. X/*
  1205. X * Global, but not exported variables
  1206. X */
  1207. X#define VL_MAX_OWNERNAME 7            /* in real life 8 chars */
  1208. X#define VL_MAX_GROUPNAME 7            /* dito. */
  1209. X
  1210. Xstatic char *Progname;                        /* name of the called process*/
  1211. Xstatic char filemode[10];            /* visible file mode (ls(1)) */
  1212. Xstatic Af_user author, owner;
  1213. Xstatic char version_string[80];            /* e.g. -V1.0 */
  1214. Xstatic char error_string[80];            /* for {af_}perror */
  1215. X
  1216. Xchar **udattrs;                    /* Uda sorted */
  1217. Xint  version_number;                /* Version identification
  1218. X                         * via option -V */
  1219. Xchar *version_states;                /* Version states via
  1220. X                         * option -s */
  1221. X
  1222. Xchar *GetVersionState (state)
  1223. X     int state;
  1224. X{
  1225. X  switch (state) {
  1226. X  case AF_BUSY:
  1227. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[busy]" : "b");
  1228. X  case AF_SAVED:
  1229. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[save]" : "s");
  1230. X  case AF_PROPOSED:
  1231. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[prop]" : "p");
  1232. X  case AF_PUBLISHED:
  1233. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[publ]" : "P");
  1234. X  case AF_ACCESSED:
  1235. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[acce]" : "a");
  1236. X  case AF_FROZEN:
  1237. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[froz]" : "f");
  1238. X  default:
  1239. X    return (IsOptionSet(VL_O_VERSIONSTATE) ? "[????]" : "?");
  1240. X  }
  1241. X}
  1242. X
  1243. Xchar *GetVersionId (generation, revision)
  1244. X     int generation, revision;
  1245. X{
  1246. X  if ( (generation != AF_BUSYVERS) || ( revision != AF_BUSYVERS)) {
  1247. X    (void)sprintf (version_string, "[%d.%d]", generation, revision);
  1248. X    return version_string;
  1249. X  }
  1250. X  else
  1251. X    return "";
  1252. X}
  1253. X
  1254. XVinfoCleanup ()
  1255. X{
  1256. X  
  1257. X}
  1258. X
  1259. Xchar *GetMode (mode)
  1260. X     u_short mode;
  1261. X{
  1262. X/* This function should return a capital 'L' in the file-class field */
  1263. X/* to indicate a *locked* version. Maybe optional. Instead of Ownername */
  1264. X/* the name of the locker is to be printed. */
  1265. X  (void)sprintf (filemode, "%c%c%c%c%c%c%c%c%c%c",
  1266. X       (mode & S_IFDIR) ? 'd' : '-',
  1267. X       (mode & S_IREAD) ? 'r' : '-',
  1268. X       (mode & S_IWRITE) ? 'w' : '-',
  1269. X       (mode & S_IEXEC) ? 'x' : '-',
  1270. X       (mode & (S_IREAD >> 3)) ? 'r' : '-',
  1271. X       (mode & (S_IWRITE >> 3)) ? 'w' : '-',
  1272. X       (mode & (S_IEXEC >> 3)) ? 'x' : '-',
  1273. X       (mode & (S_IREAD >> 6)) ? 'r' : '-',
  1274. X       (mode & (S_IWRITE >> 6)) ? 'w' : '-',
  1275. X       (mode & (S_IEXEC >> 6)) ? 'x' : '-'
  1276. X        );
  1277. X    
  1278. X  if (mode & S_ISUID)
  1279. X    filemode[1] = 's';
  1280. X  if (mode & S_ISGID)
  1281. X    filemode[6] = 's';
  1282. X  if (mode & S_ISVTX)
  1283. X    filemode[9] = 't';
  1284. X
  1285. X  return filemode;
  1286. X}
  1287. X
  1288. Xextern char *GetUserInfo (userdesc)
  1289. X     Af_user *userdesc;
  1290. X{
  1291. X  char *uinfo, *tmp;
  1292. X  
  1293. X  if ((tmp = malloc(MAXNAMLEN + MAXHOSTNAMELEN + 2)) == NULL) {
  1294. X    fprintf (stderr, "in GetUserInfo: not enough memory\n");
  1295. X    exit (1);
  1296. X  }
  1297. X
  1298. X  if ((uinfo = malloc(20)) == NULL) {
  1299. X   fprintf (stderr, "in GetUserInfo: not enough memory\n");
  1300. X    exit (1);
  1301. X }
  1302. X  
  1303. X  (void)sprintf 
  1304. X    (tmp, "%s%s%s", userdesc->af_username, userdesc->af_userhost[0] ?
  1305. X       "@" : "", userdesc->af_userhost);
  1306. X  (void)sprintf (uinfo, "%-16s", tmp);
  1307. X  free (tmp);
  1308. X  return uinfo;
  1309. X}
  1310. X
  1311. Xchar *GetDate (date)
  1312. X     time_t date;
  1313. X{
  1314. X  char *tmp_time;
  1315. X  extern char *ctime();
  1316. X
  1317. X  tmp_time = ctime(&date);
  1318. X
  1319. X  /* Format is "Sun Sep 16 01:03:52 1973\n\0" */
  1320. X  tmp_time = tmp_time + 4;
  1321. X  tmp_time[20] = '\0';
  1322. X  return tmp_time;
  1323. X}
  1324. X
  1325. X
  1326. XIsDirectory (name)
  1327. X     char *name;
  1328. X{
  1329. X  struct stat stbuf;
  1330. X
  1331. X  if (stat(name, &stbuf)) {
  1332. X    return 0;
  1333. X  }
  1334. X
  1335. X  return (stbuf.st_mode & S_IFDIR);
  1336. X}
  1337. X
  1338. Xint FileExists (name)
  1339. X     char *name;
  1340. X{
  1341. X  struct stat buf;
  1342. X
  1343. X  return ((stat (name, &buf) == 0) ? 1 : 0);
  1344. X}
  1345. X
  1346. X
  1347. Xint PutProgramName (name)
  1348. X     char *name;
  1349. X{
  1350. X  Progname = ((Progname = rindex (name, '/')) ? ++Progname : name);
  1351. X}
  1352. X
  1353. Xchar *GetProgramName ()
  1354. X{
  1355. X  return Progname;
  1356. X}
  1357. X
  1358. Xvoid PutVersionStates (states)
  1359. X     char *states;
  1360. X{
  1361. X  version_states = states;
  1362. X}
  1363. X
  1364. X#define nxt(s) (s = (*(s+strlen(s)+1) != '\0') ? s+strlen(s)+1 : NULL)
  1365. X
  1366. XCopyUdattrs (udaval, udattrs)
  1367. X     char *udaval;
  1368. X     char **udattrs;
  1369. X{
  1370. X  /* returns # of udattrs */
  1371. X  register int i;
  1372. X
  1373. X  register char *cp;
  1374. X  char *temp;
  1375. X
  1376. X  if ( (temp = malloc ((unsigned)(strlen (udaval) +2))) == NULL) {
  1377. X    perror ("malloc");
  1378. X    exit (1);
  1379. X  }
  1380. X  (void)strcpy (temp, udaval);
  1381. X  temp[strlen(udaval)+1] = '\0';
  1382. X  
  1383. X  cp = temp;            /*  */
  1384. X  while (temp && *temp) {
  1385. X    if (*temp == ',') {
  1386. X      *temp = '\0';
  1387. X    }
  1388. X    ++temp;
  1389. X  }
  1390. X
  1391. X  i = 0;
  1392. X  while (cp && *cp) {
  1393. X    udattrs[i] = cp;
  1394. X    i++; nxt(cp);        /* nxt() is a macro !*/
  1395. X  }
  1396. X  udattrs[i] = NULL;
  1397. X
  1398. X  /*
  1399. X   * Now scan for "foo=bar<blank>bar1" and substitute <blank> by <Ctrl-A>.
  1400. X   * Don't ask why.
  1401. X   */
  1402. X
  1403. X  for (i=0; udattrs[i]; i++) {
  1404. X    cp = udattrs[i];
  1405. X    for (cp = udattrs[i]; cp && *cp; cp++)
  1406. X      if (*cp == ' ')
  1407. X    *cp = AF_UDAVALDEL;        /* This is a Ctrl-A */
  1408. X  }
  1409. X  return i;            /* return # of udattrs */
  1410. X}
  1411. X
  1412. Xint AddUdattrs (udas)
  1413. X     char *udas;
  1414. X{
  1415. X  int i, length, na;
  1416. X  char **cpp;
  1417. X
  1418. X  if ( udas && (*udas == ':')) udas++;
  1419. X  length = 0;
  1420. X  /* determine length of current udattrs */
  1421. X  if (udattrs && *udattrs) {
  1422. X    for (i = 0 ; udattrs[i]; i++)
  1423. X      length++;
  1424. X  }
  1425. X
  1426. X  length += strlen (udas) + 1;    /* plus the new udas */
  1427. X  length++;
  1428. X  if ((cpp = (char **) malloc ((unsigned)(sizeof (char **) * length))) 
  1429. X      == (char **) NULL) {
  1430. X    (void)sprintf (error_string, "%s: in AddUdattra(): malloc", Progname);
  1431. X    perror (error_string);
  1432. X    exit (1);
  1433. X  }
  1434. X
  1435. X  na = CopyUdattrs (udas, cpp);
  1436. X  
  1437. X  if (udattrs && *udattrs) {
  1438. X    for (i = 0 ; udattrs[i]; i++) /* copy old into new array */
  1439. X      cpp[na++] = udattrs[i];
  1440. X  }
  1441. X  
  1442. X  cpp[na] = (char *) NULL;
  1443. X  free ((char *)udattrs);
  1444. X  
  1445. X  udattrs = cpp;
  1446. X}
  1447. X
  1448. XAddHiddenUda (name, val)
  1449. X     char *name, *val;
  1450. X{
  1451. X  int length;
  1452. X  char *huda;
  1453. X  
  1454. X  length = strlen (name);
  1455. X  length += strlen (val);
  1456. X
  1457. X  if ((huda = malloc ((unsigned)(length+2*sizeof(char)))) == (char *) NULL) {
  1458. X    (void)sprintf (error_string, "in AddHiddenUda(): malloc");
  1459. X    perror (error_string);
  1460. X    exit (1);
  1461. X  }
  1462. X  (void)sprintf (huda, "%s=%s", name, val);
  1463. X  AddUdattrs (huda);
  1464. X}
  1465. X
  1466. Xchar **GetUdattrs ()
  1467. X{
  1468. X  return udattrs;
  1469. X}
  1470. X
  1471. Xu_long vstates = 0;
  1472. X#define VL_CHCK_BUSY 01
  1473. X#define VL_CHCK_SAVE 02
  1474. X#define VL_CHCK_PROPOSED 04
  1475. X#define VL_CHCK_PUBLISHED 010
  1476. X#define VL_CHCK_ACCESSED 020
  1477. X#define VL_CHCK_FROZEN 040
  1478. X#define VL_CHCK_ALL 077
  1479. X#define VL_MAX_STATES 6
  1480. X
  1481. Xvoid ScanVersionStates ()
  1482. X
  1483. X     /*
  1484. X      * Scans strings of the form:
  1485. X      *     bspPaf
  1486. X      *        c+ (c is a char)
  1487. X      *        c-
  1488. X      *        ~c (not)
  1489. X      *        !c (not)
  1490. X      *        c-,c+
  1491. X      *        c+c-
  1492. X      */
  1493. X{
  1494. X  register last_state;
  1495. X  
  1496. X  if (! (*version_states)) {
  1497. X    vstates  = VL_CHCK_ALL;
  1498. X    return;
  1499. X  }
  1500. X
  1501. X  while (*version_states) {
  1502. X    switch (*version_states) {
  1503. X    case 'b':
  1504. X      vstates |= VL_CHCK_BUSY;
  1505. X      last_state = AF_BUSY;
  1506. X      break;
  1507. X    case 's':
  1508. X      vstates |= VL_CHCK_SAVE;
  1509. X      last_state = AF_SAVED;
  1510. X      break;
  1511. X    case 'p':
  1512. X      vstates |= VL_CHCK_PROPOSED;
  1513. X      last_state = AF_PROPOSED;
  1514. X      break;
  1515. X    case 'P':
  1516. X      vstates |= VL_CHCK_PUBLISHED;
  1517. X      last_state = AF_PUBLISHED;
  1518. X      break;
  1519. X    case 'a':
  1520. X      vstates |= VL_CHCK_ACCESSED;
  1521. X      last_state = AF_ACCESSED;
  1522. X      break;
  1523. X    case 'f':
  1524. X      vstates |= VL_CHCK_FROZEN;
  1525. X      last_state = AF_FROZEN;
  1526. X      break;
  1527. X    case '+':            /* -sb+ */
  1528. X      switch (last_state) {
  1529. X      case AF_BUSY:
  1530. X    vstates |= VL_CHCK_BUSY;
  1531. X      case AF_SAVED:
  1532. X    vstates |= VL_CHCK_SAVE;
  1533. X      case AF_PROPOSED:
  1534. X    vstates |= VL_CHCK_PROPOSED;
  1535. X      case AF_PUBLISHED:
  1536. X    vstates |= VL_CHCK_PUBLISHED;
  1537. X      case AF_ACCESSED:
  1538. X    vstates |= VL_CHCK_ACCESSED;
  1539. X      case AF_FROZEN:
  1540. X    vstates |= VL_CHCK_FROZEN;
  1541. X    break;
  1542. X      default:
  1543. X    fprintf (stderr, "%s: fatal error in ScanVersionStates\n", Progname);
  1544. X    exit (1);
  1545. X      }
  1546. X      break;
  1547. X    case '-':            /* -sb- */
  1548. X      if ( !((*(version_states+1) == ',') ||
  1549. X         (!*(version_states+1)))) {    /* -sb-f */
  1550. X    fprintf (stderr, "%s: subrange of states is not allowed\n",
  1551. X         Progname);
  1552. X    exit (1);
  1553. X      }
  1554. X      else {
  1555. X    switch (last_state) {
  1556. X    case AF_FROZEN:
  1557. X      vstates |= VL_CHCK_FROZEN;
  1558. X    case AF_ACCESSED:
  1559. X      vstates |= VL_CHCK_ACCESSED;
  1560. X    case AF_PUBLISHED:
  1561. X      vstates |= VL_CHCK_PUBLISHED;
  1562. X    case AF_PROPOSED:
  1563. X      vstates |= VL_CHCK_PROPOSED;
  1564. X    case AF_SAVED:
  1565. X      vstates |= VL_CHCK_SAVE;
  1566. X    case AF_BUSY:
  1567. X      vstates |= VL_CHCK_BUSY;
  1568. X      break;
  1569. X    default:
  1570. X      fprintf (stderr, "%s: fatal error in ScanVersionStates\n", Progname);
  1571. X      exit (1);
  1572. X    }
  1573. X      }
  1574. X      break;
  1575. X    case ',':            /* skip this char */
  1576. X      break;
  1577. X    case '~':
  1578. X    case '!':
  1579. X      if (!*(version_states + 1)) {
  1580. X    fprintf (stderr, "%s: missing version state after '%c'\n",
  1581. X         Progname, *version_states);
  1582. X    exit (1);
  1583. X      }
  1584. X      vstates = VL_CHCK_ALL;
  1585. X      switch (*(++version_states)) {
  1586. X      case 'b':
  1587. X    vstates &= ~VL_CHCK_BUSY;
  1588. X    last_state = AF_BUSY;
  1589. X    break;
  1590. X      case 's':
  1591. X    vstates &= ~VL_CHCK_SAVE;
  1592. X    last_state = AF_SAVED;
  1593. X    break;
  1594. X      case 'p':
  1595. X    vstates &= ~VL_CHCK_PROPOSED;
  1596. X    last_state = AF_PROPOSED;
  1597. X    break;
  1598. X      case 'P':
  1599. X    vstates &= ~VL_CHCK_PUBLISHED;
  1600. X    last_state = AF_PUBLISHED;
  1601. X    break;
  1602. X      case 'a':
  1603. X    vstates &= ~VL_CHCK_ACCESSED;
  1604. X    last_state = AF_ACCESSED;
  1605. X    break;
  1606. X      case 'f':
  1607. X    vstates &= ~VL_CHCK_FROZEN;
  1608. X    last_state = AF_FROZEN;
  1609. X    break;
  1610. X      default:
  1611. X    fprintf (stderr, "%s: unknown state '%c'. Ignored.\n",
  1612. X         Progname, *version_states);
  1613. X    break;
  1614. X      }
  1615. X      break;
  1616. X    default:
  1617. X      fprintf (stderr, "%s: unknown state '%c'. Asume 'b+'\n",
  1618. X           Progname, *version_states);
  1619. X      vstates = VL_CHCK_ALL;
  1620. X      return;
  1621. X    }
  1622. X    version_states++;
  1623. X  }
  1624. X}
  1625. X
  1626. Xint MatchesVersionStates (attrbuf)
  1627. X     Af_attrs *attrbuf;
  1628. X{
  1629. X  register int attrstate;
  1630. X  register int state;
  1631. X
  1632. X  state = vstates;
  1633. X  attrstate = attrbuf->af_state;
  1634. X  
  1635. X  if (state == VL_CHCK_ALL) return 1;
  1636. X  
  1637. X  switch (attrstate) {
  1638. X  case AF_BUSY:
  1639. X    return (state & VL_CHCK_BUSY);
  1640. X  case AF_SAVED:
  1641. X    return (state & VL_CHCK_SAVE);
  1642. X  case AF_PROPOSED:
  1643. X    return (state & VL_CHCK_PROPOSED);
  1644. X  case AF_PUBLISHED:
  1645. X    return (state & VL_CHCK_PUBLISHED);
  1646. X  case AF_ACCESSED:
  1647. X    return (state & VL_CHCK_ACCESSED);
  1648. X  case AF_FROZEN:
  1649. X    return (state & VL_CHCK_FROZEN);
  1650. X  default:
  1651. X    return 0;
  1652. X  }  
  1653. X}
  1654. X
  1655. Xvoid PutAuthorIdentifications (author_id)
  1656. X     char *author_id;
  1657. X{
  1658. X  char *cp;
  1659. X
  1660. X  if (cp=index (author_id, '@')) {
  1661. X    *cp++ = '\0';
  1662. X    (void)strcpy (author.af_userhost, cp);
  1663. X  }
  1664. X  (void)strcpy (author.af_username, author_id);
  1665. X}
  1666. X
  1667. Xchar *GetAuthoridFromAuthor ()
  1668. X{
  1669. X    return author.af_username;
  1670. X}
  1671. X
  1672. Xchar *GetAuthorhostFromAuthor ()
  1673. X{
  1674. X    return author.af_userhost;
  1675. X}
  1676. X
  1677. X
  1678. Xvoid PutOwnerIdentifications (owner_id)
  1679. X     char *owner_id;
  1680. X{
  1681. X  char *cp;
  1682. X
  1683. X  if (cp=index (owner_id, '@')) {
  1684. X    *cp++ = '\0';
  1685. X    (void)strcpy (owner.af_userhost, cp);
  1686. X  }
  1687. X  (void)strcpy (owner.af_username, owner_id);
  1688. X}
  1689. X
  1690. Xchar *GetOwneridFromOwner ()
  1691. X{
  1692. X    return owner.af_username;
  1693. X}
  1694. X
  1695. Xchar *GetOwnerhostFromOwner ()
  1696. X{
  1697. X    return owner.af_userhost;
  1698. X}
  1699. X
  1700. X/*ARGSUSED*/
  1701. Xint
  1702. Xa_dir_and_a_file (ac, av)
  1703. X     int ac;
  1704. X     char **av;
  1705. X{
  1706. X  /*
  1707. X   * Return 1 iff av contains any directory name.
  1708. X   */
  1709. X  while (av && *av) {
  1710. X    if (IsDirectory (*av))
  1711. X      return 1;
  1712. X    av++;
  1713. X  }
  1714. X  return 0;
  1715. X}
  1716. X
  1717. Xchar **
  1718. Xrearrange_args (ac, av)
  1719. X     int ac;
  1720. X     char **av;
  1721. X{
  1722. X  /*
  1723. X   * Sorts av in the following order: first pure files, then directories.
  1724. X   * Returns sorted av.
  1725. X   */
  1726. X  char **dirs;
  1727. X  char **tdirs;
  1728. X  char **files;
  1729. X  char **tfiles;
  1730. X  char **tav;
  1731. X
  1732. X  tav = av;
  1733. X  
  1734. X  if ((dirs = (char **)
  1735. X       malloc ((unsigned)((ac + 1) * sizeof(char *)))) == (char **)NULL) {
  1736. X    perror ("malloc");
  1737. X    exit (1);
  1738. X  }
  1739. X  tdirs = dirs;
  1740. X  
  1741. X  if ((files = (char **)
  1742. X       malloc ((unsigned)((ac + 1) * sizeof(char *)))) == (char **)NULL) {
  1743. X    perror ("malloc");
  1744. X    exit (1);
  1745. X  }
  1746. X  tfiles = files;
  1747. X  
  1748. X  while (av && *av) {
  1749. X    if (IsDirectory (*av)) {
  1750. X      *dirs = *av;
  1751. X      dirs++;
  1752. X    }
  1753. X    else {
  1754. X      *files = *av;
  1755. X      files++;
  1756. X    }
  1757. X
  1758. X    av++;
  1759. X  }
  1760. X
  1761. X  files = (char **) NULL;
  1762. X  dirs = (char **) NULL;
  1763. X  
  1764. X  av = tav;
  1765. X  while (tfiles && *tfiles) {
  1766. X    *av = *tfiles;
  1767. X    av++; tfiles++;
  1768. X  }
  1769. X
  1770. X  while (tdirs && *tdirs) {
  1771. X    *av = *tdirs;
  1772. X    av++; tdirs++;
  1773. X  }
  1774. X
  1775. X  return tav;
  1776. X}
  1777. X
  1778. Xint IsHiddenUda (uda)
  1779. X     char *uda;
  1780. X{
  1781. X  /*
  1782. X   * A hidden Uda begins and ends with 2 '_'.
  1783. X   */
  1784. X  
  1785. X  return (!strncmp (uda, "__", 2));
  1786. X}
  1787. X
  1788. Xint IsHiddenFile(attrbuf)
  1789. X     Af_attrs *attrbuf;
  1790. X{
  1791. X  /* Is file a hidden file ? */
  1792. X  if ( (attrbuf->af_name[0] == '\0') || (attrbuf->af_name[0] == '.') )
  1793. X    return 1;
  1794. X  else
  1795. X    return 0;
  1796. X}
  1797. X
  1798. Xlogerr (msg) char *msg; {
  1799. X  fprintf (stderr, "%s: %s.\n", Progname, msg);
  1800. X}
  1801. END_OF_FILE
  1802. if test 14112 -ne `wc -c <'src/vc/vlmisc.c'`; then
  1803.     echo shar: \"'src/vc/vlmisc.c'\" unpacked with wrong size!
  1804. fi
  1805. # end of 'src/vc/vlmisc.c'
  1806. fi
  1807. echo shar: End of archive 16 \(of 33\).
  1808. cp /dev/null ark16isdone
  1809. MISSING=""
  1810. 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
  1811.     if test ! -f ark${I}isdone ; then
  1812.     MISSING="${MISSING} ${I}"
  1813.     fi
  1814. done
  1815. if test "${MISSING}" = "" ; then
  1816.     echo You have unpacked all 33 archives.
  1817.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1818. else
  1819.     echo You still need to unpack the following archives:
  1820.     echo "        " ${MISSING}
  1821. fi
  1822. ##  End of shell archive.
  1823. exit 0
  1824.