rsalz@uunet.uu.net (Rich Salz) (06/05/89)
Submitted-by: Axel Mahler <unido!coma!axel> Posting-number: Volume 19, Issue 28 Archive-name: shape/part15 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 15 (of 33)." # Contents: src/afs/afvers.c src/misc/ParseArgs.c src/shape/misc.c # src/vc/retrv.c # Wrapped by rsalz@papaya.bbn.com on Thu Jun 1 19:27:05 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/afs/afvers.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/afs/afvers.c'\" else echo shar: Extracting \"'src/afs/afvers.c'\" \(13536 characters\) sed "s/^X//" >'src/afs/afvers.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ X/*LINTLIBRARY*/ X/* X * Shape/AFS X * X * afversions.c - operations on revisions X * X * Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP X * andy@db0tui62.BITNET) X * X * $Header: afvers.c[1.3] Wed Feb 22 16:28:25 1989 andy@coma published $ X * X * EXPORT: X * af_savebinary -- save derived file X * af_saverev -- save busy version X * af_newgen -- increase gen number and reset rev number X * af_setbusy -- set revision busy X * af_svnum -- set version number X */ X X#include <stdio.h> X#include <string.h> X#ifdef SUNOS_4_0 X#include <strings.h> X#endif X#include <sys/types.h> X#include <sys/stat.h> X X#include "typeconv.h" X#include "afsys.h" X#include "afs.h" X X/*==================================================================== X * af_savebinary X * X *====================================================================*/ X XEXPORT af_savebinary (busykey, savekey) X Af_key *busykey; X Af_key *savekey; /* out */ X{ X int oldpredgen, oldpredrev; X short oldnlinks; X time_t oldatime; X X if (af_keytest (busykey)) X SFAIL ("savebinary", "", AF_EINVKEY, ERROR); X X if (VATTR(busykey).af_state != AF_BUSY) X SFAIL ("savebinary", "", AF_ENOTBUSY, ERROR); X X if ((VATTR(busykey).af_mode & S_IFMT) != S_IFREG) X SFAIL ("savebinary", "", AF_ENOTREGULAR, ERROR); X X if (VATTR(busykey).af_nlinks > 1) X af_wng ("savebinary", "busykey has more than one reference"); X X if (af_checkperm (busykey, AF_WORLD) == ERROR) X return (ERROR); X X /* this then part is a little bit "hacked", it should better look like: X * X * get key for new bp entry X * modify attributes X * add new file to binary pool X */ X X /* modify some attributes for saving */ X VATTR(busykey).af_state = AF_NOSTATE; X VATTR(busykey).af_class |= AF_DERIVED; X oldatime = VATTR(busykey).af_atime; X VATTR(busykey).af_atime = (time_t) af_acttime (); X oldpredgen = VATTR(busykey).af_predgen; X VATTR(busykey).af_predgen = AF_NOVNUM; X oldpredrev = VATTR(busykey).af_predrev; X VATTR(busykey).af_predrev = AF_NOVNUM; X oldnlinks = VATTR(busykey).af_nlinks; X VATTR(busykey).af_nlinks = 1; X X if (af_rplbpentry ((Af_key *)0, busykey, savekey) == ERROR) X return (ERROR); X X /* restore attributes */ X VATTR(busykey).af_state = AF_BUSY; X VATTR(busykey).af_class &= ~AF_DERIVED; X VATTR(busykey).af_atime = oldatime; X VATTR(busykey).af_predgen = oldpredgen; X VATTR(busykey).af_predrev = oldpredrev; X VATTR(busykey).af_nlinks = oldnlinks; X X /* update binary pool descriptor */ X savekey->af_ldes->af_refcount++; X X return (AF_OK); X} X X X/*==================================================================== X * af_saverev X * X *====================================================================*/ X XEXPORT af_saverev (busykey, savekey) X X Af_key *busykey; X Af_key *savekey; /* out */ X{ X Af_key *lastkey, predkey, *af_glastkey(); X Af_user *author; X struct stat ibuf; X int af_fhash(); X X if (af_keytest (busykey)) X SFAIL ("saverev", "", AF_EINVKEY, ERROR); X X if (VATTR(busykey).af_state != AF_BUSY) X SFAIL ("saverev", "", AF_ENOTBUSY, ERROR); X X if ((VATTR(busykey).af_mode & S_IFMT) != S_IFREG) X SFAIL ("saverev", "", AF_ENOTREGULAR, ERROR); X X if (af_checkperm (busykey, AF_LOCKHOLDER) == ERROR) X SFAIL ("saverev", "", AF_ENOTLOCKED, ERROR); X X /* get attribute buffer (pointed to by "savekey") for new version */ X if (af_newvers (busykey->af_ldes, savekey, AF_SOURCE) == ERROR) X return (ERROR); X X /* set key and attributes of new version */ X VATTR(savekey).af_name = VATTR(busykey).af_name; X VATTR(savekey).af_type = VATTR(busykey).af_type; X VATTR(savekey).af_lckname = VATTR(busykey).af_lckname; X VATTR(savekey).af_lckhost = VATTR(busykey).af_lckhost; X VATTR(savekey).af_ltime = (time_t) af_acttime (); X X /* if there is only one (the busy-) revision (..nrevs == 1) */ X /* then do initial save */ X if (busykey->af_ldes->af_nrevs == 1) X { X VATTR(savekey).af_gen = AF_INITGEN; X VATTR(savekey).af_rev = AF_INITREV; X VATTR(savekey).af_predgen = AF_NOVNUM; X VATTR(savekey).af_predrev = AF_NOVNUM; X VATTR(busykey).af_predgen = AF_INITGEN; X VATTR(busykey).af_predrev = AF_INITREV; X (void) af_nodelta (busykey, savekey); X } X else /* get some attributes from preceding revision */ X { X lastkey = af_glastkey (busykey->af_ldes); X VATTR(savekey).af_gen = VATTR(lastkey).af_gen; X VATTR(savekey).af_rev = VATTR(lastkey).af_rev+1; X VATTR(savekey).af_predgen = VATTR(busykey).af_predgen; X VATTR(savekey).af_predrev = VATTR(busykey).af_predrev; X VATTR(busykey).af_predgen = VATTR(savekey).af_gen; X VATTR(busykey).af_predrev = VATTR(savekey).af_rev; X if (af_buildkey (busykey->af_ldes, VATTR(savekey).af_predgen, VATTR(savekey).af_predrev, &predkey) == ERROR) X predkey.af_ldes = (Af_revlist *)0; X (void) af_dodelta (busykey, &predkey, savekey); X } X X if (VATTR(busykey).af_variant) X VATTR(savekey).af_variant = VATTR(busykey).af_variant; X else X VATTR(savekey).af_variant = (char *)0; X X VATTR(savekey).af_state = AF_SAVED; X VATTR(savekey).af_class = VATTR(busykey).af_class; X author = af_getuser (getuid()); X VATTR(savekey).af_auname = af_entersym (author->af_username); X VATTR(savekey).af_auhost = af_enterhost (author->af_userhost); X (void) lstat (busykey->af_ldes->af_busyfilename, &ibuf); X VATTR(savekey).af_mode = ibuf.st_mode; X VATTR(savekey).af_mtime = (time_t) af_cvttime (ibuf.st_mtime); X VATTR(savekey).af_atime = (time_t) af_acttime (); X VATTR(savekey).af_ctime = (time_t) af_cvttime (ibuf.st_mtime); X VATTR(savekey).af_stime = (time_t) af_acttime (); X VATTR(savekey).af_notesize = 1; X VATTR(savekey).af_note = (char *)0; X VATTR(savekey).af_nlinks = 1; X X VATTR(savekey).af_udanum = VATTR(busykey).af_udanum; X (void) af_hashinit (&(VATTR(savekey).af_uhtab), AF_MAXUDAS, af_fhash); X (void) af_hashcopy (&(VATTR(busykey).af_uhtab), &(VATTR(savekey).af_uhtab)); X X VATTR(savekey).af_hashname = (char *)0; X VATTR(savekey).af_succgen = AF_NOVNUM; X VATTR(savekey).af_succrev = AF_NOVNUM; X X /* update list descriptor */ X busykey->af_ldes->af_nrevs++; X busykey->af_ldes->af_datasize += VATTR(savekey).af_notesize; X busykey->af_ldes->af_refcount++; X X /* save changes */ X if (af_addvers (savekey) == ERROR) X return (ERROR); X X return (AF_OK); X} /* af_saverev */ X X X X/*==================================================================== X * af_newgen X * X *====================================================================*/ X XEXPORT af_newgen (key, newkey) X Af_key *key; X Af_key *newkey; /* out */ X{ X Af_key *lastkey, *busykey, *af_gbuskey(), *af_glastkey(); X int af_fhash(); X X if (af_keytest (key)) X SFAIL ("newgen", "", AF_EINVKEY, ERROR); X X if (key->af_ldes->af_nrevs == 1) X SFAIL ("newgen", "", AF_ENOTVERS, ERROR); X X if (VATTR(key).af_class & AF_DERIVED) X SFAIL ("newgen", "", AF_EDERIVED, ERROR); X X if ((VATTR(key).af_mode & S_IFMT) != S_IFREG) X SFAIL ("newgen", "", AF_ENOTREGULAR, ERROR); X X busykey = af_gbuskey (key->af_ldes); X if (af_checkperm (busykey, AF_LOCKHOLDER) == ERROR) X SFAIL ("newgen", "", AF_ENOTLOCKED, ERROR); X X if (af_newvers (key->af_ldes, newkey, AF_SOURCE) == ERROR) X return (ERROR); X X lastkey = af_glastkey (key->af_ldes); X X if ((VATTR(key).af_predgen == VATTR(lastkey).af_gen) && X (VATTR(key).af_predrev == VATTR(lastkey).af_rev)) X { X VATTR(key).af_predgen++; X VATTR(key).af_predrev = 0; X } X X /* duplicate last revision */ X X VATTR(newkey).af_gen = VATTR(lastkey).af_gen+1; X VATTR(newkey).af_rev = 0; X VATTR(newkey).af_variant = VATTR(lastkey).af_variant; X VATTR(newkey).af_predgen = VATTR(lastkey).af_gen; X VATTR(newkey).af_predrev = VATTR(lastkey).af_rev; X X (void) af_dodelta ((Af_key *)0, lastkey, newkey); X X VATTR(newkey).af_name = VATTR(lastkey).af_name; X VATTR(newkey).af_type = VATTR(lastkey).af_type; X VATTR(newkey).af_variant = VATTR(lastkey).af_variant; X VATTR(newkey).af_state = VATTR(lastkey).af_state; X VATTR(newkey).af_class = VATTR(lastkey).af_class; X VATTR(newkey).af_auname = VATTR(lastkey).af_auname; X VATTR(newkey).af_auhost = VATTR(lastkey).af_auhost; X VATTR(newkey).af_mode = VATTR(lastkey).af_mode; X VATTR(newkey).af_mtime = VATTR(lastkey).af_mtime; X VATTR(newkey).af_atime = VATTR(lastkey).af_atime; X VATTR(newkey).af_ctime = VATTR(lastkey).af_ctime; X VATTR(newkey).af_stime = VATTR(lastkey).af_stime; X VATTR(newkey).af_notesize = VATTR(lastkey).af_notesize; X VATTR(newkey).af_note = VATTR(lastkey).af_note; X VATTR(newkey).af_lckname = (char *)0; X VATTR(newkey).af_lckhost = (char *)0; X VATTR(newkey).af_nlinks = 1; X X VATTR(newkey).af_udanum = VATTR(lastkey).af_udanum; X (void) af_hashinit (&(VATTR(newkey).af_uhtab), AF_MAXUDAS, af_fhash); X (void) af_hashcopy (&(VATTR(lastkey).af_uhtab), &(VATTR(newkey).af_uhtab)); X X VATTR(newkey).af_succgen = AF_NOVNUM; X VATTR(newkey).af_succrev = AF_NOVNUM; X X /* update list descriptor */ X key->af_ldes->af_nrevs++; X key->af_ldes->af_datasize += VATTR(newkey).af_notesize; X X /* update predecessor of busy version */ X if ((VATTR(busykey).af_predgen == VATTR(lastkey).af_gen) && X (VATTR(busykey).af_predrev == VATTR(lastkey).af_rev)) X { X VATTR(busykey).af_predgen = VATTR(newkey).af_gen; X VATTR(busykey).af_predrev = VATTR(newkey).af_rev; X } X X if (af_addvers (newkey) == ERROR) X return (ERROR); X X key->af_ldes->af_refcount++; X return (AF_OK); X} X X X/*==================================================================== X * af_setbusy X * X *====================================================================*/ X XEXPORT af_setbusy (busykey, newkey) X Af_key *busykey, *newkey; X{ X Af_key *af_gbuskey(); X X if (af_keytest (newkey)) X SFAIL ("setbusy", "", AF_EINVKEY, ERROR); X X if (busykey != (Af_key *)0) X { X if (af_keytest (busykey)) X SFAIL ("setbusy", "", AF_EINVKEY, ERROR); X if (VATTR(busykey).af_state != AF_BUSY) X SFAIL ("setbusy", "", AF_ENOTBUSY, ERROR); X if (VATTR(busykey).af_class & AF_DERIVED) X SFAIL ("setbusy", "", AF_EDERIVED, ERROR); X } X else X { X busykey = af_gbuskey (newkey->af_ldes); X } X X if (af_checkperm (busykey, AF_LOCKHOLDER) == ERROR) X SFAIL ("setbusy", "", AF_ENOTLOCKED, ERROR); X X /* if the two versions belong to one line of development */ X if (busykey->af_ldes->af_busyfilename == newkey->af_ldes->af_busyfilename) X { X VATTR(busykey).af_predgen = VATTR(newkey).af_gen; X VATTR(busykey).af_predrev = VATTR(newkey).af_rev; X } X else X { X VATTR(busykey).af_predgen = AF_NOVNUM; X VATTR(busykey).af_predrev = AF_NOVNUM; X } X if (af_updtvers (busykey, AF_CHANGE) == ERROR) X return (ERROR); X X return (AF_OK); X} X X X/*==================================================================== X * af_svnum X * X *====================================================================*/ X XEXPORT af_svnum (key, gen, rev) X Af_key *key; X int gen, rev; X{ X Af_key predkey, *lastkey, *af_glastkey(); X X if (af_keytest (key)) X SFAIL ("svnum", "", AF_EINVKEY, ERROR); X X if ((VATTR(key).af_state == AF_BUSY) || (VATTR(key).af_state > AF_PROPOSED)) X SFAIL ("svnum", "", AF_EWRONGSTATE, ERROR); X X if (!(VATTR(key).af_class & AF_DERIVED)) /* derived files can get any vnum */ X { X if (af_checkperm (key, AF_LOCKHOLDER) == ERROR) X SFAIL ("svnum", "", AF_ENOTLOCKED, ERROR); X X /* only the version number of the last saved version can be modified */ X lastkey = af_glastkey (key->af_ldes); X if (af_keycmp (key, lastkey)) X SFAIL ("svnum", "can set version number only for last saved version", X AF_EMISC, ERROR); X X /* if new version number is smaller than the old one */ X if (gen < VATTR(key).af_gen) X SFAIL ("svnum", "", AF_EINVVNUM, ERROR); X if (gen == VATTR(key).af_gen) X { X if (rev < VATTR(key).af_rev) X SFAIL ("svnum", "", AF_EINVVNUM, ERROR); X } X /* read data file in order to get it updated */ X if (af_readdata (key->af_ldes) == ERROR) X return (ERROR); X } X X VATTR(key).af_gen = (short)gen; X VATTR(key).af_rev = (short)rev; X X /* if a predecessor exists, update its successor field */ X if (af_buildkey (key->af_ldes, VATTR(key).af_predgen, X VATTR(key).af_predrev, &predkey) == AF_OK) X { X VATTR((&predkey)).af_succgen = (short)gen; X VATTR((&predkey)).af_succrev = (short)rev; X } X X /* the predecessor is updated implicitely by af_updtvers (key) */ X if (af_updtvers (key, AF_CHANGE) == ERROR) X return (ERROR); X X return (AF_OK); X} X END_OF_FILE if test 13536 -ne `wc -c <'src/afs/afvers.c'`; then echo shar: \"'src/afs/afvers.c'\" unpacked with wrong size! fi # end of 'src/afs/afvers.c' fi if test -f 'src/misc/ParseArgs.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/misc/ParseArgs.c'\" else echo shar: Extracting \"'src/misc/ParseArgs.c'\" \(12926 characters\) sed "s/^X//" >'src/misc/ParseArgs.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ Xstatic char *AFSid = "$Header: ParseArgs.c[2.1] Thu Feb 23 21:24:12 1989 axel@coma published $"; X X/* X * Log for /u/shape/dist-tape/src/misc/ParseArgs.c[1.1] X * Thu Feb 23 21:24:12 1989 axel@coma save $ X * --- empty log message --- X * ParseArgs.c[2.0] Thu Feb 23 21:24:12 1989 axel@coma published $ X * --- empty log message --- X * ParseArgs.c[2.1] Thu Feb 23 21:24:12 1989 axel@coma published $ X * --- empty log message --- X */ X X#include <stdio.h> X#include <strings.h> X X#include "ParseArgs.h" X Xstatic char *RCSid = "$Header: ParseArgs.c,v 2.0 88/06/29 16:14:32 axel Stable $"; X#ifdef CFFLGS Xstatic char *Cflags = CFFLGS; X#endif CFFLGS X X/* X * $Log: ParseArgs.c,v $ X * Revision 2.0 88/06/29 16:14:32 axel X * New System Generation X * X * Revision 1.1 88/06/07 17:10:01 axel X * This version is part of a release X * X * Revision 1.8 88/03/12 20:34:34 uli X * *** empty log message *** X * X * Revision 1.7 88/03/10 14:06:47 uli X * ParseArgs returns now the number of error encountered during parse. X * A return value of 0 means no error. This is incompatible to the previous X * versions. Is this a so called "variant" ? Should i release the previous X * version ? X * Uli X * X * Revision 1.6 88/03/08 20:48:53 uli X * blabla. X * X * Revision 1.5 88/03/08 20:03:01 uli X * pa_ShortUsage added. If called, builds a usage. X * X * Revision 1.4 88/03/08 15:34:58 uli X * Order of options is no longer important. Options are rearrange in X * longest first order. X * X * Revision 1.3 88/03/04 15:36:23 uli X * Some bugs fixed. X * X * X * Revision 1.2 88/02/23 13:53:34 uli X * Error in ParseArguments fixed: newav is now (unsigned long*). X * X * Revision 1.1 88/02/23 12:42:27 uli X * Initial revision X * X * Revision 1.2 88/02/18 14:33:52 uli X * *** empty log message *** X * X */ X X/* X * Exports: X * X * Type: OptDesc; X * Function: ParseArgs (ac, av, newac, newav, optdesc) X * int ac; X * char **av; X * int newac; X * char **newav; X * OptDesc *optdesc; X * X * ParseArgs returns 1 on success, 0 on failure. X * X */ X X/* X * Description: X * X * ParseArgs scans and tokenizes the argument string in its components. X * Components are the name of the called program, the options, the X * arguments of options, and the pure arguments (i.e. non options). X * X * An Option is specified by its name, kind, and a function, that X * handles this option. Name is a (possible multi character) string. X * The kind specifies iff the option is an ordinary switch, X * an options with an optional argument, * or an option that X * requires an argument. The function is called whenever the options X * is detected in the argument string. The number of the function X * parameters depends on the options' kind. The detected option X * is passed everytime as the first parameter. If this option X * has a (possible optional) argument, it is passed to the handler as the X * second parameter. If the argument is missed in the argument string, X * then a string which contains only a null byte is passed to the handler. X * X * Example: X * X * OptDesc odesc[] = { X * { "l", OPT_IS_SWITCH, handle_i_option }, X * { "f", OPT_HAS_ARG, handle_f_options }, X * { "o", OPT_HAS_OPT_ARG, handle_o_option} X * } X * X * In this example we have declared 'l', 'f', and 'o' to be options. X * 'l' is a ordinary switch, 'f' requires an argument, and 'o' may X * have an argument. Handle_i_options, handle_f_option, and X * and handle_o_option are the option handlers called. The handler X * are declared: X * X * int handle_i_option (option) X * char *option; X * X * int handle_f_option (option, options_argument); X * char *option, *options_argument; X * X * int handle_o_option (option, options_argument); X * char *option, *options_argument; X * X * Everytime '-i' is detected, handle_i_option is called X * handle_i_option ("i"); X * handle_f_option is called X * handle_f_option ("f", argument); X * and handle_o_option is called X * handle_o_option ("o", argument); X * X * If the argument of the options 'f' or 'o' are missed, X * the handler are called with X * handler ("<options name>", ""); X * X * X * BUGS: X * The longest options is matched. If you have declared X * 'o' as an options with an argument and 'op' as a X * switch, the option 'o' is never detected, because X * 'op' is longer. X */ X X/* X * Externals X */ Xextern char *malloc(); X X#define MINUS_CHAR_REQUIRED 1 X X/* X * Variables X */ X X#ifdef DEBUG_PARSE Xstatic int debug_parse = 0; X#endif DEBUG_PARSE X Xstatic Xint GetNextOption (str, odesc, minus_char_required) X char *str; X OptDesc odesc[]; X int minus_char_required; X{ X int i, j; X X if (!str) return -1; X X if (minus_char_required) { X if (*str != '-') X return -1; X } X X if (*str == '-') { X str++; X } X X for (i = 0; odesc[i].opt_name; i++) { X if (!(j = strncmp (odesc[i].opt_name, X str, strlen (odesc[i].opt_name)))) X return i; X } X return -1; X} X X Xstatic Xint IsOption (str, odesc, minus_char_required) X char *str; X OptDesc odesc[]; X int minus_char_required; X{ X return (GetNextOption (str, odesc, minus_char_required) >= 0 ? 1 : 0); X} X Xstatic Xchar *SkipThisOption (str, length) X char *str; X int length; X{ X if (*str == '-') str++; X return (str + length); X} X Xstatic Xint cmp_length (left, right) X OptDesc *left, *right; X{ X return (strlen (right->opt_name) - strlen (left->opt_name)); X} X Xstatic Xint cmp_alpha (left, right) X OptDesc *left, *right; X{ X return (strcmp (left->opt_name, right->opt_name)); X} X Xstatic Xint RearrangeOptDesc (odesc, cmp_function) X OptDesc *odesc; X int (*cmp_function)(); /* function that compares */ X{ X int nelem; X X for (nelem = 0; odesc[nelem].opt_name; nelem++) ; X X qsort (odesc, nelem, sizeof (struct optdesc), cmp_function); X} X Xint ParseArgs (pac, pav, newac, newav, odesc) X int pac; /* number arguments */ X char **pav; /* the arguments itself */ X int *newac; /* number arguments after parsing */ X unsigned long *newav; /* the arguments after parsing */ X OptDesc odesc[]; /* the options descriptions */ X{ X X char **cpp; /* temporary points to pav */ X char **ArgV; X char *this_arg; /* points to the current argument */ X int option, minus_char_required, opterr = 0; X char *optrepr; X int optkind; X int (*opthandler)(); X X /* X * inititialization phase X */ X *newac = 0; X X /* allocate some memory for newav */ X if ((ArgV = (char **) malloc (sizeof (char **) * (pac + 1))) == (char **) NULL) { X perror ("malloc"); X exit (1); X } X X RearrangeOptDesc (odesc, cmp_length); /* sort by length */ X X#ifdef DEBUG_PARSE X if (!strcmp (pav[1], "\001\002")) { /* ^A^B */ X debug_parse++; X fprintf (stderr, "ParseArgs: debugging enabled.\n"); X } X#endif DEBUG_PARSE X X /* X * scanning phase X */ X pav++; /* skip program name */ X X#ifdef DEBUG_PARSE X if (debug_parse) pav++; X#endif DEBUG_PARSE X X while (pav && *pav) { X this_arg = *pav; /* beginning of next argument */ X minus_char_required = 1; /* require a '-' if argument is a option */ X X while (this_arg && *this_arg) { X if ((option = GetNextOption (this_arg, odesc, minus_char_required)) >= 0) { X optrepr = odesc[option].opt_name; /* option's name */ X optkind = odesc[option].opt_kind; /* option's kind */ X opthandler = odesc[option].opt_handler; /* option's handler */ X X this_arg = SkipThisOption (this_arg, strlen (optrepr)); X minus_char_required = 0; /* -fe f AND e are options */ X X switch (optkind) { X case OPT_IS_SWITCH: X opterr += opthandler (optrepr); X break; X case OPT_HAS_OPT_ARG: X /* X * at this point, this_arg points to the next char after X * the detected option or this_arg has reached the end. X */ X if (!*this_arg) { /* *this_arg == '\0' */ X if (*++pav) { /* next arg exists */ X this_arg = *pav; X if (IsOption (this_arg, odesc, MINUS_CHAR_REQUIRED)) { /* always '-' required */ X opterr += opthandler (optrepr, ""); X this_arg = NULL; X pav--; X } X else { X opterr += opthandler (optrepr, this_arg); X this_arg = NULL; X } X } X else { /* end of pav reached */ X opterr += opthandler (optrepr, ""); X this_arg = NULL; X pav--; X } X } X else { X if (! IsOption (this_arg, odesc, (! MINUS_CHAR_REQUIRED))) { /* rest of this_arg contains arg */ X opterr += opthandler (optrepr, this_arg); X this_arg = NULL; X } X else { X opterr += opthandler (optrepr, ""); X } X } X break; X case OPT_HAS_ARG: X if (!*this_arg) { /* end of this arg reached */ X pav++; X this_arg = *pav; X if (!this_arg) { /* end of pav reached */ X opterr += opthandler (optrepr, ""); X this_arg = NULL; X pav--; X } X else { X opterr += opthandler (optrepr, this_arg); X this_arg = NULL; X } X } X else { X opterr += opthandler (optrepr, this_arg); X this_arg = NULL; X } X break; X default: X fprintf (stderr, "ParseOpt: Non option detected as option: %s.\n", X odesc[option].opt_name); X exit (1); X break; X } /* end switch */ X } /* end then */ X else { /* argument is not a options */ X ArgV[*newac] = this_arg; X (*newac)++; X this_arg = NULL; X } X } X pav++; /* select next argument */ X } X X /* finalization phase */ X ArgV[*newac] = (char *) NULL; X X#ifdef DEBUG_PARSE X if (debug_parse) { X int j; X fprintf (stderr, "ParseArgs: Pure Arguments are:\nParseArgs:\t"); X X if (!*ArgV) fprintf (stderr, "<none>\n"); X else { X for (j = 0; ArgV[j]; j++) { X fprintf (stderr, "%s ", ArgV[j]); X } X fprintf (stderr, "\n"); X } X debug_parse = 0; X fprintf (stderr, "ParseArgs: Debugging disabled.\n"); X } X#endif DEBUG_PARSE X X *newav = (unsigned long) ArgV; X return opterr; /* return # of errors. 0 means no error */ X} X Xpa_ShortUsage (progname, odesc, extra_text) X char *progname; X struct optdesc odesc[]; X char *extra_text; X{ X int i; X int twidth = 80; X int c_printed = 6; X int length = 0; X int nextlineoff; X char buf[80]; X X RearrangeOptDesc (odesc, cmp_alpha); X X#define GetTerminalWidth(x) 80 X twidth = GetTerminalWidth(); X X fprintf (stderr, "usage:"); X X if (progname && *progname) { X fprintf (stderr, " %s:", progname); X c_printed += strlen (progname) + 2; X } X X nextlineoff = c_printed + 3; X X /* first switches than option requiring an agrument */ X fprintf (stderr, " [-"); X c_printed += 3; X X for (i = 0; odesc[i].opt_name; i++) { X if (odesc[i].opt_kind == OPT_IS_SWITCH) { X length = strlen (odesc[i].opt_name); length++; X if (c_printed + length > twidth) { X c_printed = length + nextlineoff; X sprintf (buf, "\n%%%dc", nextlineoff); X fprintf (stderr, buf, ' '); X } X else { X c_printed += length; X } X X fprintf (stderr, " %s", odesc[i].opt_name); X } X } X X fprintf (stderr, "]"); c_printed++; X nextlineoff -= 3; X X for (i = 0; odesc[i].opt_name; i++) { X length = strlen (odesc[i].opt_name); X X switch (odesc[i].opt_kind) { X case OPT_IS_SWITCH: X break; X case OPT_HAS_OPT_ARG: X if ((c_printed + 14 + length) > 80) { X c_printed = length + nextlineoff + 14; X sprintf (buf, "\n%%%dc", nextlineoff); X fprintf (stderr, buf, ' '); X } X else { X c_printed += length + 14; X } X X fprintf (stderr, " [-%s <opt arg>]", odesc[i].opt_name); X break; X case OPT_HAS_ARG: X if ((c_printed + 10 + length) > 80) { X c_printed = length + nextlineoff + 10; X sprintf (buf, "\n%%%dc", nextlineoff); X fprintf (stderr, buf, ' '); X } X else { X c_printed += length + 10; X } X X fprintf (stderr, " [-%s <arg>]", odesc[i].opt_name); X break; X default: X break; X } X } X X if ((strlen (extra_text) + c_printed + 1) > twidth) { X sprintf (buf, "\n%%%dc", nextlineoff); X fprintf (stderr, buf, ' '); X } X X fprintf (stderr, " %s\n", extra_text); X} END_OF_FILE if test 12926 -ne `wc -c <'src/misc/ParseArgs.c'`; then echo shar: \"'src/misc/ParseArgs.c'\" unpacked with wrong size! fi # end of 'src/misc/ParseArgs.c' fi if test -f 'src/shape/misc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/shape/misc.c'\" else echo shar: Extracting \"'src/shape/misc.c'\" \(13128 characters\) sed "s/^X//" >'src/shape/misc.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ X#ifndef lint Xstatic char *RCSid = "$Header: misc.c,v 3.5 89/02/21 17:11:54 wolfgang Exp $"; X#endif X#ifndef lint Xstatic char *ConfFlg = CFFLGS; /* should be defined from within Makefile */ X#endif X/* X * $Log: misc.c,v $ X * Revision 3.5 89/02/21 17:11:54 wolfgang X * append_mtime changed X * X * Revision 3.4 89/02/20 16:26:08 wolfgang X * NET-RELEASE X * X * Revision 3.3 89/02/08 16:19:55 wolfgang X * one comment added for lint. X * .. X * X * Revision 3.2 89/02/08 12:46:32 wolfgang X * performance improved. X * X * Revision 3.1 89/02/06 14:26:41 wolfgang X * bug fixed. X * X * Revision 3.0 89/01/24 11:36:12 wolfgang X * New System Generation X * X * Revision 2.19 89/01/23 16:14:42 wolfgang X * inheritance of uda's is now suppressed X * X * Revision 2.18 89/01/03 13:12:23 wolfgang X * changes done for lint X * X * Revision 2.17 88/12/22 12:36:39 wolfgang X * dummy procedure free_linklist()m added. X * X * Revision 2.16 88/12/21 15:11:10 wolfgang X * changes done for lint X * X * Revision 2.15 88/12/19 13:21:27 wolfgang X * is_in_forcelist added(). X * X * Revision 2.14 88/11/23 12:35:48 wolfgang X * Another dorpkey added. X * X * Revision 2.13 88/11/21 20:55:10 wolfgang X * changes done for sun X * X * Revision 2.12 88/11/09 16:25:59 wolfgang X * bugs fixed X * X * Revision 2.11 88/11/08 11:05:02 wolfgang X * This version is part of a release X * X * Revision 2.10 88/11/03 17:29:46 wolfgang X * calls of af_dropset added in compare_attrstring(). X * X * Revision 2.9 88/10/10 16:54:43 wolfgang X * changed for the -t option. if (touchflg) nothing is restored. X * X * Revision 2.8 88/09/23 15:54:20 wolfgang X * bug fixed in get_attr_type (retrn values). X * X * Revision 2.7 88/09/22 16:15:06 wolfgang X * clleanup_links() changed (now recursive). X * X * Revision 2.6 88/09/07 11:23:30 wolfgang X * unlinking of tmp file added to cleanup_links(). X * X * Revision 2.5 88/08/25 16:09:07 wolfgang X * Message: ... restored from bpool changed; [busy] is supreesed and if X * type = "" the "." is supressed. X * X * Revision 2.4 88/08/22 15:30:43 wolfgang X * Two types added: syspath & host; are necessary for confid. X * X * Revision 2.3 88/08/22 11:24:06 wolfgang X * Attribute string changed: added "." between name & type. X * X * Revision 2.2 88/08/19 10:05:59 wolfgang X * bug fixed; if attrs were too long for bpool file, the identification X * of the busy version had not been correct. X * Furthermore the format of the string "... version restored ..." has X * been changed, so that -2 .-2 for busy Version is supressed. X * X * Revision 2.1 88/08/18 13:19:41 wolfgang X * minor bug fixes; mtime added to identification string of derived objects X * X */ X X#include <sys/types.h> X#include <sys/dir.h> X#include "shape.h" X Xextern char *forcelist[]; Xextern Bool is_in_forcelist(); Xextern char *template; Xextern int af_cleanup(); X X/* Struct for registering links */ Xstruct linkreg *link_reg = (struct linkreg *) NIL; Xstruct linkreg *last_link; X Xchar *longattrs[MAXDEPTH]; X Xchar *types[] = { "generation", /* 0 int */ X "revision", /* 1 int */ X "state", /* 2 short */ X "author", /* 3 short */ X "group", /* 4 short */ X "version", /* 5 char * */ X "variant", /* 6 char * */ X "syspath", /* 7 char * */ X "host", /* 8 char * */ X "0"}; /* 99 default = char * X (for userdefined attributes */ X X Xchar *states[] = { "busy", X "saved", X "proposed", X "published", X "accessed", X "frozen", X "0"}; X X Xint get_attr_type(name) X char *name; X{ X int i = 0; X X if (name == NIL) X return(99); X X while(strcmp(types[i],"0") != 0) X { X if((strcmp(types[i],name) == 0)) X return(i); X i++; X } X return(99); X} X Xint get_state_no(state) X char *state; X{ X int i = 0; X while(strcmp(states[i],"0") != 0) X { X if((strcmp(states[i],state) == 0)) X return(i); X i++; X } X return(99); X} X X Xstruct linkreg *init_linkreg() X{ X struct linkreg *lreg = (struct linkreg *) NIL; X X if ((lreg = (struct linkreg *) malloc(sizeof(struct linkreg))) == X (struct linkreg *) NIL) X errexit(10,"malloc"); X if((lreg->fn = malloc(MAXNAMLEN)) == NIL) X errexit(10,"malloc"); X if((lreg->newfn = malloc(MAXNAMLEN)) == NIL) X errexit(10,"malloc"); X lreg->fn[0] = '\0'; X lreg->newfn[0] = '\0'; X lreg->next = (struct linkreg *) NIL; X X return(lreg); X} X X Xregister_link(fn, newfn, busy_exist) X char *fn; X char *newfn; X Bool busy_exist; X{ X if (link_reg == (struct linkreg *) NIL) X { X link_reg = init_linkreg(); X (void) strcpy(link_reg->fn, fn); X (void) strcpy(link_reg->newfn, newfn); X link_reg->busy_exist = busy_exist; X last_link = link_reg; X } X else X { X last_link->next = init_linkreg(); X last_link = last_link->next; X (void) strcpy(last_link->fn, fn); X (void) strcpy(last_link->newfn, newfn); X last_link->busy_exist = busy_exist; X } X} X Xcleanup_links(cur_link) X struct linkreg *cur_link; X{ X char filename[MAXNAMLEN]; X char afsname[MAXNAMLEN]; X if(cur_link != (struct linkreg *) NIL) X { X cleanup_links(cur_link->next); X } X if(cur_link != (struct linkreg *) NIL) X { X if(rindex(cur_link->fn,'/') == 0) X { X (void) strcpy(filename, "./"); X (void) strcat(filename, cur_link->fn); X (void) strcpy(afsname, "./"); X (void) strcat(afsname, cur_link->newfn); X } X else X { X (void) strcpy(filename, cur_link->fn); X (void) strcpy(afsname, cur_link->newfn); X } X if (unlink(filename) != 0) X { X fprintf(stderr, "shape - Aaaaaaaaaaaaaaaaargh !!!!!\n"); X fprintf(stderr, "error while cleaning up links :\n"); X fprintf(stderr, "can't unlink %s\n", filename); X fprintf(stderr, "contact guru immediately !\n"); X af_cleanup(); X exit(1); X } X if (cur_link->busy_exist) X { X if (link(afsname,filename) != 0) X { X fprintf(stderr, "shape - Aaaaaaaaaaaaaaaaargh !!!!!\n"); X fprintf(stderr, "error while cleaning up links :\n"); X fprintf(stderr, "can't link %s to %s\n", filename, afsname); X fprintf(stderr, "contact guru immediately !\n"); X af_cleanup(); X exit(1); X } X if (unlink(afsname) != 0) X { X fprintf(stderr, "shape - Aaaaaaaaaaaaaaaaargh !!!!!\n"); X fprintf(stderr, "error while cleaning up links :\n"); X fprintf(stderr, "can't unlink %s\n", filename); X fprintf(stderr, "contact guru immediately !\n"); X af_cleanup(); X exit(1); X } X } X } X} X Xint free_linklist() X{ X/* not yet implemented */ X/* should free memory of linklist */ X ; X} X XBool compare_attrstring(attr, rulename, name, objrulename) X /*ARGSUSED*/ X char *attr; X struct rules *rulename; X char *name; X struct rules *objrulename; X{ X Af_set aset; X Af_set bset; X Af_attrs buf; X Af_attrs buf1; X Af_attrs buf2; X Af_key akey; X Af_key bkey; X Af_key key1; X Af_key key2; X Af_key restorekey; X X int retcode; X int retcode1; X char bname[MAXNAMLEN]; X char *type; X char *p; X char *d; X char sysp[MAXNAMLEN]; X X if (touchflg) X return(0); X X sysp[0] = '\0'; X X (void) strcpy(bname,name); X if ((p = rindex(bname,'.')) == 0) X { X type = NIL; X } X else X { X p[0] = '\0'; X *p++; X type = p; X } X X if ((d = rindex(bname,'/')) != 0) X { X (void) strcpy(sysp, bname); X d = rindex(sysp, '/'); X d[0] = '\0'; X *d++; X (void) strcpy(bname,d); X } X af_initattrs(&buf); X X buf.af_gen = AF_BUSYVERS; X buf.af_rev = AF_BUSYVERS; X X if(sysp[0] != '\0') X (void) strcpy(buf.af_syspath,sysp); X else X (void) strcpy(buf.af_syspath,curvpath[0]); X X (void) strcpy(buf.af_name,bname); X if (p != NIL) X (void) strcpy(buf.af_type,p); X else X (void) strcpy(buf.af_type,""); X X if (forceflg) X { X if (is_in_forcelist(name,type)) X return(3); X } X X if ((retcode1 = af_find(&buf, &aset)) == -1) X errexit(10,"af_find"); X X buf.af_gen = AF_NOVNUM; X buf.af_rev = AF_NOVNUM; X X buf.af_udattrs[0] = attr; X buf.af_udattrs[1] = NIL; X X if ((retcode = af_bpfind(&buf,&bset)) == -1) X errexit(10,"af_bpfind"); X X if ((retcode1 == 1) && (retcode == 0)) X /* derived object is not in binary pool (attr had been too long */ X { X if((retcode = af_find(&buf, &bset)) == -1) X { X errexit(10,"af_find"); X } X else X { X if (af_dropset(&bset) == -1) X errexit(10,"af_dropset"); X if (af_dropset(&aset) == -1) X errexit(10,"af_dropset"); X X if (retcode == 1) X /* busy version owns the correct attribute */ X return (0); X else X return(3); X } X } X X if ((retcode1 == 1) && (retcode == 1)) X { X if(af_setgkey(&aset,0,&key1) == -1) X errexit(10,"af_setgkey"); X if(af_setgkey(&bset,0,&key2) == -1) X errexit(10,"af_setgkey"); X if(af_gattrs(&key1,&buf1) == -1) X errexit(10,"af_gattrs"); X if(af_gattrs(&key2,&buf2) == -1) X errexit(10,"af_gattrs"); X if(buf1.af_mtime == buf2.af_mtime) X { X if (af_dropset(&bset) == -1) X errexit(10,"af_dropset"); X if (af_dropset(&aset) == -1) X errexit(10,"af_dropset"); X return (0); X } X } X if (retcode == 0) X { X if (af_dropset(&bset) == -1) X errexit(10,"af_dropset"); X if (af_dropset(&aset) == -1) X errexit(10,"af_dropset"); X return (3); X } X else X { X if (af_setgkey(&bset,0,&bkey) == -1) X errexit(10,"af_setgkey"); X if (retcode1 == 1) X { X if (af_setgkey(&aset,0,&akey) == -1) X errexit(10,"af_setgkey"); X if (af_dropkey(&akey) == -1) X errexit(10,"af_dropkey"); X } X if (af_restore(&bkey,&restorekey) == -1) X errexit(10,"af_restore"); X X if (af_sudattr(&restorekey,AF_REPLACE,attr) == -1) X errexit(10,"af_sudattr"); X X if (af_gattrs(&bkey,&buf) == -1) X errexit(10,"af_gattrs"); X X if (af_dropkey(&bkey) == -1) X errexit(10,"af_dropkey"); X X if (buf.af_gen != AF_BUSYVERS) X { X printf ("... %s.%s[%d.%d] restored from bpool\n", X buf.af_name, buf.af_type, buf.af_gen, buf.af_rev); X } X else X { X if (strcmp(buf.af_type,"")) X printf ("... %s.%s restored from bpool\n", X buf.af_name, buf.af_type); X else X printf ("... %s restored from bpool\n", X buf.af_name); X } X if (af_dropset(&bset) == -1) X errexit(10,"af_dropset"); X if (af_dropset(&aset) == -1) X errexit(10,"af_dropset"); X return(0); X } X} X X Xint append_attrs(buf,recdepth) X Af_attrs *buf; X int recdepth; X{ X char attributes[MAX_ATTR]; X X (void) sprintf(attributes,"%s%s%s%s%s%d%d%d%d", X buf->af_name, X ".", X buf->af_type, X buf->af_host, X buf->af_syspath, X buf->af_gen, X buf->af_rev, X buf->af_state, X buf->af_mtime /* , X buf->af_owner.af_username, X buf->af_owner.af_userhost, X buf->af_author.af_username, X buf->af_author.af_userhost, X buf->af_locker.af_username, X buf->af_locker.af_userhost, X buf->af_size, X buf->af_mode, X buf->af_atime, X buf->af_ctime, X buf->af_stime, X buf->af_ltime */ X ); X X/* i = 0; X while(buf->af_udattrs[i] != NIL) X { X if ((strlen(attributes) + strlen(buf->af_udattrs[i])) >= MAX_ATTR) X errexit(29,NIL); X (void) strcat(attributes,buf->af_udattrs[i]); X i++; X } X*/ X if ((strlen(attributes) + strlen(longattrs[recdepth])) >= MAX_ATTR) X errexit(29,NIL); X X (void) strcat(longattrs[recdepth],attributes); X X#ifdef DEBUG_MISC Xprintf("depth=%d;longattr=%s\n", recdepth, longattrs[recdepth]); X#endif DEBUG_MISC X X} X Xappend_mtime(testbuf,recdepth) X Af_attrs *testbuf; X /*ARGSUSED*/ X int recdepth; X{ X char time[64]; X /* (void) sprintf(time,"%d",testbuf->af_mtime); X (void) strcat(longattrs[recdepth],time); */ X} X X XBool is_in_forcelist(name,type) X char *name; X char *type; X{ X char fullname[MAXNAMLEN]; X int i = 0; X fullname[0] = '\0'; X (void) strcpy(fullname,name); X if (strcmp(type,"")) X { X (void) strcat(fullname,"."); X (void) strcat(fullname,type); X } X X while(forcelist[i] != NIL) X { X if (!strcmp(forcelist[i],fullname)) X return(TRUE); X i++; X } X return(FALSE); X} X X END_OF_FILE if test 13128 -ne `wc -c <'src/shape/misc.c'`; then echo shar: \"'src/shape/misc.c'\" unpacked with wrong size! fi # end of 'src/shape/misc.c' fi if test -f 'src/vc/retrv.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/vc/retrv.c'\" else echo shar: Extracting \"'src/vc/retrv.c'\" \(13192 characters\) sed "s/^X//" >'src/vc/retrv.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ X#ifndef lint Xstatic char *AFSid = "$Header: retrv.c[3.7] Thu Feb 23 18:13:45 1989 axel@coma published $"; X#ifdef CFFLGS Xstatic char *ConfFlg = CFFLGS; X /* should be defined from within Makefile */ X#endif X#endif X/* X * Log for /u/shape/dist-tape/src/vc/retrv.c[3.2] X * Thu Feb 23 18:13:46 1989 axel@coma save $ X * --- empty log message --- X * retrv.c[3.3] Thu Feb 23 18:13:46 1989 axel@coma save $ X * --- empty log message --- X * retrv.c[3.4] Thu Feb 23 18:13:46 1989 axel@coma published $ X * --- empty log message --- X * retrv.c[3.5] Thu Feb 23 18:13:46 1989 axel@coma published $ X * --- empty log message --- X * retrv.c[3.6] Thu Feb 23 18:13:46 1989 axel@coma save $ X * --- empty log message --- X * retrv.c[3.7] Thu Feb 23 18:13:46 1989 axel@coma published $ X * --- empty log message --- X */ X X/* X * retrv [-fmqtx] [-V version] [-a attrs] [-d date] [-g generation] X * [-n author] [-p pname] [-s state] [-lock] [-dest path] fn [fn1 ...] X * X * Retrieve a previously saved version of a file. We orient us pretty much X * towards the check-out operation of RCS. Retrieve determines the X * archive name to be searched from the given file names. Unless otherwise X * specified by the project context (-p), the archive is expected to X * reside in the AFS subdirectory. The retrieved version will be created X * in the current directory. Retrieve tries to be careful if an X * attempt is made to overwrite an existing busy-version: unless -f X * is specified, retrv will ask the caller for permission. X * If no busy version exists, one is created with the modes of the X * formerly saved version. If one exists, it's modes are kept unless X * -m is given. X * There's a number of ways to specify which version should be retrieved. X * With -V an explicit version can be selected. Another argument to -V X * could be a symbolic name (hopefully unique). Alternatively, versions X * can be selected by supplying certain attribute values to retrv, such as X * the name of the author, the version state, a generation number or a X * set of user defined attributes, possibly describing a variant. In case X * that more than one version fits the desired attributes, the newest X * of them is selected, unless -x (exact!) is specified. -V implies -x. X */ X X#include <sys/types.h> X#include <sys/stat.h> X#include <stdio.h> X#include <strings.h> X#include "ParseArgs.h" X#include "afs.h" X#include "retrv.h" X#include "project.h" X Xchar *progname; X Xstruct Transaction ThisTransaction; X X/* forward decls for option handlers */ Xextern handle_R_switch (); Xextern handle_f_switch (); Xextern handle_l_switch (); Xextern handle_m_switch (); Xextern handle_q_switch (); Xextern handle_t_switch (); Xextern handle_x_switch (); Xextern handle_V_opt (); Xextern handle_a_opt (); Xextern handle_d_opt (); Xextern handle_dest_opt (); Xextern handle_g_opt (); Xextern handle_n_opt (); Xextern handle_p_opt (); Xextern handle_s_opt (); Xextern usage (); X Xunsigned int options; X Xstatic OptDesc retrvargs[] = { X { "version", OPT_IS_SWITCH, handle_R_switch }, X { "f", OPT_IS_SWITCH, handle_f_switch }, X { "l", OPT_IS_SWITCH, handle_l_switch }, X { "lock", OPT_IS_SWITCH, handle_l_switch }, X { "m", OPT_IS_SWITCH, handle_m_switch }, X { "q", OPT_IS_SWITCH, handle_q_switch }, X { "t", OPT_IS_SWITCH, handle_t_switch }, X { "x", OPT_IS_SWITCH, handle_x_switch }, X { "V", OPT_HAS_ARG, handle_V_opt }, X { "a", OPT_HAS_ARG, handle_a_opt }, X { "d", OPT_HAS_ARG, handle_d_opt }, X { "date", OPT_HAS_ARG, handle_d_opt }, X { "dest", OPT_HAS_ARG, handle_dest_opt }, X { "g", OPT_HAS_ARG, handle_g_opt }, X { "n", OPT_HAS_ARG, handle_n_opt }, X { "p", OPT_HAS_ARG, handle_p_opt }, X { "s", OPT_HAS_ARG, handle_s_opt }, X { "h", OPT_IS_SWITCH, usage }, X/* { "?", OPT_HAS_ARG, usage }, */ X { (char *) NULL, NULL, NULL } X}; Xstatic OptDesc vcatargs[] = { X { "version", OPT_IS_SWITCH, handle_R_switch }, X { "q", OPT_IS_SWITCH, handle_q_switch }, X { "t", OPT_IS_SWITCH, handle_t_switch }, X { "x", OPT_IS_SWITCH, handle_x_switch }, X { "V", OPT_HAS_ARG, handle_V_opt }, X { "a", OPT_HAS_ARG, handle_a_opt }, X { "d", OPT_HAS_ARG, handle_d_opt }, X { "date", OPT_HAS_ARG, handle_d_opt }, X { "g", OPT_HAS_ARG, handle_g_opt }, X { "n", OPT_HAS_ARG, handle_n_opt }, X { "p", OPT_HAS_ARG, handle_p_opt }, X { "s", OPT_HAS_ARG, handle_s_opt }, X { "h", OPT_IS_SWITCH, usage }, X/* { "?", OPT_HAS_ARG, usage }, */ X { (char *) NULL, NULL, NULL } X}; X Xstatic int nfnms; X Xstatic struct Vdesc dversion; X Xchar *dp = NULL; /* nasty sideeffect here - see 'handle_dest_opt' */ X Xmain (ac, av) char **av; { X register int i; X int nac, bound_vid = 0, rc = 0; X unsigned int options_bak = 0; X char messg[80], *es, *getenv(), **nav, *version(), vstring[16], *cp; X Project pdesc; X struct Vdesc *vdescr = &dversion, alt_dversion; X X progname = (cp = rindex (av[0], '/')) ? ++cp : av[0]; X /* make prog-name available to entire program */ X X if (ac < 2) { X pa_ShortUsage (progname, vcatargs, "files ..."); X } X X if (!strcmp (progname, TONAME)) { X options |= TYPEOUT; X if (ParseArgs (ac, av, &nac, &nav, vcatargs)) { X pa_ShortUsage (progname, vcatargs, "files..."); X } X } X else { X if (ParseArgs (ac, av, &nac, &nav, retrvargs)) { X pa_ShortUsage (progname, retrvargs, "files..."); X } X } X X if (!(options & (TYPEOUT | COPY | LOCKIT))) options |= COPY; X X if (!(options & ATTRDEF)) { X es = getenv (RTRATTR); X if ((es) && (es[0] != '\0')) { X options |= ATTRDEF; X (void)strcpy (dversion.v_attrf, es); X } X } X X if ((options & PROJCSET) && fail(GetProject (dversion.v_pname, &pdesc))) { X (void)sprintf (messg, "%s %s", EINVALPROJ, dversion.v_pname); X logerr (messg); X exit (1); X } X X CatchSigs (); X nfnms = nac; X ThisTransaction.tr_rc = 0; X for (i = 0, vdescr = &dversion; i < nfnms; i++) { X if (!setjmp (ThisTransaction.tr_env)) { X if (bound_vid) { X bound_vid = FALSE; X options = options_bak; /* restore original selection options */ X vdescr = &dversion; X } X ThisTransaction.tr_seqno = i; X if (BoundVersion (nav[i], ThisTransaction.tr_fname, vstring)) { X alt_dversion.v_vno = mkvno (vstring); X options_bak = options; /* save original selection options */ X options |= (VSPECSET | XACT); X options &= ~(ATTRDEF | GENSET | AUNSET | STATSET | DATESET); X vdescr = &alt_dversion; X bound_vid = TRUE; X } X else { X (void)strcpy (ThisTransaction.tr_fname, nav[i]); X } X ThisTransaction.tr_done = FALSE; X RetrieveAFile (ThisTransaction.tr_fname, vdescr, &pdesc, dp); X } X else { /* ThisTransaction was aborted */ X rc += ThisTransaction.tr_rc; X } X } X logdiag ("done."); X return (rc); X} X XSfunc_t interrupt_action () { /* is executed by appropriate signal handler */ X char messg[80]; X X if ((nfnms - ThisTransaction.tr_seqno) > 1) { X (void)sprintf (messg, "\ncompletely stop retrieving (%d files pending) ?", X nfnms - ThisTransaction.tr_seqno); X if (ask_confirm (messg, "no")) { X if (ThisTransaction.tr_done) { X (void)sprintf (messg, "\ntoo late, %s already restored", X ThisTransaction.tr_fname); X logdiag (messg); X return; /* continue where we've been interrupted */ X } X (void)sprintf (messg, NORESTORE, ThisTransaction.tr_fname); X logdiag (messg); X longjmp (ThisTransaction.tr_env, 1); X } X else { X (void)sprintf (messg, NORESTORE, ThisTransaction.tr_fname); X logmsg (messg); X exit (1); X } X } X else { X (void)sprintf (messg, "\n%s not restored", ThisTransaction.tr_fname); X logdiag (messg); X exit (1); X } X} X Xlogmsg (msg) char *msg; { X if (!(options & QUIETPLEASE)) { X fprintf (stdout, "%s\n", msg); X } X} X Xlogdiag (msg) char *msg; { X if (!(options & QUIETPLEASE)) { X fprintf (stderr, "%s\n", msg); X } X} X Xlogerr (msg) char *msg; { X fprintf (stderr, "%s: %s\n", progname, msg); X} X X/*ARGSUSED*/ Xhandle_R_switch (o, a) char *o, *a; { X printf ("This is %s version %s.\n", progname, version ()); X printf ("AFS version %s.\n", af_version()); X exit (0); X} X X/*ARGSUSED*/ Xhandle_f_switch (o, a) char *o, *a; { X options |= FORCE; X return 0; X} X X/*ARGSUSED*/ Xhandle_l_switch (o, a) char *o, *a; { X char messg[128]; X X if (options & TYPEOUT) { X logerr ("Locking makes no sense in TYPEOUT mode of operation - ignored."); X return 0; X } X if (options & COPY) { X (void)sprintf (messg, "No checkout (with lock) to distant directory %s.", dp); X logerr (messg); X exit (1); X } X options |= LOCKIT; X return 0; X} X X/*ARGSUSED*/ Xhandle_m_switch (o, a) char *o, *a; { X options |= KEEPMODE; X return 0; X} X X/*ARGSUSED*/ Xhandle_q_switch (o, a) char *o, *a; { X options |= QUIETPLEASE; X return 0; X} X X/*ARGSUSED*/ Xhandle_t_switch (o, a) char *o, *a; { X if (options & LOCKIT) { X logerr ("Locking makes no sense in TYPEOUT mode of operation - ignored."); X options &= ~LOCKIT; X } X if (options & COPY) { X logerr ("TYPEOUT mode of operation overrides COPY mode."); X options &= ~COPY; X dp = NULL; X } X options |= TYPEOUT; X return 0; X} X X/*ARGSUSED*/ Xhandle_x_switch (o, a) char *o, *a; { X options |= XACT; X return 0; X} X X/*ARGSUSED*/ Xhandle_V_opt (o, a) char *o, *a; { X dversion.v_vno = mkvno (a); X (void)strcpy (dversion.v_spec, a); X options |= VSPECSET; X options |= XACT; X return 0; X} X X/*ARGSUSED*/ Xhandle_a_opt (o, a) char *o, *a; { X options |= ATTRDEF; X (void)strcpy (dversion.v_attrf, a); X return 0; X} X X/*ARGSUSED*/ Xhandle_d_opt (o, a) char *o, *a; { X char messg[128]; X time_t mktime(); X X if ((options & STATSET) && (dversion.v_state == AF_BUSY)) { X logmsg (WDOVRBS); X options &= ~STATSET; X } X if (dversion.v_time = mktime (a)) { X options |= DATESET; X return 0; X } X else { X (void)sprintf (messg, "invalid date specification: %s.", a); X logerr (messg); X tusage (); X return 1; X } X} X X/*ARGSUSED*/ Xhandle_dest_opt (o, a) char *o, *a; { X char messg[128]; X static char dpath[256]; X struct stat statbuf; X X if (!a) return 1; X if (options & LOCKIT) { X (void)sprintf (messg, "No checkout (with lock) to distant directory %s.", a); X logerr (messg); X exit (1); X } X if (options & TYPEOUT) { X logerr ("Already TYPEOUT mode of operation selected."); X return 0; X } X if (options & COPY) { X (void)sprintf (messg, "Destination path already set to %s. %s ignored.", dpath, X a); X logerr (messg); X return 0; X } X options |= COPY; X (void)strcpy (dpath, a); X if (stat (dpath, &statbuf) < 0) { X (void)sprintf (messg, "Destination path %s does not exist.", dpath); X logerr (messg); X exit (1); X } X if (!(statbuf.st_mode & S_IFDIR)) { X (void)sprintf (messg, "Destination %s is not a directory.", dpath); X logerr (messg); X exit (1); X } X dp = dpath; X return 0; X} X X/*ARGSUSED*/ Xhandle_g_opt (o, a) char *o, *a; { X char messg[128]; X X if (dversion.v_genno = mkgenno (a)) { X options |= GENSET; X return 0; X } X else { X (void)sprintf (messg, "'%s' is not a legal generation number.", a); X logerr (messg); X return 1; X } X} X X/*ARGSUSED*/ Xhandle_n_opt (o, a) char *o, *a; { X char *cp; X X options |= AUNSET; X if (cp=index (a, '@')) { X *cp = '\0'; X (void)strcpy (dversion.v_auhost, ++cp); X } X (void)strcpy (dversion.v_aunam, a); X return 0; X} X X/*ARGSUSED*/ Xhandle_p_opt (o, a) char *o, *a; { X options |= PROJCSET; X (void)strcpy (dversion.v_pname, a); X return 0; X} X X/*ARGSUSED*/ Xhandle_s_opt (o, a) char *o, *a; { X char messg[128]; X X if (!fail((dversion.v_state = mkstate (a)))) { X if ((options & DATESET) && (dversion.v_state == AF_BUSY)) { X logmsg (WDOVRBS); X } X else { X options |= STATSET; X } X } X else { X (void)sprintf (messg, "unrecognized version state: %s.\n", a); X logerr (messg); X helpstates (); X exit (1); X } X return 0; X} X Xtusage () { X fputs ("specify time as yy/mm/dd[/hh:mm].\n", stderr); X} X Xhelpstates () { X fputs ("The following states are recognized:\n", stderr); X fputs ("\tbusy, save, proposed, published, accessed, frozen\n", stderr); X} X Xusage () { X if (strcmp (progname, "vcat")) X pa_ShortUsage (progname, retrvargs, "files ..."); X else X pa_ShortUsage (progname, vcatargs, "files ..."); X} END_OF_FILE if test 13192 -ne `wc -c <'src/vc/retrv.c'`; then echo shar: \"'src/vc/retrv.c'\" unpacked with wrong size! fi # end of 'src/vc/retrv.c' fi echo shar: End of archive 15 \(of 33\). cp /dev/null ark15isdone MISSING="" 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 if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 33 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.