[comp.sources.unix] v19i028: A software configuration management system, Part15/33

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.