home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / shape / part15 < prev    next >
Encoding:
Internet Message Format  |  1989-05-31  |  56.4 KB

  1. Subject:  v19i028:  A software configuration management system, Part15/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 28
  8. Archive-name: shape/part15
  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 15 (of 33)."
  19. # Contents:  src/afs/afvers.c src/misc/ParseArgs.c src/shape/misc.c
  20. #   src/vc/retrv.c
  21. # Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:05 1989
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'src/afs/afvers.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'src/afs/afvers.c'\"
  25. else
  26. echo shar: Extracting \"'src/afs/afvers.c'\" \(13536 characters\)
  27. sed "s/^X//" >'src/afs/afvers.c' <<'END_OF_FILE'
  28. X/*
  29. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  30. X *  and U. Pralle
  31. X * 
  32. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  33. X * WARRANTY for any part of this software to work correctly or as described
  34. X * in the manuals. We do not accept any liability for any kind of damage
  35. X * caused by use of this software, such as loss of data, time, money, or 
  36. X * effort.
  37. X * 
  38. X * Permission is granted to use, copy, modify, or distribute any part of
  39. X * this software as long as this is done without asking for charge, and
  40. X * provided that this copyright notice is retained as part of the source
  41. X * files. You may charge a distribution fee for the physical act of
  42. X * transferring a copy, and you may at your option offer warranty
  43. X * protection in exchange for a fee.
  44. X * 
  45. X * Direct questions to: Tech. Univ. Berlin
  46. X *              Wilfried Koch
  47. X *              Sekr. FR 5-6 
  48. X *              Franklinstr. 28/29
  49. X *              D-1000 Berlin 10, West Germany
  50. X * 
  51. X *              Tel: +49-30-314-22972
  52. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  53. X */
  54. X/*LINTLIBRARY*/
  55. X/*
  56. X *    Shape/AFS
  57. X *
  58. X *    afversions.c - operations on revisions
  59. X *
  60. X *    Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP
  61. X *                       andy@db0tui62.BITNET)
  62. X *
  63. X *    $Header: afvers.c[1.3] Wed Feb 22 16:28:25 1989 andy@coma published $
  64. X *
  65. X *    EXPORT:
  66. X *    af_savebinary -- save derived file
  67. X *    af_saverev -- save busy version
  68. X *    af_newgen -- increase gen number and reset rev number
  69. X *    af_setbusy -- set revision busy
  70. X *    af_svnum -- set version number
  71. X */
  72. X
  73. X#include <stdio.h>
  74. X#include <string.h>
  75. X#ifdef SUNOS_4_0
  76. X#include <strings.h>
  77. X#endif
  78. X#include <sys/types.h>
  79. X#include <sys/stat.h>
  80. X
  81. X#include "typeconv.h"
  82. X#include "afsys.h"
  83. X#include "afs.h"
  84. X
  85. X/*====================================================================
  86. X *    af_savebinary
  87. X *
  88. X *====================================================================*/
  89. X
  90. XEXPORT af_savebinary (busykey, savekey)
  91. X     Af_key *busykey;
  92. X     Af_key *savekey; /* out */
  93. X{
  94. X  int    oldpredgen, oldpredrev;
  95. X  short  oldnlinks;
  96. X  time_t oldatime;
  97. X
  98. X  if (af_keytest (busykey))
  99. X    SFAIL ("savebinary", "", AF_EINVKEY, ERROR);
  100. X  
  101. X  if (VATTR(busykey).af_state != AF_BUSY)
  102. X    SFAIL ("savebinary", "", AF_ENOTBUSY, ERROR);
  103. X
  104. X  if ((VATTR(busykey).af_mode & S_IFMT) != S_IFREG)
  105. X    SFAIL ("savebinary", "", AF_ENOTREGULAR, ERROR);
  106. X
  107. X  if (VATTR(busykey).af_nlinks > 1)
  108. X    af_wng ("savebinary", "busykey has more than one reference");
  109. X
  110. X  if (af_checkperm (busykey, AF_WORLD) == ERROR)
  111. X    return (ERROR);
  112. X
  113. X  /* this then part is a little bit "hacked", it should better look like:
  114. X   * 
  115. X   * get key for new bp entry
  116. X   * modify attributes
  117. X   * add new file to binary pool
  118. X   */
  119. X  
  120. X  /* modify some attributes for saving */
  121. X  VATTR(busykey).af_state = AF_NOSTATE;
  122. X  VATTR(busykey).af_class |= AF_DERIVED;
  123. X  oldatime = VATTR(busykey).af_atime;
  124. X  VATTR(busykey).af_atime = (time_t) af_acttime ();
  125. X  oldpredgen = VATTR(busykey).af_predgen;
  126. X  VATTR(busykey).af_predgen = AF_NOVNUM;
  127. X  oldpredrev = VATTR(busykey).af_predrev;
  128. X  VATTR(busykey).af_predrev = AF_NOVNUM;
  129. X  oldnlinks = VATTR(busykey).af_nlinks;
  130. X  VATTR(busykey).af_nlinks = 1;
  131. X  
  132. X  if (af_rplbpentry ((Af_key *)0, busykey, savekey) == ERROR)
  133. X    return (ERROR);
  134. X
  135. X  /* restore attributes */
  136. X  VATTR(busykey).af_state = AF_BUSY;
  137. X  VATTR(busykey).af_class &= ~AF_DERIVED;
  138. X  VATTR(busykey).af_atime = oldatime;
  139. X  VATTR(busykey).af_predgen = oldpredgen;
  140. X  VATTR(busykey).af_predrev = oldpredrev;
  141. X  VATTR(busykey).af_nlinks = oldnlinks;
  142. X
  143. X  /* update binary pool descriptor */
  144. X  savekey->af_ldes->af_refcount++;
  145. X  
  146. X  return (AF_OK);
  147. X}
  148. X
  149. X
  150. X/*====================================================================
  151. X *    af_saverev
  152. X *
  153. X *====================================================================*/
  154. X
  155. XEXPORT af_saverev (busykey, savekey)
  156. X
  157. X     Af_key *busykey;
  158. X     Af_key *savekey; /* out */
  159. X{
  160. X  Af_key *lastkey, predkey, *af_glastkey();
  161. X  Af_user *author;
  162. X  struct stat ibuf;
  163. X  int af_fhash();
  164. X  
  165. X  if (af_keytest (busykey))
  166. X    SFAIL ("saverev", "", AF_EINVKEY, ERROR);
  167. X  
  168. X  if (VATTR(busykey).af_state != AF_BUSY)
  169. X    SFAIL ("saverev", "", AF_ENOTBUSY, ERROR);
  170. X
  171. X  if ((VATTR(busykey).af_mode & S_IFMT) != S_IFREG)
  172. X    SFAIL ("saverev", "", AF_ENOTREGULAR, ERROR);
  173. X
  174. X  if (af_checkperm (busykey, AF_LOCKHOLDER) == ERROR)
  175. X    SFAIL ("saverev", "", AF_ENOTLOCKED, ERROR);
  176. X
  177. X  /* get attribute buffer (pointed to by "savekey") for new version */
  178. X  if (af_newvers (busykey->af_ldes, savekey, AF_SOURCE) == ERROR)
  179. X    return (ERROR);
  180. X
  181. X  /* set key and attributes of new version */
  182. X  VATTR(savekey).af_name = VATTR(busykey).af_name;
  183. X  VATTR(savekey).af_type = VATTR(busykey).af_type;
  184. X  VATTR(savekey).af_lckname = VATTR(busykey).af_lckname;
  185. X  VATTR(savekey).af_lckhost = VATTR(busykey).af_lckhost;
  186. X  VATTR(savekey).af_ltime = (time_t) af_acttime ();
  187. X  
  188. X  /* if there is only one (the busy-) revision (..nrevs == 1) */
  189. X     /* then do initial save */
  190. X  if (busykey->af_ldes->af_nrevs == 1)
  191. X    {
  192. X      VATTR(savekey).af_gen = AF_INITGEN;
  193. X      VATTR(savekey).af_rev = AF_INITREV;
  194. X      VATTR(savekey).af_predgen = AF_NOVNUM;
  195. X      VATTR(savekey).af_predrev = AF_NOVNUM;
  196. X      VATTR(busykey).af_predgen = AF_INITGEN;
  197. X      VATTR(busykey).af_predrev = AF_INITREV;
  198. X      (void) af_nodelta (busykey, savekey);
  199. X    }
  200. X  else /* get some attributes from preceding revision */
  201. X    {
  202. X      lastkey = af_glastkey (busykey->af_ldes);
  203. X      VATTR(savekey).af_gen = VATTR(lastkey).af_gen; 
  204. X      VATTR(savekey).af_rev = VATTR(lastkey).af_rev+1;
  205. X      VATTR(savekey).af_predgen = VATTR(busykey).af_predgen;
  206. X      VATTR(savekey).af_predrev = VATTR(busykey).af_predrev;
  207. X      VATTR(busykey).af_predgen = VATTR(savekey).af_gen;
  208. X      VATTR(busykey).af_predrev = VATTR(savekey).af_rev;
  209. X      if (af_buildkey (busykey->af_ldes, VATTR(savekey).af_predgen, VATTR(savekey).af_predrev, &predkey) == ERROR)
  210. X    predkey.af_ldes = (Af_revlist *)0;
  211. X      (void) af_dodelta (busykey, &predkey, savekey);
  212. X    }
  213. X
  214. X  if (VATTR(busykey).af_variant)
  215. X    VATTR(savekey).af_variant = VATTR(busykey).af_variant;
  216. X  else
  217. X    VATTR(savekey).af_variant = (char *)0;
  218. X
  219. X  VATTR(savekey).af_state = AF_SAVED;
  220. X  VATTR(savekey).af_class = VATTR(busykey).af_class;
  221. X  author = af_getuser (getuid());
  222. X  VATTR(savekey).af_auname = af_entersym (author->af_username);
  223. X  VATTR(savekey).af_auhost = af_enterhost (author->af_userhost);
  224. X  (void) lstat (busykey->af_ldes->af_busyfilename, &ibuf);    
  225. X  VATTR(savekey).af_mode = ibuf.st_mode;
  226. X  VATTR(savekey).af_mtime = (time_t) af_cvttime (ibuf.st_mtime);
  227. X  VATTR(savekey).af_atime = (time_t) af_acttime ();
  228. X  VATTR(savekey).af_ctime = (time_t) af_cvttime (ibuf.st_mtime);
  229. X  VATTR(savekey).af_stime = (time_t) af_acttime ();
  230. X  VATTR(savekey).af_notesize = 1;
  231. X  VATTR(savekey).af_note = (char *)0;
  232. X  VATTR(savekey).af_nlinks = 1;
  233. X
  234. X  VATTR(savekey).af_udanum = VATTR(busykey).af_udanum;
  235. X  (void) af_hashinit (&(VATTR(savekey).af_uhtab), AF_MAXUDAS, af_fhash);
  236. X  (void) af_hashcopy (&(VATTR(busykey).af_uhtab), &(VATTR(savekey).af_uhtab));
  237. X  
  238. X  VATTR(savekey).af_hashname = (char *)0;
  239. X  VATTR(savekey).af_succgen = AF_NOVNUM;
  240. X  VATTR(savekey).af_succrev = AF_NOVNUM;
  241. X  
  242. X  /* update list descriptor */
  243. X  busykey->af_ldes->af_nrevs++;
  244. X  busykey->af_ldes->af_datasize += VATTR(savekey).af_notesize;
  245. X  busykey->af_ldes->af_refcount++;
  246. X  
  247. X  /* save changes */
  248. X  if (af_addvers (savekey) == ERROR)
  249. X    return (ERROR);
  250. X  
  251. X  return (AF_OK);
  252. X} /* af_saverev */
  253. X
  254. X
  255. X
  256. X/*====================================================================
  257. X *    af_newgen
  258. X *
  259. X *====================================================================*/
  260. X
  261. XEXPORT af_newgen (key, newkey)
  262. X     Af_key *key;
  263. X     Af_key *newkey; /* out */
  264. X{
  265. X  Af_key *lastkey, *busykey, *af_gbuskey(), *af_glastkey();
  266. X  int    af_fhash();
  267. X
  268. X  if (af_keytest (key))
  269. X    SFAIL ("newgen", "", AF_EINVKEY, ERROR);
  270. X
  271. X  if (key->af_ldes->af_nrevs == 1)
  272. X    SFAIL ("newgen", "", AF_ENOTVERS, ERROR);
  273. X
  274. X  if (VATTR(key).af_class & AF_DERIVED)
  275. X    SFAIL ("newgen", "", AF_EDERIVED, ERROR);
  276. X
  277. X  if ((VATTR(key).af_mode & S_IFMT) != S_IFREG)
  278. X    SFAIL ("newgen", "", AF_ENOTREGULAR, ERROR);
  279. X
  280. X  busykey = af_gbuskey (key->af_ldes);
  281. X  if (af_checkperm (busykey, AF_LOCKHOLDER) == ERROR)
  282. X    SFAIL ("newgen", "", AF_ENOTLOCKED, ERROR);
  283. X
  284. X  if (af_newvers (key->af_ldes, newkey, AF_SOURCE) == ERROR)
  285. X    return (ERROR);
  286. X
  287. X  lastkey = af_glastkey (key->af_ldes);
  288. X
  289. X  if ((VATTR(key).af_predgen == VATTR(lastkey).af_gen) && 
  290. X      (VATTR(key).af_predrev == VATTR(lastkey).af_rev))
  291. X    {
  292. X      VATTR(key).af_predgen++;
  293. X      VATTR(key).af_predrev = 0;
  294. X    }
  295. X
  296. X  /* duplicate last revision */
  297. X
  298. X  VATTR(newkey).af_gen = VATTR(lastkey).af_gen+1; 
  299. X  VATTR(newkey).af_rev = 0;
  300. X  VATTR(newkey).af_variant = VATTR(lastkey).af_variant;
  301. X  VATTR(newkey).af_predgen = VATTR(lastkey).af_gen;
  302. X  VATTR(newkey).af_predrev = VATTR(lastkey).af_rev;
  303. X
  304. X  (void) af_dodelta ((Af_key *)0, lastkey, newkey);
  305. X
  306. X  VATTR(newkey).af_name = VATTR(lastkey).af_name;
  307. X  VATTR(newkey).af_type = VATTR(lastkey).af_type;
  308. X  VATTR(newkey).af_variant = VATTR(lastkey).af_variant;
  309. X  VATTR(newkey).af_state = VATTR(lastkey).af_state;
  310. X  VATTR(newkey).af_class = VATTR(lastkey).af_class;
  311. X  VATTR(newkey).af_auname = VATTR(lastkey).af_auname;
  312. X  VATTR(newkey).af_auhost = VATTR(lastkey).af_auhost;
  313. X  VATTR(newkey).af_mode = VATTR(lastkey).af_mode;
  314. X  VATTR(newkey).af_mtime = VATTR(lastkey).af_mtime;
  315. X  VATTR(newkey).af_atime = VATTR(lastkey).af_atime;
  316. X  VATTR(newkey).af_ctime = VATTR(lastkey).af_ctime;
  317. X  VATTR(newkey).af_stime = VATTR(lastkey).af_stime;
  318. X  VATTR(newkey).af_notesize = VATTR(lastkey).af_notesize;
  319. X  VATTR(newkey).af_note = VATTR(lastkey).af_note;
  320. X  VATTR(newkey).af_lckname = (char *)0;
  321. X  VATTR(newkey).af_lckhost = (char *)0;
  322. X  VATTR(newkey).af_nlinks = 1;
  323. X
  324. X  VATTR(newkey).af_udanum = VATTR(lastkey).af_udanum;
  325. X  (void) af_hashinit (&(VATTR(newkey).af_uhtab), AF_MAXUDAS, af_fhash);
  326. X  (void) af_hashcopy (&(VATTR(lastkey).af_uhtab), &(VATTR(newkey).af_uhtab));
  327. X
  328. X  VATTR(newkey).af_succgen = AF_NOVNUM;
  329. X  VATTR(newkey).af_succrev = AF_NOVNUM;
  330. X
  331. X  /* update list descriptor */
  332. X  key->af_ldes->af_nrevs++;
  333. X  key->af_ldes->af_datasize += VATTR(newkey).af_notesize;
  334. X
  335. X  /* update predecessor of busy version */
  336. X  if  ((VATTR(busykey).af_predgen == VATTR(lastkey).af_gen) && 
  337. X       (VATTR(busykey).af_predrev == VATTR(lastkey).af_rev))
  338. X    {
  339. X      VATTR(busykey).af_predgen = VATTR(newkey).af_gen;
  340. X      VATTR(busykey).af_predrev = VATTR(newkey).af_rev;
  341. X    }
  342. X
  343. X  if (af_addvers (newkey) == ERROR)
  344. X    return (ERROR);
  345. X
  346. X  key->af_ldes->af_refcount++;
  347. X  return (AF_OK);
  348. X}
  349. X
  350. X
  351. X/*====================================================================
  352. X *    af_setbusy
  353. X *
  354. X *====================================================================*/
  355. X
  356. XEXPORT af_setbusy (busykey, newkey)
  357. X     Af_key *busykey, *newkey;
  358. X{
  359. X  Af_key *af_gbuskey();
  360. X
  361. X  if (af_keytest (newkey))
  362. X    SFAIL ("setbusy", "", AF_EINVKEY, ERROR);
  363. X
  364. X  if (busykey != (Af_key *)0)
  365. X    {
  366. X      if (af_keytest (busykey))
  367. X    SFAIL ("setbusy", "", AF_EINVKEY, ERROR);
  368. X      if (VATTR(busykey).af_state != AF_BUSY)
  369. X    SFAIL ("setbusy", "", AF_ENOTBUSY, ERROR);
  370. X      if (VATTR(busykey).af_class & AF_DERIVED)
  371. X    SFAIL ("setbusy", "", AF_EDERIVED, ERROR);
  372. X    }
  373. X  else
  374. X    {
  375. X      busykey = af_gbuskey (newkey->af_ldes);
  376. X    }
  377. X
  378. X  if (af_checkperm (busykey, AF_LOCKHOLDER) == ERROR)
  379. X    SFAIL ("setbusy", "", AF_ENOTLOCKED, ERROR);
  380. X
  381. X  /* if the two versions belong to one line of development */
  382. X  if (busykey->af_ldes->af_busyfilename == newkey->af_ldes->af_busyfilename)
  383. X    {
  384. X      VATTR(busykey).af_predgen = VATTR(newkey).af_gen;
  385. X      VATTR(busykey).af_predrev = VATTR(newkey).af_rev;
  386. X    }
  387. X  else
  388. X    {
  389. X      VATTR(busykey).af_predgen = AF_NOVNUM;
  390. X      VATTR(busykey).af_predrev = AF_NOVNUM;
  391. X    }
  392. X  if (af_updtvers (busykey, AF_CHANGE) == ERROR)
  393. X    return (ERROR);
  394. X
  395. X  return (AF_OK);
  396. X}
  397. X
  398. X
  399. X/*====================================================================
  400. X *    af_svnum
  401. X *
  402. X *====================================================================*/
  403. X
  404. XEXPORT af_svnum (key, gen, rev)
  405. X     Af_key *key;
  406. X     int gen, rev;
  407. X{
  408. X  Af_key predkey, *lastkey, *af_glastkey();
  409. X
  410. X  if (af_keytest (key))
  411. X    SFAIL ("svnum", "", AF_EINVKEY, ERROR);
  412. X
  413. X  if ((VATTR(key).af_state == AF_BUSY) || (VATTR(key).af_state > AF_PROPOSED))
  414. X    SFAIL ("svnum", "", AF_EWRONGSTATE, ERROR);
  415. X
  416. X  if (!(VATTR(key).af_class & AF_DERIVED)) /* derived files can get any vnum */
  417. X    {
  418. X      if (af_checkperm (key, AF_LOCKHOLDER) == ERROR)
  419. X    SFAIL ("svnum", "", AF_ENOTLOCKED, ERROR);
  420. X
  421. X      /* only the version number of the last saved version can be modified */
  422. X      lastkey = af_glastkey (key->af_ldes);
  423. X      if (af_keycmp (key, lastkey))
  424. X    SFAIL ("svnum", "can set version number only for last saved version",
  425. X           AF_EMISC, ERROR);
  426. X
  427. X      /* if new version number is smaller than the old one */
  428. X      if (gen < VATTR(key).af_gen)
  429. X    SFAIL ("svnum", "", AF_EINVVNUM, ERROR);
  430. X      if (gen == VATTR(key).af_gen)
  431. X    {
  432. X      if (rev < VATTR(key).af_rev)
  433. X        SFAIL ("svnum", "", AF_EINVVNUM, ERROR);
  434. X    }
  435. X      /* read data file in order to get it updated */
  436. X      if (af_readdata (key->af_ldes) == ERROR)
  437. X    return (ERROR);
  438. X    }
  439. X
  440. X  VATTR(key).af_gen = (short)gen;
  441. X  VATTR(key).af_rev = (short)rev;
  442. X
  443. X  /* if a predecessor exists, update its successor field */
  444. X  if (af_buildkey (key->af_ldes, VATTR(key).af_predgen,
  445. X           VATTR(key).af_predrev, &predkey) == AF_OK)
  446. X    {
  447. X      VATTR((&predkey)).af_succgen = (short)gen;
  448. X      VATTR((&predkey)).af_succrev = (short)rev;
  449. X    }
  450. X
  451. X  /* the predecessor is updated implicitely by af_updtvers (key) */
  452. X  if (af_updtvers (key, AF_CHANGE) == ERROR)
  453. X    return (ERROR);
  454. X
  455. X  return (AF_OK);
  456. X}
  457. X
  458. END_OF_FILE
  459. if test 13536 -ne `wc -c <'src/afs/afvers.c'`; then
  460.     echo shar: \"'src/afs/afvers.c'\" unpacked with wrong size!
  461. fi
  462. # end of 'src/afs/afvers.c'
  463. fi
  464. if test -f 'src/misc/ParseArgs.c' -a "${1}" != "-c" ; then 
  465.   echo shar: Will not clobber existing file \"'src/misc/ParseArgs.c'\"
  466. else
  467. echo shar: Extracting \"'src/misc/ParseArgs.c'\" \(12926 characters\)
  468. sed "s/^X//" >'src/misc/ParseArgs.c' <<'END_OF_FILE'
  469. X/*
  470. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  471. X *  and U. Pralle
  472. X * 
  473. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  474. X * WARRANTY for any part of this software to work correctly or as described
  475. X * in the manuals. We do not accept any liability for any kind of damage
  476. X * caused by use of this software, such as loss of data, time, money, or 
  477. X * effort.
  478. X * 
  479. X * Permission is granted to use, copy, modify, or distribute any part of
  480. X * this software as long as this is done without asking for charge, and
  481. X * provided that this copyright notice is retained as part of the source
  482. X * files. You may charge a distribution fee for the physical act of
  483. X * transferring a copy, and you may at your option offer warranty
  484. X * protection in exchange for a fee.
  485. X * 
  486. X * Direct questions to: Tech. Univ. Berlin
  487. X *              Wilfried Koch
  488. X *              Sekr. FR 5-6 
  489. X *              Franklinstr. 28/29
  490. X *              D-1000 Berlin 10, West Germany
  491. X * 
  492. X *              Tel: +49-30-314-22972
  493. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  494. X */
  495. Xstatic char *AFSid = "$Header: ParseArgs.c[2.1] Thu Feb 23 21:24:12 1989 axel@coma published $";
  496. X
  497. X/*
  498. X * Log for /u/shape/dist-tape/src/misc/ParseArgs.c[1.1]
  499. X *     Thu Feb 23 21:24:12 1989 axel@coma save $
  500. X *  --- empty log message ---
  501. X *  ParseArgs.c[2.0] Thu Feb 23 21:24:12 1989 axel@coma published $
  502. X *  --- empty log message ---
  503. X *  ParseArgs.c[2.1] Thu Feb 23 21:24:12 1989 axel@coma published $
  504. X *  --- empty log message ---
  505. X */
  506. X
  507. X#include <stdio.h>
  508. X#include <strings.h>
  509. X
  510. X#include "ParseArgs.h"
  511. X
  512. Xstatic char *RCSid = "$Header: ParseArgs.c,v 2.0 88/06/29 16:14:32 axel Stable $";
  513. X#ifdef CFFLGS
  514. Xstatic char *Cflags = CFFLGS;
  515. X#endif CFFLGS
  516. X
  517. X/*
  518. X * $Log:    ParseArgs.c,v $
  519. X * Revision 2.0  88/06/29  16:14:32  axel
  520. X * New System Generation
  521. X * 
  522. X * Revision 1.1  88/06/07  17:10:01  axel
  523. X * This version is part of a release
  524. X * 
  525. X * Revision 1.8  88/03/12  20:34:34  uli
  526. X * *** empty log message ***
  527. X * 
  528. X * Revision 1.7  88/03/10  14:06:47  uli
  529. X * ParseArgs returns now the number of error encountered during parse.
  530. X * A return value of 0 means no error. This is incompatible to the previous
  531. X * versions. Is this a so called "variant" ? Should i release the previous
  532. X * version ?
  533. X *                         Uli
  534. X * 
  535. X * Revision 1.6  88/03/08  20:48:53  uli
  536. X * blabla.
  537. X * 
  538. X * Revision 1.5  88/03/08  20:03:01  uli
  539. X * pa_ShortUsage added. If called, builds a usage.
  540. X * 
  541. X * Revision 1.4  88/03/08  15:34:58  uli
  542. X * Order of options is no longer important. Options are rearrange in
  543. X * longest first order.
  544. X * 
  545. X * Revision 1.3  88/03/04  15:36:23  uli
  546. X * Some bugs fixed.
  547. X * 
  548. X * 
  549. X * Revision 1.2  88/02/23  13:53:34  uli
  550. X * Error in ParseArguments fixed: newav is now (unsigned long*).
  551. X * 
  552. X * Revision 1.1  88/02/23  12:42:27  uli
  553. X * Initial revision
  554. X * 
  555. X * Revision 1.2  88/02/18  14:33:52  uli
  556. X * *** empty log message ***
  557. X * 
  558. X */
  559. X
  560. X/*
  561. X * Exports:
  562. X *
  563. X * Type: OptDesc;
  564. X * Function: ParseArgs (ac, av, newac, newav, optdesc)
  565. X *               int ac;
  566. X *                char **av;
  567. X *                int newac;
  568. X *                char **newav;
  569. X *                OptDesc *optdesc;
  570. X *
  571. X *           ParseArgs returns 1 on success, 0 on failure.
  572. X *
  573. X */
  574. X
  575. X/*
  576. X * Description:
  577. X * 
  578. X * ParseArgs scans and tokenizes the argument string in its components.
  579. X * Components are the name of the called program, the options, the
  580. X * arguments of options, and the pure arguments (i.e.  non options).
  581. X *
  582. X * An Option is specified by its name, kind, and a function, that
  583. X * handles this option. Name is a (possible multi character) string.
  584. X * The kind specifies iff the option is an ordinary switch,
  585. X * an options with an optional argument,  * or an option that
  586. X * requires an argument. The function is called whenever the options
  587. X * is detected in the argument string. The number of the function
  588. X * parameters depends on the options' kind. The detected option
  589. X * is passed everytime as the first parameter. If this option
  590. X * has a (possible optional) argument, it is passed to the handler as the
  591. X * second parameter. If the argument is missed in the argument string,
  592. X * then a string which contains only a null byte is passed to the handler.
  593. X *
  594. X * Example:
  595. X *
  596. X * OptDesc odesc[] = {
  597. X *    { "l", OPT_IS_SWITCH, handle_i_option },
  598. X *    { "f", OPT_HAS_ARG, handle_f_options },
  599. X *      { "o", OPT_HAS_OPT_ARG, handle_o_option}
  600. X * }
  601. X *
  602. X * In this example we have declared 'l', 'f', and 'o' to be options.
  603. X * 'l' is a ordinary switch, 'f' requires an argument, and 'o' may
  604. X * have an argument. Handle_i_options, handle_f_option, and
  605. X * and handle_o_option are the option handlers called. The handler
  606. X * are declared:
  607. X *
  608. X *    int handle_i_option (option)
  609. X *        char *option;
  610. X *
  611. X *      int handle_f_option (option, options_argument);
  612. X *        char *option, *options_argument;
  613. X *
  614. X *    int handle_o_option (option, options_argument);
  615. X *        char *option, *options_argument;
  616. X *
  617. X * Everytime '-i' is detected, handle_i_option is called
  618. X *        handle_i_option ("i");
  619. X * handle_f_option is called
  620. X *        handle_f_option ("f", argument);
  621. X * and handle_o_option is called
  622. X *        handle_o_option ("o", argument);
  623. X *
  624. X * If the argument of the options 'f' or 'o' are missed,
  625. X * the handler are called with
  626. X *        handler ("<options name>", "");
  627. X *
  628. X *
  629. X * BUGS:
  630. X *    The longest options is matched. If you have declared
  631. X *    'o' as an options with an argument and 'op' as a
  632. X *      switch, the option 'o' is never detected, because
  633. X *      'op' is longer.
  634. X */
  635. X  
  636. X/*
  637. X * Externals
  638. X */
  639. Xextern char *malloc();
  640. X
  641. X#define MINUS_CHAR_REQUIRED 1
  642. X
  643. X/*
  644. X * Variables
  645. X */
  646. X
  647. X#ifdef DEBUG_PARSE
  648. Xstatic int debug_parse = 0;
  649. X#endif DEBUG_PARSE
  650. X
  651. Xstatic
  652. Xint GetNextOption (str, odesc, minus_char_required)
  653. X     char *str;
  654. X     OptDesc odesc[];
  655. X     int minus_char_required;
  656. X{
  657. X  int i, j;
  658. X
  659. X  if (!str) return -1;
  660. X
  661. X  if (minus_char_required) {
  662. X    if (*str != '-')
  663. X      return -1;
  664. X  }
  665. X  
  666. X  if (*str == '-') {
  667. X    str++;
  668. X  }
  669. X  
  670. X  for (i = 0; odesc[i].opt_name; i++) {
  671. X    if (!(j = strncmp (odesc[i].opt_name,
  672. X               str, strlen (odesc[i].opt_name))))
  673. X      return i;
  674. X  }
  675. X  return -1;
  676. X}
  677. X
  678. X
  679. Xstatic
  680. Xint IsOption (str, odesc, minus_char_required)
  681. X     char *str;
  682. X     OptDesc odesc[];
  683. X     int minus_char_required;
  684. X{
  685. X  return (GetNextOption (str, odesc, minus_char_required) >= 0 ? 1 : 0);
  686. X}
  687. X
  688. Xstatic
  689. Xchar *SkipThisOption (str, length)
  690. X     char *str;
  691. X     int length;
  692. X{
  693. X  if (*str == '-') str++;
  694. X  return (str + length);
  695. X}
  696. X
  697. Xstatic
  698. Xint cmp_length (left, right)
  699. X     OptDesc *left, *right;
  700. X{
  701. X  return (strlen (right->opt_name) - strlen (left->opt_name));
  702. X}
  703. X
  704. Xstatic
  705. Xint cmp_alpha (left, right)
  706. X     OptDesc *left, *right;
  707. X{
  708. X  return (strcmp (left->opt_name, right->opt_name));
  709. X}
  710. X
  711. Xstatic
  712. Xint RearrangeOptDesc (odesc, cmp_function)
  713. X     OptDesc *odesc;
  714. X     int (*cmp_function)();    /* function that compares */
  715. X{
  716. X  int nelem;
  717. X
  718. X  for (nelem = 0; odesc[nelem].opt_name; nelem++) ;
  719. X  
  720. X  qsort (odesc, nelem, sizeof (struct optdesc), cmp_function);
  721. X}
  722. X
  723. Xint ParseArgs (pac, pav, newac, newav, odesc)
  724. X     int pac;            /* number arguments */
  725. X     char **pav;        /* the arguments itself */
  726. X     int *newac;        /* number arguments after parsing */
  727. X     unsigned long *newav;    /* the arguments after parsing */
  728. X     OptDesc odesc[];        /* the options descriptions */
  729. X{
  730. X
  731. X  char **cpp;            /* temporary points to pav */
  732. X  char **ArgV;
  733. X  char *this_arg;        /* points to the current argument */
  734. X  int option, minus_char_required, opterr = 0;
  735. X  char *optrepr;
  736. X  int optkind;
  737. X  int (*opthandler)();
  738. X    
  739. X  /*
  740. X   * inititialization phase
  741. X   */
  742. X  *newac = 0;
  743. X
  744. X  /* allocate some memory for newav */
  745. X  if ((ArgV = (char **) malloc (sizeof (char **) * (pac + 1))) == (char **) NULL) {
  746. X    perror ("malloc");
  747. X    exit (1);
  748. X  }
  749. X
  750. X  RearrangeOptDesc (odesc, cmp_length);    /* sort by length */
  751. X  
  752. X#ifdef DEBUG_PARSE
  753. X  if (!strcmp (pav[1], "\001\002")) { /* ^A^B */
  754. X    debug_parse++; 
  755. X    fprintf (stderr, "ParseArgs: debugging enabled.\n");
  756. X  }
  757. X#endif DEBUG_PARSE
  758. X
  759. X  /*
  760. X   * scanning phase
  761. X   */
  762. X  pav++;        /* skip program name */
  763. X
  764. X#ifdef DEBUG_PARSE
  765. X  if (debug_parse) pav++;
  766. X#endif DEBUG_PARSE
  767. X  
  768. X  while (pav && *pav) {
  769. X    this_arg = *pav;        /* beginning of next argument */
  770. X    minus_char_required = 1;    /* require a '-' if argument is a option */
  771. X    
  772. X    while (this_arg && *this_arg) {
  773. X      if ((option = GetNextOption (this_arg, odesc, minus_char_required)) >= 0) {
  774. X    optrepr = odesc[option].opt_name; /* option's name */
  775. X    optkind = odesc[option].opt_kind; /* option's kind */
  776. X    opthandler = odesc[option].opt_handler;    /* option's handler */
  777. X    
  778. X    this_arg = SkipThisOption (this_arg, strlen (optrepr));
  779. X    minus_char_required = 0; /* -fe  f AND e are options */
  780. X    
  781. X    switch (optkind) {
  782. X    case OPT_IS_SWITCH:
  783. X      opterr += opthandler (optrepr);
  784. X      break;
  785. X    case OPT_HAS_OPT_ARG:
  786. X      /*
  787. X       * at this point, this_arg points to the next char after
  788. X       * the detected option or this_arg has reached the end.
  789. X       */
  790. X      if (!*this_arg) { /* *this_arg == '\0' */
  791. X        if (*++pav) { /* next arg exists */
  792. X          this_arg = *pav;
  793. X          if (IsOption (this_arg, odesc, MINUS_CHAR_REQUIRED)) { /* always '-' required */
  794. X        opterr += opthandler (optrepr, "");
  795. X        this_arg = NULL;
  796. X        pav--;
  797. X          }
  798. X          else {
  799. X        opterr += opthandler (optrepr, this_arg);
  800. X        this_arg = NULL;
  801. X          }
  802. X        }
  803. X        else { /* end of pav reached */
  804. X          opterr += opthandler (optrepr, "");
  805. X          this_arg = NULL;
  806. X          pav--;
  807. X        }
  808. X      }
  809. X      else {
  810. X        if (! IsOption (this_arg, odesc, (! MINUS_CHAR_REQUIRED))) { /* rest of this_arg contains arg */
  811. X          opterr += opthandler (optrepr, this_arg);
  812. X          this_arg = NULL;
  813. X        }
  814. X        else {
  815. X          opterr += opthandler (optrepr, "");
  816. X        }
  817. X      }
  818. X      break;
  819. X    case OPT_HAS_ARG:
  820. X      if (!*this_arg) { /* end of this arg reached */
  821. X        pav++;
  822. X        this_arg = *pav;
  823. X        if (!this_arg) { /* end of pav reached */
  824. X          opterr += opthandler (optrepr, "");
  825. X          this_arg = NULL;
  826. X          pav--;
  827. X        }
  828. X        else {
  829. X          opterr += opthandler (optrepr, this_arg);
  830. X          this_arg = NULL;
  831. X        }
  832. X      }
  833. X      else {
  834. X        opterr += opthandler (optrepr, this_arg);
  835. X        this_arg = NULL;
  836. X      }
  837. X      break;
  838. X    default:
  839. X      fprintf (stderr, "ParseOpt: Non option detected as option: %s.\n",
  840. X           odesc[option].opt_name);
  841. X      exit (1);
  842. X      break;
  843. X    } /* end switch */
  844. X      } /* end then */
  845. X      else {            /* argument is not a options */
  846. X    ArgV[*newac] = this_arg;
  847. X    (*newac)++;
  848. X    this_arg = NULL;
  849. X      }
  850. X    }
  851. X    pav++;            /* select next argument */
  852. X  }
  853. X    
  854. X  /* finalization phase  */
  855. X  ArgV[*newac] = (char *) NULL;
  856. X
  857. X#ifdef DEBUG_PARSE
  858. X  if (debug_parse) {
  859. X    int j;
  860. X    fprintf (stderr, "ParseArgs: Pure Arguments are:\nParseArgs:\t");
  861. X
  862. X    if (!*ArgV) fprintf (stderr, "<none>\n");
  863. X    else {
  864. X      for (j = 0; ArgV[j]; j++) {
  865. X    fprintf (stderr, "%s ", ArgV[j]);
  866. X      }
  867. X      fprintf (stderr, "\n");
  868. X    }
  869. X    debug_parse = 0;
  870. X    fprintf (stderr, "ParseArgs: Debugging disabled.\n");
  871. X  }
  872. X#endif DEBUG_PARSE
  873. X
  874. X  *newav = (unsigned long) ArgV;
  875. X  return opterr;        /* return # of errors. 0 means no error */
  876. X}
  877. X
  878. Xpa_ShortUsage (progname, odesc, extra_text)
  879. X     char *progname;
  880. X     struct optdesc odesc[];
  881. X     char *extra_text;
  882. X{
  883. X  int i;
  884. X  int twidth = 80;
  885. X  int c_printed = 6;
  886. X  int length = 0;
  887. X  int nextlineoff;
  888. X  char buf[80];
  889. X  
  890. X  RearrangeOptDesc (odesc, cmp_alpha);
  891. X
  892. X#define GetTerminalWidth(x) 80
  893. X  twidth = GetTerminalWidth();
  894. X  
  895. X  fprintf (stderr, "usage:");
  896. X  
  897. X  if (progname && *progname) {
  898. X    fprintf (stderr, " %s:", progname);
  899. X    c_printed += strlen (progname) + 2;
  900. X  }
  901. X
  902. X  nextlineoff = c_printed + 3;
  903. X  
  904. X  /* first switches than option requiring an agrument */
  905. X  fprintf (stderr, " [-");
  906. X  c_printed += 3;
  907. X  
  908. X  for (i = 0; odesc[i].opt_name; i++) {
  909. X    if (odesc[i].opt_kind == OPT_IS_SWITCH) {
  910. X      length = strlen (odesc[i].opt_name); length++;
  911. X      if (c_printed + length > twidth) {
  912. X    c_printed = length + nextlineoff;
  913. X    sprintf (buf, "\n%%%dc", nextlineoff);
  914. X    fprintf (stderr, buf, ' ');
  915. X      }
  916. X      else {
  917. X    c_printed += length;
  918. X      }
  919. X      
  920. X      fprintf (stderr, " %s", odesc[i].opt_name);
  921. X    }
  922. X  }
  923. X
  924. X  fprintf (stderr, "]"); c_printed++;
  925. X  nextlineoff -= 3;
  926. X  
  927. X  for (i = 0; odesc[i].opt_name; i++) {
  928. X    length = strlen (odesc[i].opt_name);
  929. X    
  930. X    switch (odesc[i].opt_kind) {
  931. X    case OPT_IS_SWITCH:
  932. X        break;
  933. X    case OPT_HAS_OPT_ARG:
  934. X    if ((c_printed + 14 + length) > 80) {
  935. X      c_printed = length + nextlineoff + 14;
  936. X      sprintf (buf, "\n%%%dc", nextlineoff);
  937. X      fprintf (stderr, buf, ' ');
  938. X    }
  939. X    else {
  940. X      c_printed += length + 14;
  941. X    }
  942. X        
  943. X    fprintf (stderr, " [-%s <opt arg>]", odesc[i].opt_name);
  944. X      break;
  945. X    case OPT_HAS_ARG:
  946. X    if ((c_printed + 10 + length) > 80) {
  947. X      c_printed = length + nextlineoff + 10;
  948. X      sprintf (buf, "\n%%%dc", nextlineoff);
  949. X      fprintf (stderr, buf, ' ');
  950. X    }
  951. X    else {
  952. X      c_printed += length + 10;
  953. X    }
  954. X        
  955. X      fprintf (stderr, " [-%s <arg>]", odesc[i].opt_name);
  956. X      break;
  957. X    default:
  958. X      break;
  959. X    }
  960. X  }
  961. X
  962. X  if ((strlen (extra_text) + c_printed + 1) > twidth) {
  963. X    sprintf (buf, "\n%%%dc", nextlineoff);
  964. X    fprintf (stderr, buf, ' ');
  965. X  }
  966. X  
  967. X  fprintf (stderr, " %s\n", extra_text);
  968. X}
  969. END_OF_FILE
  970. if test 12926 -ne `wc -c <'src/misc/ParseArgs.c'`; then
  971.     echo shar: \"'src/misc/ParseArgs.c'\" unpacked with wrong size!
  972. fi
  973. # end of 'src/misc/ParseArgs.c'
  974. fi
  975. if test -f 'src/shape/misc.c' -a "${1}" != "-c" ; then 
  976.   echo shar: Will not clobber existing file \"'src/shape/misc.c'\"
  977. else
  978. echo shar: Extracting \"'src/shape/misc.c'\" \(13128 characters\)
  979. sed "s/^X//" >'src/shape/misc.c' <<'END_OF_FILE'
  980. X/*
  981. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  982. X *  and U. Pralle
  983. X * 
  984. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  985. X * WARRANTY for any part of this software to work correctly or as described
  986. X * in the manuals. We do not accept any liability for any kind of damage
  987. X * caused by use of this software, such as loss of data, time, money, or 
  988. X * effort.
  989. X * 
  990. X * Permission is granted to use, copy, modify, or distribute any part of
  991. X * this software as long as this is done without asking for charge, and
  992. X * provided that this copyright notice is retained as part of the source
  993. X * files. You may charge a distribution fee for the physical act of
  994. X * transferring a copy, and you may at your option offer warranty
  995. X * protection in exchange for a fee.
  996. X * 
  997. X * Direct questions to: Tech. Univ. Berlin
  998. X *              Wilfried Koch
  999. X *              Sekr. FR 5-6 
  1000. X *              Franklinstr. 28/29
  1001. X *              D-1000 Berlin 10, West Germany
  1002. X * 
  1003. X *              Tel: +49-30-314-22972
  1004. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  1005. X */
  1006. X#ifndef lint
  1007. Xstatic char *RCSid = "$Header: misc.c,v 3.5 89/02/21 17:11:54 wolfgang Exp $";
  1008. X#endif
  1009. X#ifndef lint
  1010. Xstatic char *ConfFlg = CFFLGS;    /* should be defined from within Makefile */
  1011. X#endif
  1012. X/*
  1013. X * $Log:    misc.c,v $
  1014. X * Revision 3.5  89/02/21  17:11:54  wolfgang
  1015. X * append_mtime changed
  1016. X * 
  1017. X * Revision 3.4  89/02/20  16:26:08  wolfgang
  1018. X * NET-RELEASE
  1019. X * 
  1020. X * Revision 3.3  89/02/08  16:19:55  wolfgang
  1021. X * one comment added for lint.
  1022. X * ..
  1023. X * 
  1024. X * Revision 3.2  89/02/08  12:46:32  wolfgang
  1025. X * performance improved.
  1026. X * 
  1027. X * Revision 3.1  89/02/06  14:26:41  wolfgang
  1028. X * bug fixed.
  1029. X * 
  1030. X * Revision 3.0  89/01/24  11:36:12  wolfgang
  1031. X * New System Generation
  1032. X * 
  1033. X * Revision 2.19  89/01/23  16:14:42  wolfgang
  1034. X * inheritance of uda's is now suppressed
  1035. X * 
  1036. X * Revision 2.18  89/01/03  13:12:23  wolfgang
  1037. X * changes done for lint
  1038. X * 
  1039. X * Revision 2.17  88/12/22  12:36:39  wolfgang
  1040. X * dummy procedure free_linklist()m added.
  1041. X * 
  1042. X * Revision 2.16  88/12/21  15:11:10  wolfgang
  1043. X * changes done for lint
  1044. X * 
  1045. X * Revision 2.15  88/12/19  13:21:27  wolfgang
  1046. X * is_in_forcelist added().
  1047. X * 
  1048. X * Revision 2.14  88/11/23  12:35:48  wolfgang
  1049. X * Another dorpkey added.
  1050. X * 
  1051. X * Revision 2.13  88/11/21  20:55:10  wolfgang
  1052. X * changes done for sun
  1053. X * 
  1054. X * Revision 2.12  88/11/09  16:25:59  wolfgang
  1055. X * bugs fixed
  1056. X * 
  1057. X * Revision 2.11  88/11/08  11:05:02  wolfgang
  1058. X * This version is part of a release
  1059. X * 
  1060. X * Revision 2.10  88/11/03  17:29:46  wolfgang
  1061. X * calls of af_dropset added in compare_attrstring().
  1062. X * 
  1063. X * Revision 2.9  88/10/10  16:54:43  wolfgang
  1064. X * changed for the -t option. if (touchflg) nothing is restored.
  1065. X * 
  1066. X * Revision 2.8  88/09/23  15:54:20  wolfgang
  1067. X * bug fixed in get_attr_type (retrn values).
  1068. X * 
  1069. X * Revision 2.7  88/09/22  16:15:06  wolfgang
  1070. X * clleanup_links() changed (now recursive).
  1071. X * 
  1072. X * Revision 2.6  88/09/07  11:23:30  wolfgang
  1073. X * unlinking of tmp file added to cleanup_links().
  1074. X * 
  1075. X * Revision 2.5  88/08/25  16:09:07  wolfgang
  1076. X * Message: ... restored from bpool changed; [busy] is supreesed and if
  1077. X * type = "" the "." is supressed.
  1078. X * 
  1079. X * Revision 2.4  88/08/22  15:30:43  wolfgang
  1080. X * Two types added: syspath & host; are necessary for confid.
  1081. X * 
  1082. X * Revision 2.3  88/08/22  11:24:06  wolfgang
  1083. X * Attribute string changed: added "." between name & type.
  1084. X * 
  1085. X * Revision 2.2  88/08/19  10:05:59  wolfgang
  1086. X * bug fixed; if attrs were too long for bpool file, the identification
  1087. X * of the busy version had not been correct.
  1088. X * Furthermore the format of the string "... version restored ..." has
  1089. X * been changed, so that -2 .-2 for busy Version is supressed.
  1090. X * 
  1091. X * Revision 2.1  88/08/18  13:19:41  wolfgang
  1092. X * minor bug fixes; mtime added to identification string of derived objects
  1093. X * 
  1094. X */
  1095. X
  1096. X#include <sys/types.h>
  1097. X#include <sys/dir.h>
  1098. X#include "shape.h"
  1099. X
  1100. Xextern char *forcelist[];
  1101. Xextern Bool is_in_forcelist();
  1102. Xextern char *template;
  1103. Xextern int af_cleanup();
  1104. X
  1105. X/* Struct for registering links */
  1106. Xstruct linkreg *link_reg = (struct linkreg *) NIL;
  1107. Xstruct linkreg *last_link;
  1108. X
  1109. Xchar *longattrs[MAXDEPTH];
  1110. X
  1111. Xchar *types[] = { "generation",          /*  0  int */
  1112. X          "revision",            /*  1  int */
  1113. X          "state",               /*  2  short */
  1114. X          "author",              /*  3  short */
  1115. X          "group",               /*  4  short */
  1116. X          "version",             /*  5  char * */
  1117. X          "variant",             /*  6  char * */
  1118. X          "syspath",             /*  7  char * */
  1119. X          "host",                /*  8  char * */
  1120. X          "0"};                  /* 99  default = char *
  1121. X                        (for userdefined attributes */
  1122. X
  1123. X
  1124. Xchar *states[] = { "busy",
  1125. X           "saved",
  1126. X           "proposed",
  1127. X           "published",
  1128. X           "accessed",
  1129. X           "frozen",
  1130. X           "0"};
  1131. X  
  1132. X
  1133. Xint get_attr_type(name)
  1134. X     char *name;
  1135. X{
  1136. X  int i = 0;
  1137. X
  1138. X  if (name == NIL)
  1139. X    return(99);
  1140. X
  1141. X  while(strcmp(types[i],"0") != 0)
  1142. X    {
  1143. X      if((strcmp(types[i],name) == 0))
  1144. X    return(i);
  1145. X      i++;
  1146. X    }
  1147. X  return(99);
  1148. X}
  1149. X
  1150. Xint get_state_no(state)
  1151. X     char *state;
  1152. X{
  1153. X  int i = 0;
  1154. X  while(strcmp(states[i],"0") != 0)
  1155. X    {
  1156. X      if((strcmp(states[i],state) == 0))
  1157. X    return(i);
  1158. X      i++;
  1159. X    }
  1160. X  return(99);
  1161. X}
  1162. X
  1163. X
  1164. Xstruct linkreg *init_linkreg()
  1165. X{
  1166. X  struct linkreg *lreg = (struct linkreg *) NIL;
  1167. X
  1168. X  if ((lreg = (struct linkreg *) malloc(sizeof(struct linkreg))) ==
  1169. X      (struct linkreg *) NIL)
  1170. X    errexit(10,"malloc");
  1171. X  if((lreg->fn = malloc(MAXNAMLEN)) == NIL)
  1172. X    errexit(10,"malloc");
  1173. X  if((lreg->newfn = malloc(MAXNAMLEN)) == NIL)
  1174. X    errexit(10,"malloc");
  1175. X  lreg->fn[0] = '\0';
  1176. X  lreg->newfn[0] = '\0';
  1177. X  lreg->next = (struct linkreg *) NIL;
  1178. X
  1179. X  return(lreg);
  1180. X}
  1181. X
  1182. X
  1183. Xregister_link(fn, newfn, busy_exist)
  1184. X     char *fn;
  1185. X     char *newfn;
  1186. X     Bool busy_exist;
  1187. X{
  1188. X  if (link_reg == (struct linkreg *) NIL)
  1189. X    {
  1190. X      link_reg = init_linkreg();
  1191. X      (void) strcpy(link_reg->fn, fn);
  1192. X      (void) strcpy(link_reg->newfn, newfn);
  1193. X      link_reg->busy_exist = busy_exist;
  1194. X      last_link = link_reg;
  1195. X    }
  1196. X  else
  1197. X    {
  1198. X      last_link->next = init_linkreg();
  1199. X      last_link = last_link->next;
  1200. X      (void) strcpy(last_link->fn, fn);
  1201. X      (void) strcpy(last_link->newfn, newfn);
  1202. X      last_link->busy_exist = busy_exist;
  1203. X    }
  1204. X}
  1205. X
  1206. Xcleanup_links(cur_link)
  1207. X     struct linkreg *cur_link;
  1208. X{
  1209. X  char filename[MAXNAMLEN];
  1210. X  char afsname[MAXNAMLEN];
  1211. X  if(cur_link != (struct linkreg *) NIL)
  1212. X    {
  1213. X      cleanup_links(cur_link->next);
  1214. X    }
  1215. X  if(cur_link != (struct linkreg *) NIL)
  1216. X    {
  1217. X      if(rindex(cur_link->fn,'/') == 0)
  1218. X    {
  1219. X      (void) strcpy(filename, "./");
  1220. X      (void) strcat(filename, cur_link->fn);
  1221. X      (void) strcpy(afsname, "./");
  1222. X      (void) strcat(afsname, cur_link->newfn);
  1223. X    }
  1224. X      else
  1225. X    {
  1226. X      (void) strcpy(filename, cur_link->fn);
  1227. X      (void) strcpy(afsname, cur_link->newfn);
  1228. X    }
  1229. X      if (unlink(filename) != 0)
  1230. X    {
  1231. X      fprintf(stderr, "shape - Aaaaaaaaaaaaaaaaargh !!!!!\n");
  1232. X      fprintf(stderr, "error while cleaning up links :\n");
  1233. X      fprintf(stderr, "can't unlink %s\n", filename);
  1234. X      fprintf(stderr, "contact guru immediately !\n");
  1235. X      af_cleanup();
  1236. X      exit(1);
  1237. X    }
  1238. X      if (cur_link->busy_exist)
  1239. X    {
  1240. X      if (link(afsname,filename) != 0)
  1241. X        {
  1242. X          fprintf(stderr, "shape - Aaaaaaaaaaaaaaaaargh !!!!!\n");
  1243. X          fprintf(stderr, "error while cleaning up links :\n");
  1244. X          fprintf(stderr, "can't link %s to %s\n", filename, afsname);
  1245. X          fprintf(stderr, "contact guru immediately !\n");
  1246. X          af_cleanup();
  1247. X          exit(1);
  1248. X        }
  1249. X      if (unlink(afsname) != 0)
  1250. X        {
  1251. X          fprintf(stderr, "shape - Aaaaaaaaaaaaaaaaargh !!!!!\n");
  1252. X          fprintf(stderr, "error while cleaning up links :\n");
  1253. X          fprintf(stderr, "can't unlink %s\n", filename);
  1254. X          fprintf(stderr, "contact guru immediately !\n");
  1255. X          af_cleanup();
  1256. X          exit(1);
  1257. X        }
  1258. X    }
  1259. X    }
  1260. X}
  1261. X
  1262. Xint free_linklist()
  1263. X{
  1264. X/* not yet implemented */
  1265. X/* should free memory of linklist */
  1266. X  ;
  1267. X}
  1268. X  
  1269. XBool compare_attrstring(attr, rulename, name, objrulename)
  1270. X     /*ARGSUSED*/
  1271. X     char *attr;
  1272. X     struct rules *rulename;
  1273. X     char *name;
  1274. X     struct rules *objrulename;
  1275. X{
  1276. X  Af_set aset;
  1277. X  Af_set bset;
  1278. X  Af_attrs buf;
  1279. X  Af_attrs buf1;
  1280. X  Af_attrs buf2;
  1281. X  Af_key akey;
  1282. X  Af_key bkey;
  1283. X  Af_key key1;
  1284. X  Af_key key2;
  1285. X  Af_key restorekey;
  1286. X
  1287. X  int retcode;
  1288. X  int retcode1;
  1289. X  char bname[MAXNAMLEN];
  1290. X  char *type;
  1291. X  char *p;
  1292. X  char *d;
  1293. X  char sysp[MAXNAMLEN];
  1294. X
  1295. X  if (touchflg)
  1296. X    return(0);
  1297. X  
  1298. X  sysp[0] = '\0';
  1299. X
  1300. X  (void) strcpy(bname,name);
  1301. X  if ((p = rindex(bname,'.')) == 0)
  1302. X    {
  1303. X      type = NIL;
  1304. X    }
  1305. X  else
  1306. X    {
  1307. X      p[0] = '\0';
  1308. X      *p++;
  1309. X      type = p;
  1310. X    }
  1311. X
  1312. X  if ((d = rindex(bname,'/')) != 0)
  1313. X    {
  1314. X      (void) strcpy(sysp, bname);
  1315. X      d = rindex(sysp, '/');
  1316. X      d[0] = '\0';
  1317. X      *d++;
  1318. X      (void) strcpy(bname,d);
  1319. X    }
  1320. X  af_initattrs(&buf);
  1321. X  
  1322. X  buf.af_gen = AF_BUSYVERS;
  1323. X  buf.af_rev = AF_BUSYVERS;
  1324. X
  1325. X  if(sysp[0] != '\0')
  1326. X    (void) strcpy(buf.af_syspath,sysp);
  1327. X  else
  1328. X    (void) strcpy(buf.af_syspath,curvpath[0]);
  1329. X
  1330. X  (void) strcpy(buf.af_name,bname);
  1331. X  if (p != NIL)
  1332. X    (void) strcpy(buf.af_type,p);
  1333. X  else
  1334. X    (void) strcpy(buf.af_type,"");
  1335. X
  1336. X  if (forceflg)
  1337. X    {
  1338. X      if (is_in_forcelist(name,type))
  1339. X    return(3);
  1340. X    }
  1341. X
  1342. X  if ((retcode1 = af_find(&buf, &aset)) == -1)
  1343. X    errexit(10,"af_find");
  1344. X
  1345. X  buf.af_gen = AF_NOVNUM;
  1346. X  buf.af_rev = AF_NOVNUM;
  1347. X
  1348. X  buf.af_udattrs[0] = attr;
  1349. X  buf.af_udattrs[1] = NIL;
  1350. X
  1351. X  if ((retcode = af_bpfind(&buf,&bset)) == -1) 
  1352. X    errexit(10,"af_bpfind");
  1353. X
  1354. X  if ((retcode1 == 1) && (retcode == 0))
  1355. X    /* derived object is not in binary pool (attr had been too long */
  1356. X    {
  1357. X      if((retcode = af_find(&buf, &bset)) == -1)
  1358. X    {
  1359. X      errexit(10,"af_find");
  1360. X    }
  1361. X      else
  1362. X    {
  1363. X      if (af_dropset(&bset) == -1)
  1364. X        errexit(10,"af_dropset");
  1365. X      if (af_dropset(&aset) == -1)
  1366. X        errexit(10,"af_dropset");
  1367. X      
  1368. X      if (retcode == 1)
  1369. X        /* busy version owns the correct attribute */
  1370. X        return (0);
  1371. X      else
  1372. X        return(3);
  1373. X    }
  1374. X    }
  1375. X  
  1376. X  if ((retcode1 == 1) && (retcode == 1))
  1377. X    {
  1378. X      if(af_setgkey(&aset,0,&key1) == -1)
  1379. X    errexit(10,"af_setgkey");
  1380. X      if(af_setgkey(&bset,0,&key2) == -1)
  1381. X    errexit(10,"af_setgkey");
  1382. X      if(af_gattrs(&key1,&buf1) == -1)
  1383. X     errexit(10,"af_gattrs");
  1384. X      if(af_gattrs(&key2,&buf2) == -1)
  1385. X     errexit(10,"af_gattrs");
  1386. X      if(buf1.af_mtime == buf2.af_mtime)
  1387. X    {
  1388. X      if (af_dropset(&bset) == -1)
  1389. X        errexit(10,"af_dropset");
  1390. X      if (af_dropset(&aset) == -1)
  1391. X        errexit(10,"af_dropset");
  1392. X      return (0);
  1393. X    }
  1394. X    }
  1395. X  if (retcode == 0)
  1396. X    {
  1397. X      if (af_dropset(&bset) == -1)
  1398. X    errexit(10,"af_dropset");
  1399. X      if (af_dropset(&aset) == -1)
  1400. X      errexit(10,"af_dropset");
  1401. X      return (3);
  1402. X    }
  1403. X  else
  1404. X    {
  1405. X      if (af_setgkey(&bset,0,&bkey) == -1)
  1406. X    errexit(10,"af_setgkey");
  1407. X      if (retcode1 == 1)
  1408. X    {
  1409. X      if (af_setgkey(&aset,0,&akey) == -1)
  1410. X        errexit(10,"af_setgkey");
  1411. X      if (af_dropkey(&akey) == -1)
  1412. X        errexit(10,"af_dropkey");
  1413. X    } 
  1414. X      if (af_restore(&bkey,&restorekey) == -1)
  1415. X    errexit(10,"af_restore");
  1416. X
  1417. X      if (af_sudattr(&restorekey,AF_REPLACE,attr) == -1)
  1418. X    errexit(10,"af_sudattr");
  1419. X
  1420. X      if (af_gattrs(&bkey,&buf) == -1)
  1421. X    errexit(10,"af_gattrs");
  1422. X
  1423. X      if (af_dropkey(&bkey) == -1)
  1424. X    errexit(10,"af_dropkey");
  1425. X
  1426. X      if (buf.af_gen != AF_BUSYVERS)
  1427. X    {
  1428. X      printf ("... %s.%s[%d.%d] restored from bpool\n",
  1429. X          buf.af_name, buf.af_type, buf.af_gen, buf.af_rev);
  1430. X    }
  1431. X      else
  1432. X    {
  1433. X      if (strcmp(buf.af_type,""))
  1434. X        printf ("... %s.%s restored from bpool\n",
  1435. X            buf.af_name, buf.af_type);
  1436. X      else
  1437. X        printf ("... %s restored from bpool\n",
  1438. X            buf.af_name);
  1439. X    }
  1440. X      if (af_dropset(&bset) == -1)
  1441. X    errexit(10,"af_dropset");
  1442. X      if (af_dropset(&aset) == -1)
  1443. X    errexit(10,"af_dropset");
  1444. X      return(0);
  1445. X    }
  1446. X}
  1447. X
  1448. X
  1449. Xint append_attrs(buf,recdepth)
  1450. X     Af_attrs *buf;
  1451. X     int recdepth;
  1452. X{
  1453. X  char attributes[MAX_ATTR];
  1454. X
  1455. X  (void) sprintf(attributes,"%s%s%s%s%s%d%d%d%d",
  1456. X      buf->af_name,
  1457. X      ".",
  1458. X      buf->af_type,
  1459. X      buf->af_host,
  1460. X      buf->af_syspath,
  1461. X      buf->af_gen,
  1462. X      buf->af_rev,
  1463. X      buf->af_state,
  1464. X      buf->af_mtime /* ,
  1465. X      buf->af_owner.af_username,
  1466. X      buf->af_owner.af_userhost,
  1467. X      buf->af_author.af_username,
  1468. X      buf->af_author.af_userhost,
  1469. X      buf->af_locker.af_username,
  1470. X      buf->af_locker.af_userhost,
  1471. X       buf->af_size,
  1472. X      buf->af_mode,
  1473. X      buf->af_atime,
  1474. X      buf->af_ctime,
  1475. X       buf->af_stime,
  1476. X      buf->af_ltime */
  1477. X      );
  1478. X
  1479. X/*  i = 0;
  1480. X  while(buf->af_udattrs[i] != NIL)
  1481. X    {
  1482. X      if ((strlen(attributes) + strlen(buf->af_udattrs[i])) >= MAX_ATTR)
  1483. X    errexit(29,NIL);
  1484. X      (void) strcat(attributes,buf->af_udattrs[i]);
  1485. X      i++;
  1486. X    }
  1487. X*/
  1488. X  if ((strlen(attributes) + strlen(longattrs[recdepth])) >= MAX_ATTR)
  1489. X    errexit(29,NIL);
  1490. X
  1491. X  (void) strcat(longattrs[recdepth],attributes);
  1492. X
  1493. X#ifdef DEBUG_MISC
  1494. Xprintf("depth=%d;longattr=%s\n", recdepth, longattrs[recdepth]);
  1495. X#endif DEBUG_MISC
  1496. X
  1497. X}
  1498. X
  1499. Xappend_mtime(testbuf,recdepth)
  1500. X     Af_attrs *testbuf;
  1501. X     /*ARGSUSED*/
  1502. X     int recdepth;
  1503. X{
  1504. X  char time[64];
  1505. X  /* (void) sprintf(time,"%d",testbuf->af_mtime);
  1506. X  (void) strcat(longattrs[recdepth],time); */
  1507. X}
  1508. X
  1509. X
  1510. XBool is_in_forcelist(name,type)
  1511. X     char *name;
  1512. X     char *type;
  1513. X{
  1514. X  char fullname[MAXNAMLEN];
  1515. X  int i = 0;
  1516. X  fullname[0] = '\0';
  1517. X  (void) strcpy(fullname,name);
  1518. X  if (strcmp(type,""))
  1519. X    {
  1520. X      (void) strcat(fullname,".");
  1521. X      (void) strcat(fullname,type);
  1522. X    }
  1523. X
  1524. X  while(forcelist[i] != NIL)
  1525. X    {
  1526. X      if (!strcmp(forcelist[i],fullname))
  1527. X    return(TRUE);
  1528. X      i++;
  1529. X    }
  1530. X  return(FALSE);
  1531. X}
  1532. X
  1533. X  
  1534. END_OF_FILE
  1535. if test 13128 -ne `wc -c <'src/shape/misc.c'`; then
  1536.     echo shar: \"'src/shape/misc.c'\" unpacked with wrong size!
  1537. fi
  1538. # end of 'src/shape/misc.c'
  1539. fi
  1540. if test -f 'src/vc/retrv.c' -a "${1}" != "-c" ; then 
  1541.   echo shar: Will not clobber existing file \"'src/vc/retrv.c'\"
  1542. else
  1543. echo shar: Extracting \"'src/vc/retrv.c'\" \(13192 characters\)
  1544. sed "s/^X//" >'src/vc/retrv.c' <<'END_OF_FILE'
  1545. X/*
  1546. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  1547. X *  and U. Pralle
  1548. X * 
  1549. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  1550. X * WARRANTY for any part of this software to work correctly or as described
  1551. X * in the manuals. We do not accept any liability for any kind of damage
  1552. X * caused by use of this software, such as loss of data, time, money, or 
  1553. X * effort.
  1554. X * 
  1555. X * Permission is granted to use, copy, modify, or distribute any part of
  1556. X * this software as long as this is done without asking for charge, and
  1557. X * provided that this copyright notice is retained as part of the source
  1558. X * files. You may charge a distribution fee for the physical act of
  1559. X * transferring a copy, and you may at your option offer warranty
  1560. X * protection in exchange for a fee.
  1561. X * 
  1562. X * Direct questions to: Tech. Univ. Berlin
  1563. X *              Wilfried Koch
  1564. X *              Sekr. FR 5-6 
  1565. X *              Franklinstr. 28/29
  1566. X *              D-1000 Berlin 10, West Germany
  1567. X * 
  1568. X *              Tel: +49-30-314-22972
  1569. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  1570. X */
  1571. X#ifndef lint
  1572. Xstatic char *AFSid = "$Header: retrv.c[3.7] Thu Feb 23 18:13:45 1989 axel@coma published $";
  1573. X#ifdef CFFLGS
  1574. Xstatic char *ConfFlg = CFFLGS;
  1575. X    /* should be defined from within Makefile */
  1576. X#endif
  1577. X#endif
  1578. X/*
  1579. X * Log for /u/shape/dist-tape/src/vc/retrv.c[3.2]
  1580. X *     Thu Feb 23 18:13:46 1989 axel@coma save $
  1581. X *  --- empty log message ---
  1582. X *  retrv.c[3.3] Thu Feb 23 18:13:46 1989 axel@coma save $
  1583. X *  --- empty log message ---
  1584. X *  retrv.c[3.4] Thu Feb 23 18:13:46 1989 axel@coma published $
  1585. X *  --- empty log message ---
  1586. X *  retrv.c[3.5] Thu Feb 23 18:13:46 1989 axel@coma published $
  1587. X *  --- empty log message ---
  1588. X *  retrv.c[3.6] Thu Feb 23 18:13:46 1989 axel@coma save $
  1589. X *  --- empty log message ---
  1590. X *  retrv.c[3.7] Thu Feb 23 18:13:46 1989 axel@coma published $
  1591. X *  --- empty log message ---
  1592. X */
  1593. X
  1594. X/*
  1595. X *  retrv [-fmqtx] [-V version] [-a attrs] [-d date] [-g generation]  
  1596. X *          [-n author] [-p pname] [-s state] [-lock] [-dest path] fn [fn1 ...]
  1597. X *
  1598. X *  Retrieve a previously saved version of a file. We orient us pretty much
  1599. X *  towards the check-out operation of RCS. Retrieve determines the
  1600. X *  archive name to be searched from the given file names. Unless otherwise
  1601. X *  specified by the project context (-p), the archive is expected to
  1602. X *  reside in the AFS subdirectory. The retrieved version will be created
  1603. X *  in the current directory. Retrieve tries to be careful if an
  1604. X *  attempt is made to overwrite an existing busy-version: unless -f
  1605. X *  is specified, retrv will ask the caller for permission.
  1606. X *  If no busy version exists, one is created with the modes of the
  1607. X *  formerly saved version. If one exists, it's modes are kept unless
  1608. X *  -m is given.
  1609. X *  There's a number of ways to specify which version should be retrieved.
  1610. X *  With -V an explicit version can be selected. Another argument to -V
  1611. X *  could be a symbolic name (hopefully unique). Alternatively, versions
  1612. X *  can be selected by supplying certain attribute values to retrv, such as
  1613. X *  the name of the author, the version state, a generation number or a 
  1614. X *  set of user defined attributes, possibly describing a variant. In case
  1615. X *  that more than one version fits the desired attributes, the newest
  1616. X *  of them is selected, unless -x (exact!) is specified. -V implies -x.
  1617. X */
  1618. X
  1619. X#include <sys/types.h>
  1620. X#include <sys/stat.h>
  1621. X#include <stdio.h>
  1622. X#include <strings.h>
  1623. X#include "ParseArgs.h"
  1624. X#include "afs.h"
  1625. X#include "retrv.h"
  1626. X#include "project.h"
  1627. X
  1628. Xchar *progname;
  1629. X
  1630. Xstruct Transaction ThisTransaction;
  1631. X
  1632. X/* forward decls for option handlers */
  1633. Xextern handle_R_switch ();
  1634. Xextern handle_f_switch ();
  1635. Xextern handle_l_switch ();
  1636. Xextern handle_m_switch ();
  1637. Xextern handle_q_switch ();
  1638. Xextern handle_t_switch ();
  1639. Xextern handle_x_switch ();
  1640. Xextern handle_V_opt ();
  1641. Xextern handle_a_opt ();
  1642. Xextern handle_d_opt ();
  1643. Xextern handle_dest_opt ();
  1644. Xextern handle_g_opt ();
  1645. Xextern handle_n_opt ();
  1646. Xextern handle_p_opt ();
  1647. Xextern handle_s_opt ();
  1648. Xextern usage ();
  1649. X
  1650. Xunsigned int options;
  1651. X
  1652. Xstatic OptDesc retrvargs[] = {
  1653. X  { "version", OPT_IS_SWITCH, handle_R_switch },
  1654. X  { "f", OPT_IS_SWITCH, handle_f_switch },
  1655. X  { "l", OPT_IS_SWITCH, handle_l_switch },
  1656. X  { "lock", OPT_IS_SWITCH, handle_l_switch },
  1657. X  { "m", OPT_IS_SWITCH, handle_m_switch },
  1658. X  { "q", OPT_IS_SWITCH, handle_q_switch },
  1659. X  { "t", OPT_IS_SWITCH, handle_t_switch },
  1660. X  { "x", OPT_IS_SWITCH, handle_x_switch },
  1661. X  { "V", OPT_HAS_ARG, handle_V_opt }, 
  1662. X  { "a", OPT_HAS_ARG, handle_a_opt }, 
  1663. X  { "d", OPT_HAS_ARG, handle_d_opt }, 
  1664. X  { "date", OPT_HAS_ARG, handle_d_opt }, 
  1665. X  { "dest", OPT_HAS_ARG, handle_dest_opt },
  1666. X  { "g", OPT_HAS_ARG, handle_g_opt }, 
  1667. X  { "n", OPT_HAS_ARG, handle_n_opt }, 
  1668. X  { "p", OPT_HAS_ARG, handle_p_opt }, 
  1669. X  { "s", OPT_HAS_ARG, handle_s_opt }, 
  1670. X  { "h", OPT_IS_SWITCH, usage },
  1671. X/*  { "?", OPT_HAS_ARG, usage }, */
  1672. X  { (char *)  NULL, NULL, NULL }
  1673. X};
  1674. Xstatic OptDesc vcatargs[] = {
  1675. X  { "version", OPT_IS_SWITCH, handle_R_switch },
  1676. X  { "q", OPT_IS_SWITCH, handle_q_switch },
  1677. X  { "t", OPT_IS_SWITCH, handle_t_switch },
  1678. X  { "x", OPT_IS_SWITCH, handle_x_switch },
  1679. X  { "V", OPT_HAS_ARG, handle_V_opt }, 
  1680. X  { "a", OPT_HAS_ARG, handle_a_opt }, 
  1681. X  { "d", OPT_HAS_ARG, handle_d_opt }, 
  1682. X  { "date", OPT_HAS_ARG, handle_d_opt }, 
  1683. X  { "g", OPT_HAS_ARG, handle_g_opt }, 
  1684. X  { "n", OPT_HAS_ARG, handle_n_opt }, 
  1685. X  { "p", OPT_HAS_ARG, handle_p_opt }, 
  1686. X  { "s", OPT_HAS_ARG, handle_s_opt }, 
  1687. X  { "h", OPT_IS_SWITCH, usage },
  1688. X/*  { "?", OPT_HAS_ARG, usage }, */
  1689. X  { (char *)  NULL, NULL, NULL }
  1690. X};
  1691. X
  1692. Xstatic int nfnms;
  1693. X
  1694. Xstatic struct Vdesc dversion;
  1695. X
  1696. Xchar *dp = NULL; /* nasty sideeffect here - see 'handle_dest_opt' */
  1697. X
  1698. Xmain (ac, av) char **av; {
  1699. X  register int i;
  1700. X  int nac, bound_vid = 0, rc = 0;
  1701. X  unsigned int options_bak = 0;
  1702. X  char messg[80], *es, *getenv(), **nav, *version(), vstring[16], *cp;
  1703. X  Project pdesc;
  1704. X  struct Vdesc *vdescr = &dversion, alt_dversion;
  1705. X
  1706. X  progname = (cp = rindex (av[0], '/')) ? ++cp : av[0];
  1707. X  /* make prog-name available to entire program */
  1708. X
  1709. X  if (ac < 2) {
  1710. X    pa_ShortUsage (progname, vcatargs, "files ...");
  1711. X  }
  1712. X
  1713. X  if (!strcmp (progname, TONAME)) {
  1714. X    options |= TYPEOUT;
  1715. X    if (ParseArgs (ac, av, &nac, &nav, vcatargs)) {
  1716. X      pa_ShortUsage (progname, vcatargs, "files...");
  1717. X    }
  1718. X  }
  1719. X  else {
  1720. X    if (ParseArgs (ac, av, &nac, &nav, retrvargs)) {
  1721. X      pa_ShortUsage (progname, retrvargs, "files...");
  1722. X    }
  1723. X  }
  1724. X
  1725. X  if (!(options & (TYPEOUT | COPY | LOCKIT))) options |= COPY;
  1726. X    
  1727. X  if (!(options & ATTRDEF)) {
  1728. X    es = getenv (RTRATTR);
  1729. X    if ((es) && (es[0] != '\0')) {
  1730. X      options |= ATTRDEF;
  1731. X      (void)strcpy (dversion.v_attrf, es);
  1732. X    }
  1733. X  }
  1734. X
  1735. X  if ((options & PROJCSET) && fail(GetProject (dversion.v_pname, &pdesc))) {
  1736. X    (void)sprintf (messg, "%s %s", EINVALPROJ, dversion.v_pname);
  1737. X    logerr (messg);
  1738. X    exit (1);
  1739. X  }
  1740. X
  1741. X  CatchSigs ();
  1742. X  nfnms = nac;
  1743. X  ThisTransaction.tr_rc = 0;
  1744. X  for (i = 0, vdescr = &dversion; i < nfnms; i++) {
  1745. X    if (!setjmp (ThisTransaction.tr_env)) {
  1746. X      if (bound_vid) {
  1747. X    bound_vid = FALSE;
  1748. X    options = options_bak; /* restore original selection options */
  1749. X    vdescr = &dversion;
  1750. X      }
  1751. X      ThisTransaction.tr_seqno = i;
  1752. X      if (BoundVersion (nav[i], ThisTransaction.tr_fname, vstring)) {
  1753. X    alt_dversion.v_vno = mkvno (vstring);
  1754. X    options_bak = options; /* save original selection options */
  1755. X    options |= (VSPECSET | XACT);
  1756. X    options &= ~(ATTRDEF | GENSET | AUNSET | STATSET | DATESET);
  1757. X    vdescr = &alt_dversion;
  1758. X    bound_vid = TRUE;
  1759. X      }
  1760. X      else {
  1761. X    (void)strcpy (ThisTransaction.tr_fname, nav[i]);
  1762. X      }
  1763. X      ThisTransaction.tr_done = FALSE;
  1764. X      RetrieveAFile (ThisTransaction.tr_fname, vdescr, &pdesc, dp);
  1765. X    }
  1766. X    else { /* ThisTransaction was aborted */
  1767. X      rc += ThisTransaction.tr_rc;
  1768. X    }
  1769. X  }
  1770. X  logdiag ("done.");
  1771. X  return (rc);
  1772. X}
  1773. X
  1774. XSfunc_t interrupt_action () { /* is executed by appropriate signal handler */
  1775. X  char messg[80];
  1776. X
  1777. X  if ((nfnms - ThisTransaction.tr_seqno) > 1) { 
  1778. X    (void)sprintf (messg, "\ncompletely stop retrieving (%d files pending) ?", 
  1779. X         nfnms - ThisTransaction.tr_seqno);
  1780. X    if (ask_confirm (messg, "no")) {
  1781. X      if (ThisTransaction.tr_done) {
  1782. X    (void)sprintf (messg, "\ntoo late, %s already restored", 
  1783. X         ThisTransaction.tr_fname);
  1784. X    logdiag (messg);
  1785. X    return; /* continue where we've been interrupted */
  1786. X      }
  1787. X      (void)sprintf (messg, NORESTORE, ThisTransaction.tr_fname);
  1788. X      logdiag (messg);
  1789. X      longjmp (ThisTransaction.tr_env, 1);
  1790. X    }
  1791. X    else {
  1792. X      (void)sprintf (messg, NORESTORE, ThisTransaction.tr_fname);
  1793. X      logmsg (messg);
  1794. X      exit (1);
  1795. X    }
  1796. X  }
  1797. X  else {
  1798. X    (void)sprintf (messg, "\n%s not restored", ThisTransaction.tr_fname);
  1799. X    logdiag (messg);
  1800. X    exit (1);
  1801. X  }
  1802. X}
  1803. X
  1804. Xlogmsg (msg) char *msg; {
  1805. X  if (!(options & QUIETPLEASE)) {
  1806. X    fprintf (stdout, "%s\n", msg);
  1807. X  }
  1808. X}
  1809. X
  1810. Xlogdiag (msg) char *msg; {
  1811. X  if (!(options & QUIETPLEASE)) {
  1812. X    fprintf (stderr, "%s\n", msg);
  1813. X  }
  1814. X}
  1815. X
  1816. Xlogerr (msg) char *msg; {
  1817. X  fprintf (stderr, "%s: %s\n", progname, msg);
  1818. X}
  1819. X
  1820. X/*ARGSUSED*/
  1821. Xhandle_R_switch (o, a) char *o, *a; {
  1822. X  printf ("This is %s version %s.\n", progname, version ());
  1823. X  printf ("AFS version %s.\n", af_version());
  1824. X  exit (0);
  1825. X}
  1826. X
  1827. X/*ARGSUSED*/
  1828. Xhandle_f_switch (o, a) char *o, *a; {
  1829. X  options |= FORCE;
  1830. X  return 0;
  1831. X}
  1832. X
  1833. X/*ARGSUSED*/
  1834. Xhandle_l_switch (o, a) char *o, *a; {
  1835. X  char messg[128];
  1836. X
  1837. X  if (options & TYPEOUT) {
  1838. X    logerr ("Locking makes no sense in TYPEOUT mode of operation - ignored.");
  1839. X    return 0;
  1840. X  }
  1841. X  if (options & COPY) {
  1842. X    (void)sprintf (messg, "No checkout (with lock) to distant directory %s.", dp);
  1843. X    logerr (messg);
  1844. X    exit (1);
  1845. X  }
  1846. X  options |= LOCKIT;
  1847. X  return 0;
  1848. X}
  1849. X
  1850. X/*ARGSUSED*/
  1851. Xhandle_m_switch (o, a) char *o, *a; {
  1852. X  options |= KEEPMODE;
  1853. X  return 0;
  1854. X}
  1855. X
  1856. X/*ARGSUSED*/
  1857. Xhandle_q_switch (o, a) char *o, *a; {
  1858. X  options |= QUIETPLEASE;
  1859. X  return 0;
  1860. X}
  1861. X
  1862. X/*ARGSUSED*/
  1863. Xhandle_t_switch (o, a) char *o, *a; {
  1864. X  if (options & LOCKIT) {
  1865. X    logerr ("Locking makes no sense in TYPEOUT mode of operation - ignored.");
  1866. X    options &= ~LOCKIT;
  1867. X  }
  1868. X  if (options & COPY) {
  1869. X    logerr ("TYPEOUT mode of operation overrides COPY mode.");
  1870. X    options &= ~COPY;
  1871. X    dp = NULL;
  1872. X  }
  1873. X  options |= TYPEOUT;
  1874. X  return 0;
  1875. X}
  1876. X
  1877. X/*ARGSUSED*/
  1878. Xhandle_x_switch (o, a) char *o, *a; {
  1879. X  options |= XACT;
  1880. X  return 0;
  1881. X}
  1882. X
  1883. X/*ARGSUSED*/
  1884. Xhandle_V_opt (o, a) char *o, *a; {
  1885. X  dversion.v_vno = mkvno (a);
  1886. X  (void)strcpy (dversion.v_spec, a);
  1887. X  options |= VSPECSET;
  1888. X  options |= XACT;
  1889. X  return 0;
  1890. X}
  1891. X
  1892. X/*ARGSUSED*/
  1893. Xhandle_a_opt (o, a) char *o, *a; {
  1894. X  options |= ATTRDEF;
  1895. X  (void)strcpy (dversion.v_attrf, a);
  1896. X  return 0;
  1897. X}
  1898. X
  1899. X/*ARGSUSED*/
  1900. Xhandle_d_opt (o, a) char *o, *a; {
  1901. X  char messg[128];
  1902. X  time_t mktime();
  1903. X
  1904. X  if ((options & STATSET) && (dversion.v_state == AF_BUSY)) {
  1905. X    logmsg (WDOVRBS);
  1906. X    options &= ~STATSET;
  1907. X  }
  1908. X  if (dversion.v_time = mktime (a)) {
  1909. X    options |= DATESET;
  1910. X    return 0;
  1911. X  }
  1912. X  else {
  1913. X    (void)sprintf (messg, "invalid date specification: %s.", a);
  1914. X    logerr (messg);
  1915. X    tusage ();
  1916. X    return 1;
  1917. X  }
  1918. X}
  1919. X
  1920. X/*ARGSUSED*/
  1921. Xhandle_dest_opt (o, a) char *o, *a; {
  1922. X  char messg[128];
  1923. X  static char dpath[256];
  1924. X  struct stat statbuf;
  1925. X
  1926. X  if (!a) return 1;
  1927. X  if (options & LOCKIT) {
  1928. X    (void)sprintf (messg, "No checkout (with lock) to distant directory %s.", a);
  1929. X    logerr (messg);
  1930. X    exit (1);
  1931. X  }
  1932. X  if (options & TYPEOUT) {
  1933. X    logerr ("Already TYPEOUT mode of operation selected.");
  1934. X    return 0;
  1935. X  }
  1936. X  if (options & COPY) {
  1937. X    (void)sprintf (messg, "Destination path already set to %s. %s ignored.", dpath,
  1938. X         a);
  1939. X    logerr (messg);
  1940. X    return 0;
  1941. X  }
  1942. X  options |= COPY;
  1943. X  (void)strcpy (dpath, a);
  1944. X  if (stat (dpath, &statbuf) < 0) {
  1945. X    (void)sprintf (messg, "Destination path %s does not exist.", dpath);
  1946. X    logerr (messg);
  1947. X    exit (1);
  1948. X  }
  1949. X  if (!(statbuf.st_mode & S_IFDIR)) {
  1950. X    (void)sprintf (messg, "Destination %s is not a directory.", dpath);
  1951. X    logerr (messg);
  1952. X    exit (1);
  1953. X  }    
  1954. X  dp = dpath;
  1955. X  return 0;
  1956. X}
  1957. X  
  1958. X/*ARGSUSED*/
  1959. Xhandle_g_opt (o, a) char *o, *a; {
  1960. X  char messg[128];
  1961. X
  1962. X  if (dversion.v_genno = mkgenno (a)) {
  1963. X    options |= GENSET;
  1964. X    return 0;
  1965. X  }
  1966. X  else {
  1967. X    (void)sprintf (messg, "'%s' is not a legal generation number.", a);
  1968. X    logerr (messg);
  1969. X    return 1;
  1970. X  }
  1971. X}
  1972. X
  1973. X/*ARGSUSED*/
  1974. Xhandle_n_opt (o, a) char *o, *a; {
  1975. X  char *cp;
  1976. X
  1977. X  options |= AUNSET;
  1978. X  if (cp=index (a, '@')) {
  1979. X    *cp = '\0';
  1980. X    (void)strcpy (dversion.v_auhost, ++cp);
  1981. X  }
  1982. X  (void)strcpy (dversion.v_aunam, a);
  1983. X  return 0;
  1984. X}
  1985. X
  1986. X/*ARGSUSED*/
  1987. Xhandle_p_opt (o, a) char *o, *a; {
  1988. X  options |= PROJCSET;
  1989. X  (void)strcpy (dversion.v_pname, a);
  1990. X  return 0;
  1991. X}
  1992. X
  1993. X/*ARGSUSED*/
  1994. Xhandle_s_opt (o, a) char *o, *a; {
  1995. X  char messg[128];
  1996. X
  1997. X  if (!fail((dversion.v_state = mkstate (a)))) {
  1998. X    if ((options & DATESET) && (dversion.v_state == AF_BUSY)) {
  1999. X      logmsg (WDOVRBS);
  2000. X    }
  2001. X    else {
  2002. X      options |= STATSET;
  2003. X    }
  2004. X  }
  2005. X  else {
  2006. X    (void)sprintf (messg, "unrecognized version state: %s.\n", a);
  2007. X    logerr (messg);
  2008. X    helpstates ();
  2009. X    exit (1);
  2010. X  }
  2011. X  return 0;
  2012. X}
  2013. X
  2014. Xtusage () {
  2015. X  fputs ("specify time as yy/mm/dd[/hh:mm].\n", stderr);
  2016. X}
  2017. X
  2018. Xhelpstates () {
  2019. X  fputs ("The following states are recognized:\n", stderr);
  2020. X  fputs ("\tbusy, save, proposed, published, accessed, frozen\n", stderr);
  2021. X}
  2022. X
  2023. Xusage () {
  2024. X  if (strcmp (progname, "vcat"))
  2025. X    pa_ShortUsage (progname, retrvargs, "files ...");
  2026. X  else 
  2027. X    pa_ShortUsage (progname, vcatargs, "files ...");
  2028. X}
  2029. END_OF_FILE
  2030. if test 13192 -ne `wc -c <'src/vc/retrv.c'`; then
  2031.     echo shar: \"'src/vc/retrv.c'\" unpacked with wrong size!
  2032. fi
  2033. # end of 'src/vc/retrv.c'
  2034. fi
  2035. echo shar: End of archive 15 \(of 33\).
  2036. cp /dev/null ark15isdone
  2037. MISSING=""
  2038. 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
  2039.     if test ! -f ark${I}isdone ; then
  2040.     MISSING="${MISSING} ${I}"
  2041.     fi
  2042. done
  2043. if test "${MISSING}" = "" ; then
  2044.     echo You have unpacked all 33 archives.
  2045.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2046. else
  2047.     echo You still need to unpack the following archives:
  2048.     echo "        " ${MISSING}
  2049. fi
  2050. ##  End of shell archive.
  2051. exit 0
  2052.