[comp.sources.unix] v19i027: A software configuration management system, Part14/33

rsalz@uunet.uu.net (Rich Salz) (06/03/89)

Submitted-by: Axel Mahler <unido!coma!axel>
Posting-number: Volume 19, Issue 27
Archive-name: shape/part14



#! /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 14 (of 33)."
# Contents:  src/afs/afcompar.c src/shape/macro.c src/vc/vadm_note.c
#   src/vc/vadm_reserve.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:04 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/afs/afcompar.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/afs/afcompar.c'\"
else
echo shar: Extracting \"'src/afs/afcompar.c'\" \(12396 characters\)
sed "s/^X//" >'src/afs/afcompar.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/*
X *	Shape/AFS
X *
X *	afcompar.c -- attribute comparison routines 
X *
X *	Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X *					  (andy@db0tui62.BITNET)
X *
X *	$Header: afcompar.c[1.4] Wed Feb 22 16:27:23 1989 andy@coma published $
X *
X *	EXPORT:
X *      af_cmpatime -- compare dates of last access
X *      af_cmpauthor -- compare authors
X *      af_cmpctime -- compare dates of last status change
X *      af_cmpgen -- compare generation numbers
X *      af_cmphost -- compare hosts
X *      af_cmphuman -- compare name, type, gen, rev, variant
X *      af_cmplocker -- compare lockers
X *      af_cmpltime -- compare date of last lock change
X *      af_cmpmode -- compare protections
X *      af_cmpmtime -- compare dates of last modification
X *      af_cmpname -- compare names
X *      af_cmpowner -- compare owners
X *      af_cmprev -- compare revision numbers
X *      af_cmpsize -- compare file sizes
X *      af_cmpstate -- compare states
X *      af_cmpsvtime -- compare dates of saving
X *      af_cmpspath -- compare syspaths
X *      af_cmptype -- compare types
X *      af_cmpvariant -- compare variant attributes
X *      af_cmpversion -- compare version numbers (gen.rev)
X *
X *      af_cmpfuncts -- list of names of all compare functions
X *      af_attrlist -- list of attribute names
X *      af_udaname -- global variable holding the name of the
X *                    user defined attribute used for sorting
X *      af_cmpuda -- compare user defined attributes
X */
X
X#include <stdio.h>
X#include <string.h>
X#ifdef SUNOS_4_0
X#include <strings.h>
X#endif
X
X#include "typeconv.h"
X#include "afsys.h"
X#include "afs.h"
X
X/*================================================================
X *      af_cmpatime -- compare dates of last access
X *
X *================================================================*/
X
XEXPORT int af_cmpatime (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_atime - VATTR(key2).af_atime);
X}
X
X/*================================================================
X *      af_cmpauthor -- compare authors
X *
X *================================================================*/
X
XEXPORT af_cmpauthor (key1, key2)
X     Af_key *key1, *key2;
X{
X  int res;
X
X  if (!(res = strcmp (NOTNIL(VATTR(key1).af_auname),
X		      NOTNIL(VATTR(key2).af_auname))))
X    return (strcmp (NOTNIL(VATTR(key1).af_auhost),
X		    NOTNIL(VATTR(key2).af_auhost)));
X  else
X    return (res);
X}
X
X/*================================================================
X *      af_cmpctime -- compare dates of last status change
X *
X *================================================================*/
X
XEXPORT af_cmpctime (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_ctime - VATTR(key2).af_ctime);
X}
X
X/*================================================================
X *      af_cmpgen -- compare generation numbers
X *
X *================================================================*/
X
XEXPORT af_cmpgen (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_gen - VATTR(key2).af_gen);
X}
X
X/*================================================================
X *      af_cmphost -- compare hostnames
X *
X *================================================================*/
X
XEXPORT af_cmphost (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (strcmp (CATTR(key1).af_host, CATTR(key2).af_host));
X}
X
X/*================================================================
X *      af_cmphuman -- compare name, type, gen, rev, variant
X *
X *================================================================*/
X
XEXPORT af_cmphuman (key1, key2)
X     Af_key *key1, *key2;
X{
X  int diff;
X
X  if (!(diff = strcmp (VATTR(key1).af_name, VATTR(key2).af_name)) &&
X      !(diff = strcmp (NOTNIL(VATTR(key1).af_type),
X		       NOTNIL(VATTR(key2).af_type))) &&
X      !(diff = VATTR(key1).af_gen - VATTR(key2).af_gen) &&
X      !(diff = VATTR(key1).af_rev - VATTR(key2).af_rev))
X    {
X      return (strcmp (NOTNIL(VATTR(key1).af_variant),
X		      NOTNIL(VATTR(key2).af_variant)));
X    }
X  return (diff);
X}
X
X/*================================================================
X *      af_cmplocker -- compare lockers
X *
X *================================================================*/
X
XEXPORT af_cmplocker (key1, key2)
X     Af_key *key1, *key2;
X{
X  int res;
X
X  if (!(res = strcmp (NOTNIL(VATTR(key1).af_lckname),
X		      NOTNIL(VATTR(key2).af_lckname))))
X    return (strcmp (NOTNIL(VATTR(key1).af_lckhost),
X		    NOTNIL(VATTR(key2).af_lckhost)));
X  else
X    return (res);
X}
X
X/*================================================================
X *      af_cmpltime -- compare dates of last lock change
X *
X *================================================================*/
X
XEXPORT af_cmpltime (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_ltime - VATTR(key2).af_ltime);
X}
X
X/*================================================================
X *      af_cmpmode -- compare protections
X *
X *================================================================*/
X
XEXPORT af_cmpmode (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_mode - VATTR(key2).af_mode);
X}
X
X/*================================================================
X *      af_cmpmtime -- compare dates of last modification
X *
X *================================================================*/
X
XEXPORT af_cmpmtime (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_mtime - VATTR(key2).af_mtime);
X}
X
X/*================================================================
X *      af_cmpname -- compare names
X *
X *================================================================*/
X
XEXPORT af_cmpname (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (strcmp (VATTR(key1).af_name, VATTR(key2).af_name));
X}
X
X/*================================================================
X *      af_cmpowner -- compare owners
X *
X *================================================================*/
X
XEXPORT af_cmpowner (key1, key2)
X     Af_key *key1, *key2;
X{
X  int res;
X
X  if (!(res = strcmp (CATTR(key1).af_ownname, CATTR(key2).af_ownname)))
X    return (strcmp (CATTR(key1).af_ownhost, CATTR(key2).af_ownhost));
X  else
X    return (res);
X}
X
X/*================================================================
X *      af_cmprev -- compare revision numbers
X *
X *================================================================*/
X
XEXPORT af_cmprev (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_rev - VATTR(key2).af_rev);
X}
X
X/*================================================================
X *      af_cmpsize -- compare file size
X *
X *================================================================*/
X
XEXPORT af_cmpsize (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_fsize - VATTR(key2).af_fsize);
X}
X
X/*================================================================
X *      af_cmpstate -- compare states
X *
X *================================================================*/
X
XEXPORT af_cmpstate (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_state - VATTR(key2).af_state);
X}
X
X/*================================================================
X *      af_cmpsvtime -- compare dates of saving
X *
X *================================================================*/
X
XEXPORT af_cmpsvtime (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (VATTR(key1).af_stime - VATTR(key2).af_stime);
X}
X
X/*================================================================
X *      af_cmpspath -- compare syspaths
X *
X *================================================================*/
X
XEXPORT af_cmpspath (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (strcmp (CATTR(key1).af_syspath, CATTR(key2).af_syspath));
X}
X
X/*================================================================
X *      af_cmptype -- compare types
X *
X *================================================================*/
X
XEXPORT af_cmptype (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (strcmp (NOTNIL(VATTR(key1).af_type),
X		  NOTNIL(VATTR(key2).af_type)));
X}
X
X/*================================================================
X *      af_cmpvariant -- compare variant attribute
X *
X *================================================================*/
X
XEXPORT af_cmpvariant (key1, key2)
X     Af_key *key1, *key2;
X{
X  return (strcmp (NOTNIL(VATTR(key1).af_variant),
X		  NOTNIL(VATTR(key2).af_variant)));
X}
X
X/*================================================================
X *      af_cmpversion -- compare version numbers (gen.rev)
X *
X *================================================================*/
X
XEXPORT af_cmpversion (key1, key2)
X     Af_key *key1, *key2;
X{
X  if (VATTR(key1).af_gen == VATTR(key2).af_gen)
X    return (VATTR(key1).af_rev - VATTR(key2).af_rev);
X  else
X    return (VATTR(key1).af_gen - VATTR(key2).af_gen);
X}
X
X/*===============================================================
X *      af_cmpfuncts -- array of comparison functions
X *
X *===============================================================*/
X
Xstruct cmpfun { int (*func) (); };
X
XEXPORT struct cmpfun af_cmpfuncts[] = { af_cmpatime,
X					  af_cmpauthor,
X					  af_cmpctime,
X					  af_cmpgen,
X					  af_cmphost,
X					  af_cmphuman,
X					  af_cmplocker,
X					  af_cmpltime,
X					  af_cmpmode,
X					  af_cmpmtime,
X					  af_cmpname,
X					  af_cmpowner,
X					  af_cmprev,
X					  af_cmpsize,
X					  af_cmpstate,
X					  af_cmpsvtime,
X					  af_cmpspath,
X					  af_cmptype,
X					  af_cmpvariant,
X					  af_cmpversion,
X					};
X
X
X/*===============================================================
X *      af_attrlist -- list of attribute names
X *                     (in alphabetical order)
X *
X *===============================================================*/
X
XEXPORT char *af_attrlist[] = { AF_ATTATIME,
X				 AF_ATTAUTHOR,
X				 AF_ATTCTIME,
X				 AF_ATTGEN,
X				 AF_ATTHOST,
X				 AF_ATTHUMAN,
X				 AF_ATTLOCKER,
X				 AF_ATTLTIME,
X				 AF_ATTMODE,
X				 AF_ATTMTIME,
X				 AF_ATTNAME,
X				 AF_ATTOWNER,
X				 AF_ATTREV,
X				 AF_ATTSIZE,
X				 AF_ATTSTATE,
X				 AF_ATTSTIME,
X				 AF_ATTSPATH,
X				 AF_ATTTYPE,
X				 AF_ATTVARIANT,
X				 AF_ATTVERSION,
X				};
X
X/*================================================================
X *      af_cmpuda -- compare user defined attributes
X *
X *================================================================*/
X
XEXPORT char af_udaname[AF_UDANAMLEN];
X
XEXPORT af_cmpuda (key1, key2)
X     Af_key *key1, *key2;
X{
X  char *uda1, *uda2, *vallist1, *vallist2, *af_symlookup();
X
X  uda1 = af_symlookup (&(VATTR(key1).af_uhtab), af_udaname,
X		       (Af_revlist *)0, (Af_revlist **)0);
X  uda2 = af_symlookup (&(VATTR(key2).af_uhtab), af_udaname,
X		       (Af_revlist *)0, (Af_revlist **)0);
X
X  if (uda1 == (char *)0)
X    {
X      if (uda2 == (char *)0)
X	return (0); /* equal */
X      else
X	return (1); /* key1 is "greater" than key2 */
X    }
X  else
X    {
X      if (uda2 == (char *)0)
X	return (-1); /* key2 is "greater" than key1 */
X    }
X
X  /* see if ther are values */
X  vallist1 = index (uda1, AF_UDANAMDEL);
X  vallist2 = index (uda2, AF_UDANAMDEL);
X
X  if (vallist1 == (char *)0)
X    {
X      if (vallist2 == (char *)0)
X	return (0); /* equal */
X      else
X	return (1); /* key1 is "greater" than key2 */
X    }
X  else
X    {
X      if (vallist2 == (char *)0)
X	return (-1); /* key2 is "greater" than key1 */
X    }
X
X  /* compare values of user defined attributes */
X  /* this is a simple textual comparison up to now */
X  return (strcmp (vallist1, vallist2));
X}
X
END_OF_FILE
if test 12396 -ne `wc -c <'src/afs/afcompar.c'`; then
    echo shar: \"'src/afs/afcompar.c'\" unpacked with wrong size!
fi
# end of 'src/afs/afcompar.c'
fi
if test -f 'src/shape/macro.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/shape/macro.c'\"
else
echo shar: Extracting \"'src/shape/macro.c'\" \(12566 characters\)
sed "s/^X//" >'src/shape/macro.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: macro.c,v 3.2 89/02/20 16:25:49 wolfgang Exp $";
X#endif
X#ifndef lint
Xstatic char *ConfFlg = CFFLGS;	/* should be defined from within Makefile */
X#endif
X/*
X * $Log:	macro.c,v $
X * Revision 3.2  89/02/20  16:25:49  wolfgang
X * NET-RELEASE
X * 
X * Revision 3.1  89/02/08  12:45:34  wolfgang
X * performance improved.
X * 
X * Revision 3.0  89/01/24  11:35:54  wolfgang
X * New System Generation
X * 
X * Revision 2.19  89/01/03  13:11:05  wolfgang
X * changes done for lint
X * 
X * Revision 2.18  88/12/21  15:03:44  wolfgang
X * changes done for lint
X * 
X * Revision 2.17  88/12/15  16:16:23  wolfgang
X * bug fixed in get_macros (segmantation violation on sissy (SUN))
X * 
X * Revision 2.16  88/11/21  20:56:56  wolfgang
X * changes done for sun
X * 
X * Revision 2.15  88/11/18  15:01:18  wolfgang
X * bug fixed: ::= indicates no longer a macrodef.
X * 
X * Revision 2.14  88/11/04  16:41:58  wolfgang
X * variant macros no are accumulated.
X * 
X * Revision 2.13  88/10/27  16:37:40  wolfgang
X * bugs fixed (new variant handling).
X * 
X * Revision 2.12  88/10/20  13:20:56  wolfgang
X * bug fixed in get_variant_macro.
X * 
X * Revision 2.11  88/10/18  17:41:12  wolfgang
X * new handling for variants implemented. macro expansion changed.
X * 
X * Revision 2.10  88/10/14  17:14:10  wolfgang
X * new procedure: get_variant_macro added and changes don for new
X * handling of variants.
X * 
X * Revision 2.9  88/10/13  12:03:24  wolfgang
X * handle_comments changed: white space is now required after #%.
X * 
X * Revision 2.8  88/09/16  13:30:57  wolfgang
X * getlin changed. In continuation lines one leading TAB is now suppressd.
X * 
X * Revision 2.7  88/09/09  11:40:31  wolfgang
X * little bug fixed.
X * 
X * Revision 2.6  88/09/08  11:57:51  wolfgang
X * handle_comments(line) improved: # are allowed in quotes.
X * 
X * Revision 2.5  88/09/08  11:48:29  wolfgang
X * handle_comments improved: kills commenmts if there are no quotes.
X * 
X * Revision 2.4  88/09/08  10:32:55  wolfgang
X * handle_comments(line) added. Now comments are allowed in rule- and
X * variant-section, respectively.
X * 
X * Revision 2.3  88/09/07  11:22:38  wolfgang
X * get_macros changed; the files are copied into a tmp file which is
X * the input file for yylex.
X * 
X * Revision 2.2  88/08/23  16:33:21  wolfgang
X * In dump() now \t is supressed for generating confid's (im macrodefinitions
X * \t is not allowed as first char.
X * 
X * Revision 2.1  88/08/19  10:17:33  wolfgang
X * This version is part of a release
X * 
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X#include "macro.h"
X#include "shape.h"
X
Xextern FILE *mkstemp();
Xextern void addhash();
Xextern char *get_variant_macro();
Xextern char *curvar[];
Xextern struct vardef *vardefs[];
Xchar *template = "/tmp/shapeXXXXXX";
XFILE *temp;
X
X
Xchar *curvpath[8] = {NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL};
Xchar *errstring;
Xint macdepth;
Xint variants_active = 0;
X
Xchar *get_next_item(string)
X     char *string;
X{
X  char *p1;
X
X  if ((p1 = index(string,' ')) != NIL)
X    {
X      *p1 = '\0';
X      return string;
X    }
X  else
X    return string;
X}
X
X
Xchar *getlin(file)
X     FILE *file;
X{
X  char line[MAXLINELENGTH];
X  char line2[MAXLINELENGTH];
X  int len = 0;
X  while (fgets(line, MAXLINELENGTH, file))   /* getc ?????  */
X    {
X      len = strlen(line);
X      while ((line[len-2] == '\\') && (line[len-1] == '\n'))
X	{
X	  line[len-2] = ' ';
X	  line[len-1] = '\0';
X	  (void) fgets(line2, MAXLINELENGTH, file);
X	  if(line2[0] == '\t')
X	    (void) strcat(line,&line2[1]);
X	  else
X	    (void) strcat(line,line2);
X	  len = strlen(line);
X	}
X      len = strlen(line);
X      line[len-1] = '\0';
X      return (line);
X    }
X/*NOTREACHED*/
X}
X
X
Xget_macros(file)
X     FILE *file;
X{
X  FILE *incfile;
X  char *line;
X  char *incp;
X  int inck;
X  char incfilename[MAXNAMLEN];
X  extern char *expandmacro();
X
X  while((line = getlin(file)) != NIL)
X    {
X
X      if((strncmp(line,INCLUDE,7)) == 0)
X	{
X	  inck = 7;
X	  while ((line[inck] == '\t') || (line[inck] == ' '))
X	    inck++;
X	  if ((incp = rindex(line+inck,' ')) != NIL)
X	    *incp = '\0';
X	  if ((incp = rindex(line+inck,'\t')) != NIL)
X	    *incp = '\0';
X	  if (index(line+inck,'$') != NIL)
X	    (void) strcpy(incfilename,expandmacro(line+inck));
X	  else
X	    (void) strcpy(incfilename,line+inck);
X	  if ((incfile = fopen(incfilename,"r")) == NULL)
X	    errexit(24,incfilename);
X	  else
X	    {
X	      get_macros(incfile);
X	      (void) fclose(incfile);
X	    }
X	}
X      else
X	{
X	  handle_comments(line);
X	  fputs(line,temp);
X	  fputs("\n",temp);
X
X	  macrodef(line);
X	}
X    }
X}
X
X
Xmacrodef(line)
X     char *line;
X{
X  char *name;
X  char *value;
X  int hashv;
X  char *p1, *p2;
X  char *enventry;
X  char *line2;
X
X  if (!line)
X    return;
X
X  if ((name = malloc(MACRONAM)) == NIL)
X    errexit(10,"malloc");
X  if((value = malloc(MACROVAL)) == NIL)
X    errexit(10,"malloc");
X  if((line2 = malloc(MAXLINELENGTH)) == NIL)
X    errexit(10,"malloc");
X  if (*line != '\t')
X    {
X      p1 = index(line,'=');
X      p2 = index(line,':');
X      
X      if ((p1 != NIL) && (*(p1-1) != ':') && (*(p1-2) != ':'))
X	{
X	  if ((p2 == NIL) || (p1 < p2))
X	    {
X	      *p1 = '\0';
X	      p2 = p1;
X	      p2--;
X	      while((*line == '\t') || (*line == ' '))
X		line++;
X	      while((*p2 == ' ') || (*p2 == '\t'))
X		*p2-- = '\0';
X	      name = line;
X	    }
X	  p1++;
X	  while((*p1 == '\t') || (*p1 == ' '))
X	    p1++;
X	  value = p1;
X	  if (strcmp(name,IMPORT) != 0)
X	    {
X#ifdef DEBUG_MACRO
Xprintf("name=#%s#\nvalue=#%s#\n\n", name, value);
X#endif DEBUG_MACRO
X	      hashv = hashval(name);
X	      addhash(hashv,name,value);
X              if (strcmp(name,"VPATH") == 0)
X		{
X		  insertvpath(value);
X		}
X            }
X	  else
X	    { 
X	      /* get environment variables */
X	      while((name = get_next_item(value)) != NIL)
X		{
X		  if (strcmp(value,"") == 0)
X		    break;
X		  value = index(value,'\0');
X		  value++;
X		  if ((enventry = getenv(name)) != NIL)
X		    {
X		      (void) strcpy(line2,name);
X		      (void) strcat(line2,"=");
X		      (void) strcat(line2,enventry);
X		      macrodef(line2);
X		    }
X		}
X	    }
X	}
X    }
X  free(name);
X  free(line2);
X  free(value);
X}
X
Xchar *expandmacro(inpstring)
X     char *inpstring;
X{
X
Xchar name[64];
Xint hashv;
Xchar *p;
Xstruct hash *current = (struct hash *) NIL;
Xint j = 0;
Xint ii = 0;
Xchar *list[100];
Xchar klazu;
Xchar *start;
Xchar newstr[MAXLINELENGTH];
Xchar *string;
Xchar *mist;
Xchar *variant_macro = NIL;
XBool dollar;
Xdollar = FALSE;
Xif (macdepth == 0)
X    errstring = inpstring;
X
Xmacdepth++;
X
Xif (macdepth == 50)
X  errexit(25, errstring);
X
Xnewstr[0] = '\0';
Xif ((string = malloc((unsigned) (strlen(inpstring) + sizeof(char)))) == NIL)
X  errexit(10,"malloc");
X(void) strcpy(string,inpstring);
Xp = string;
X
Xwhile (*p != '\0')
X  {
X    if (*p != '$')
X      {
X	if (dollar == FALSE)
X	  {
X	    list[ii] = p;
X	    ii++;
X	    dollar = FALSE;
X	  }
X  	if (ii > 100)
X	  errexit(25, errstring);
X      }
X    while ((*p != '$') && (*p != '\0'))
X      p++;
X    if ( *p == '\0')
X      break;
X    else
X      {
X	if ((*(p+1) == '(') || (*(p+1) == '{'))
X	  {
X	    klazu = ((*(p+1) == '(') ? ')':'}');
X	    *p = '\0';
X	    p = p + 2;
X	    start = p;
X
X	    while(*p != klazu)
X	      {
X		p++;
X	      }
X	    *p = '\0';
X	    (void) strcpy(name,start);
X	    p++;
X	  }
X	else
X	  {
X	    if ((*(p+1) != '@') && (*(p+1) != '?') &&
X		(*(p+1) != '<') && (*(p+1) != '*') &&
X		(*(p+1) != '$') && (*(p+1) != '+'))
X	      {
X		name[0] = *(p+1);
X		name[1] = '\0';
X		*p = '\0';
X		p = p + 2;
X	      }
X	    else
X	      {
X		name[0] = '\0';
X		dollar = TRUE; 
X		p = p + 2;
X	      }
X	  }
X	if (name[0] != '\0')
X	  {
X	    dollar = FALSE;
X
X	    if(strcmp(curvar[0],""))
X	      {
X		variant_macro = get_variant_macro(name);
X		if (strcmp(variant_macro,BLUMENKOHL))
X		  {
X		    mist = expandmacro(variant_macro);
X		    if ((list[ii] =
X			 malloc((unsigned)
X				(strlen(mist) + sizeof(char)))) == NIL)
X		      errexit(10,"malloc");
X		    (void) strcpy(list[ii],mist);
X		    ii++;
X		    if (ii > 100)
X		      errexit(25, errstring);
X		  }
X	      }
X	    if((variant_macro == NIL) || (!strcmp(variant_macro,BLUMENKOHL)))
X	      {
X		variant_macro = NIL;
X		hashv = hashval(name);
X		if (hashtab[hashv] != (struct hash *) NIL)
X		  {
X		    current = hashtab[hashv];
X		    while (((strcmp (current->name, name)) != 0) && (current->next != (struct hash *) NIL))
X		      current = current->next;
X		    
X		    if ((strcmp(current->name, name) == 0))
X		      {
X			mist = expandmacro(current->entry);
X			if ((list[ii] =
X			     malloc((unsigned) 
X				    (strlen(mist) + sizeof(char)))) == NIL)
X			  errexit(10,"malloc");
X			(void) strcpy(list[ii],mist);
X			ii++;
X			if (ii > 100)
X			  errexit(25, errstring);
X		      }
X		  }
X	      }
X	  }
X      }
X  }
Xfor (j = 0; j < ii; j++)
X     (void) strcat(newstr,list[j]);
Xmacdepth = 0;
Xreturn newstr;
X} /*end expandmacro */
X
X
X
Xhandle_comments(line)
X     char *line;
X{
X  char *p;
X  int i;
X  int q = 0;
X  int dq = 0;
X
X  if (( p = index(line,'#')) == NIL)
X    /* no comment */
X    return;
X  
X  if ((line[0] == '#') && (line[1] != '%'))
X    {
X      /* comment, starting at beginning of line */
X      line[0] = '\0';
X      return;
X    }
X
X  if (((line[0] == '#') && (line[1] == '%')) &&
X      ((line[2] == ' ') || (line[2] == '\t')))
X    return;
X  
X  if (p != NIL)
X    {
X      if((index(line,'\'') == NIL) && (index(line,'\"') == NIL))
X	/* the # is not in quotes */
X	{
X	  *p = '\0';
X	  return;
X	}
X      else
X	/* maybe no comment */
X	{
X	  for(i = 0; line[i] != '\0'; i++)
X	    {
X	      if(line[i] == '\'')
X		q++;
X	      if(line[i] == '\"')
X		dq++;
X	      if((line[i] == '#') && ((q % 2) == 0) && ((dq % 2) == 0))
X		{
X		  line[i] = '\0';
X		  return;
X		}
X	    }
X	}
X    }
X}
X
X
Xchar *get_variant_macro(name)
X     char *name;
X
X     /* get macro value for variant */
X{
Xint i = 0;
Xint k = 0;
Xint j = 0;
X
Xchar *p;
Xchar *p1;
Xchar *p2;
Xchar *p3;
X
Xchar macro[2048];
Xchar retval[1024];
X
Xretval[0] = '\0';
X
Xwhile(strcmp(curvar[i],""))
X  {
X    k = 0;
X    while (vardefs[k] != (struct vardef *) NIL)
X      {
X	if (strcmp(vardefs[k]->name,curvar[i]))
X	  k++;
X	else
X	  break;
X      }
X
X    if (vardefs[k] != (struct vardef *) NIL)
X      {
X	if ((!strcmp(name,"vpath")) && (vardefs[k]->vpath != NIL))
X	  {
X	    if (retval[0] == '\0')
X	      (void) strcat(retval, vardefs[k]->vpath);
X	    else
X	      {
X		(void) strcat(retval," ");
X		(void) strcat(retval, vardefs[k]->vpath);
X	      }
X	  }
X    
X	if ((!strcmp(name,"vflags")) && (vardefs[k]->vflags != NIL))
X	  {
X	    if (retval[0] == '\0')
X	      (void) strcat(retval,vardefs[k]->vflags);
X	    else
X	      {
X		(void) strcat(retval," ");
X		(void) strcat(retval,vardefs[k]->vflags);
X	      }
X	  }
X
X	for(j = 0; j < MAXVMACROS; j++)
X	  {
X	    if (vardefs[k]->vmacros[j] == NIL)
X	      {
X		i++;
X		break;
X	      }
X	    (void) strcpy(macro,vardefs[k]->vmacros[j]);
X	    if (!strcmp(macro,""))
X	      {
X		i++;
X		break;
X	      }
X	    p1 = index(macro,'=');
X	    p2 = index(macro,' ');
X	    p3 = index(macro,'\t');
X    
X	    if (p2 == NIL)
X	      p2 = p1 + 1;
X    
X	    if (p3 == NIL)
X	      p3 = p1 + 1;
X
X	    if (( p1 < p2) && (p1 < p3))
X	      p = p1;
X	    if (( p2 < p1) && (p2 < p3))
X	      p = p2;
X	    if (( p3 < p2) && (p3 < p1))
X	      p = p3;
X
X	    *p = '\0';
X	    p1++;
X	    
X	    if (!strcmp(name,macro))
X	      {
X		while((*p1 == ' ') || (*p1 == '\t') || (*p1 == '='))
X		  p1++;
X		if(retval[0] == '\0')
X		  (void) strcat(retval,p1);
X		else
X		  {
X		    (void) strcat(retval," ");
X		    (void) strcat(retval,p1);
X		  }
X	      }
X	  }
X      }
X    else
X      i++;
X  }
Xif(retval[0] != '\0')
X  return(retval);
Xelse
X  return(BLUMENKOHL);
X}
END_OF_FILE
if test 12566 -ne `wc -c <'src/shape/macro.c'`; then
    echo shar: \"'src/shape/macro.c'\" unpacked with wrong size!
fi
# end of 'src/shape/macro.c'
fi
if test -f 'src/vc/vadm_note.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/vc/vadm_note.c'\"
else
echo shar: Extracting \"'src/vc/vadm_note.c'\" \(12678 characters\)
sed "s/^X//" >'src/vc/vadm_note.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: vadm_note.c[3.10] Thu Feb 23 18:14:13 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/vadm_note.c[3.4]
X * 	Thu Feb 23 18:14:13 1989 axel@coma published $
X *  --- empty log message ---
X *  vadm_note.c[3.6] Thu Feb 23 18:14:13 1989 axel@coma published $
X *  --- empty log message ---
X *  vadm_note.c[3.7] Thu Feb 23 18:14:13 1989 axel@coma save $
X *  --- empty log message ---
X *  vadm_note.c[3.8] Thu Feb 23 18:14:13 1989 axel@coma save $
X *  --- empty log message ---
X *  vadm_note.c[3.9] Thu Feb 23 18:14:13 1989 axel@coma save $
X *  --- empty log message ---
X *  vadm_note.c[3.10] Thu Feb 23 18:14:13 1989 axel@coma published $
X *  --- empty log message ---
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include <afs.h>
X#include "vadm.h"
X#include "afsapp.h"
X#include "locks.h"
X#include "vc_sysdep.h"
X
X/* Externals */
Xextern int af_errno;
Xextern jmp_buf here;		/* reentrance point after we caught a sig */
Xextern char *malloc (), *getenv();
Xextern char **environment;	/* pointer to our environment */
Xextern struct Transaction ThisTransaction;
Xextern char *get_from_stdin();	/* read a text from stdin */
Xextern int call_editor();	/* returns a text */
Xextern char *FindProgram(), *FindFile();
Xextern unsigned int options;
Xextern int def_vnum;
X
X/* locals */
Xstatic char buf[100];		/* buffer for error messages */
Xstatic char *editor;		/* user's favorite editor*/
X
X/**/
Xstatic
Xint determine_defaults ()
X{
X  /*
X   * Returns 0 on error (editor not found, editor not executable, and so).
X   * 1 on success.
X   */
X  char *neweditor;
X  int ask_default = 0;		/* if env-editor is not available */
X				/* user if he/she want's default editor */
X
X  /* examine user's favorite editor, if any */
X  if ((editor = getenv (EDITOR_ENV_NAME)) == NULL)
X    editor = DEFAULT_EDITOR;
X
X  if (!index (editor, '/'))
X    if ((neweditor = FindFile (editor)) == NULL) {
X      (void)sprintf (buf, "Sorry, your favorite editor %s is not available on this machine.",
X		     editor);
X      logmsg (buf);
X      ask_default++;
X    }
X    else
X      editor = neweditor;
X  
X  /* is editor executable ? */
X  if (!ask_default && !FileExecutable (editor)) {
X   (void)sprintf (buf, "Sorry, your favorite editor %s is not executable.",
X	     editor);
X    logmsg (buf);
X    ask_default++;
X  }
X  
X  if (ask_default) {
X    /* if default editor not available resign. */
X    if (strcmp (editor, DEFAULT_EDITOR)) {
X      (void)sprintf (buf, "Do you accept default editor %s ?", DEFAULT_EDITOR);
X      if (ask_confirm (buf, "yes")) {
X	editor = DEFAULT_EDITOR;
X	if (!FileExecutable (editor)) {
X	  logmsg ("Arrg, also default editor is not available. --- I resign.");
X	  return 0;
X	}
X      }
X      else
X	return 0;		/* user doesn't want */
X    }
X    else
X      return 0;			/* default editor is not available */
X  }
X  return 1;
X}
X
X/**/
Xstatic
Xint note_ok (newnote, oldnote)
X     char *newnote, *oldnote;
X{
X  /*
X   * returns 0 if no changes detected, 1 otherwise.
X   */
X    
X  if (!newnote) {
X    if (ask_confirm ("Description is empty. Save anyway ?", "no"))
X      return 0;
X    else
X      return 1;
X  }
X      
X  if (oldnote && !strcmp (newnote, oldnote)) {
X    logmsg ("No changes detected.");
X    return 0;
X  }
X
X  /* newnote contains only layout ? */
X  while (*newnote) {
X    switch (*newnote) {
X    case ' ':
X    case '\n':
X    case '\t':
X      break;
X    default:
X      return 1;
X      break;
X    }
X    newnote++;
X  }
X
X  if (ask_confirm ("Description contains only layout. Save anyway?", "no"))
X    return 0;
X  else
X    return 1;
X}
X
X/**/
Xstatic
Xint save_it (key, note)
X     Af_key *key;
X     char *note;
X{
X  af_snote (key, note);
X  ThisTransaction.tr_done = 1;
X}
X
X/**/
Xstatic
Xint save_note_multiple (note, set)
X     char *note;
X     Af_set *set;
X{
X  int i, rc = 0;
X
X  for (i = 0 ; i < set->af_nkeys; i++) {
X    rc += af_snote (&(set->af_klist[i]), note);
X  }
X  if (note) free (note);
X  return rc;
X}
X
X/**/
Xstatic
Xint process_notes (set, change_it)
X     Af_set *set;
X     int change_it;
X{
X  int i;
X  char *note, *newnote, *mktemp();
X  int retcode;			/* retcode from editor */
X  char tmp_file[20];		/* tmp-file's name */
X  char name[MAXNAMLEN], nametype[MAXTYPLEN];
X  
X  if (!determine_defaults ())	/* that is the editor */
X    return -1;
X  
X  CatchSigs ();
X
X  /* read description per file and save if changes. */
X  for (i = 0; i < set->af_nkeys; i++) {
X
X    /* remember this location */
X    if (setjmp (ThisTransaction.tr_env)) {
X      if ( i < set->af_nkeys )
X	continue;
X      else
X	return 0;
X    }
X
X    /* construct file name */
X    (void)sprintf (nametype, "%s", af_rtype(&set->af_klist[i]));
X    (void)sprintf (name,  "%s%c%s", af_rname(&set->af_klist[i]),
X	     nametype ? '.' : NULL,
X	     nametype ? nametype : NULL);
X    
X    ThisTransaction.tr_seqno = i;
X    (void)strcpy (ThisTransaction.tr_fname, name);
X    ThisTransaction.tr_done = 0;
X      
X    /* print afsname and version */
X    (void)sprintf (buf, "%s[%d.%d]:", name, af_rgen (&set->af_klist[i]),
X	     af_rrev (&set->af_klist[i]));
X    logmsg (buf);		/* this file */
X    
X    (void)strcpy (tmp_file, mktemp ("/tmp/vctlXXXXXX"));
X
X    /* Do we change the old note ? */
X    if (change_it) {		/* get old note */
X      note = af_rnote (&set->af_klist[i]);
X
X      /* Note "Empty log message" is an empty note  */
X      if (!strcmp (note, EMPTYNOTE)) {
X	free (note);
X	note = NULL;
X      }
X    }
X    else
X      note = NULL;
X    
X    newnote = NULL;
X    retcode = call_editor (editor, tmp_file, note, &newnote);
X      
X    if (retcode == -1) {	/* editor exited abnormally */
X      if (i == (set->af_nkeys - 1)) {
X	logmsg ("Description lost.");
X	return 1;
X      }
X      
X      if (ask_confirm ("Description lost. Continue ?", "no"))
X	return 1;
X      else
X	continue;
X    }
X    
X    if (note_ok (newnote, note)) { /* any changes ? */
X      save_it (&set->af_klist[i], newnote);
X      logmsg ("Description saved.");
X    }
X    else
X      logmsg ("Description not saved.");
X    
X    if (note)
X      free (note);
X    
X    if (newnote)
X      free (newnote);
X  }
X  return 0;
X}
X
X/**/
Xprint_erroneous (erroneous, errs)
X     char **erroneous;
X     int errs;
X{
X  int i, j;
X  
X  fprintf (stderr, "No saved versions of");
X  j = 0;
X  for (i = 0; i < errs; i++) {
X    if (++j == errs)
X      if (errs == 1)
X	fprintf (stderr, " \"%s\"", erroneous[i]);
X      else
X	fprintf (stderr, " and \"%s\"", erroneous[i]);
X    else
X      fprintf (stderr, " \"%s\",", erroneous[i]);
X  }
X  fprintf (stderr, " found --- skipped\n");
X}
X
X/**/
Xstatic
Xint do_note (vlist, ac, av, change_it)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X     int change_it;
X{
X  Af_set set;
X  int errs;
X  char **erroneous;
X  
X  if (IsOptionSet(Vopt_version)) {
X    errs = GetKeysByGenRev
X	(ac,av, gen(def_vnum), rev(def_vnum), &set, 
X	 &erroneous);
X  }
X  else {
X    if (! ((vlist->from_version_set) || vlist->to_version_set))
X      errs = GetKeysByGenRev 
X	(ac,av, AF_BUSYVERS, AF_BUSYVERS, &set, &erroneous);
X    else
X      errs = GetKeysByName (ac,av, vlist, &set, &erroneous);
X  }
X  if (errs)
X    print_erroneous (erroneous, errs);
X
X  /* all given files do not exist ? */
X  if (!set.af_nkeys) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X
X  if (af_sortset (&set, AF_ATTHUMAN) == -1) {
X    af_perror ("Do_note: af_sortset AF_ATTHUMAN");
X    return 1;
X  }
X      
X  /* If stdin is redirected use text as description for *all* afs files. */
X  if (!isatty (0)) {		/* 0 == stdin */
X    /* do not append to old desc. Also we have no special term-char.
X     * Read until EOF. */
X    return save_note_multiple (get_from_stdin ((char *)NULL, -1), &set);
X  }
X  
X  /* shall we go on if an error occurs? Ask user. */
X  if (errs && (!ask_confirm ("Continue anyway ?", "yes")))
X      return 1;
X    
X  return process_notes (&set, change_it);
X}
X
X/**/
Xint DoSetNote (vlist, ac, av)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X{
X  return do_note (vlist, ac, av, 0); /* don't change existing note */
X}
X
X/**/
Xint DoChangeNote (vlist, ac, av)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X{
X  return do_note (vlist, ac, av, 1); /* change existing note */
X}
X
X/**/
Xstatic
Xint do_description (vlist, ac, av, change_it)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X     int change_it;		/* if set, append to old note */
X{
X  /*
X   * Changes an existing description note of the first version (i.e. 1.0)
X   * of an AFS file. Returns 0 on success, otherwise 1 to indicate an error.
X   */
X
X  Af_set set;
X  int errs = 0;			/* # of not found afs files */
X  char **erroneous;
X  
X  /* A version list makes no sence. Ignore it, but display warning msg. */
X  if (vlist->from_version_set || vlist->to_version_set)
X    logwng ("version specification list ignored.");
X  
X  errs = GetKeysByGenRev (ac,av, AF_FIRSTVERS, AF_FIRSTVERS, &set, 
X			  &erroneous);
X
X  if (errs)
X    print_erroneous (erroneous, errs);
X  
X  /* all given files do not exist ? */
X  if (!set.af_nkeys) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X    
X  if (af_sortset (&set, AF_ATTHUMAN) == -1) {
X    af_perror ("Do_description: af_sortset AF_ATTHUMAN");
X    return 1;
X  }
X      
X  /* If stdin is redirected use text as description for *all* afs files. */
X  if (!isatty (0)) {		/* 0 == stdin */
X    /* do not append to old desc. Also we have no special term-char.
X     * Read until EOF. */
X    return save_note_multiple (get_from_stdin ((char *)NULL, -1), &set);
X  }
X    
X  /* shall we go on if an error occurs? Ask user. */
X  if (errs && (!ask_confirm ("Continue anyway ?", "yes")))
X    return 1;
X
X  return process_notes (&set, change_it);
X}
X
X/**/
Xint DoSetDescription (vlist, ac, av)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X{
X  return do_description (vlist, ac, av, 0); /* don't change existing note */
X}
X
X/**/
Xint DoChangeDescription (vlist, ac, av)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X{
X  return do_description (vlist, ac, av, 1); /* change to old note */
X}
X
Xint DoSetIntent (ac, av) int ac; char **av; {
X  /* We must hold the lock for the history, that we wanna change. */
X  register int i;
X  int rc, rcsum = 0;
X  char fname[256], messg[80], *oldintent, *intent, *getintent(), *intattr,
X       *lockerid();
X  Af_key thiskey;
X  Af_user *locker;
X
X
X  for (i=0; i < ac; i++) {
X    if (setjmp (ThisTransaction.tr_env)) continue;
X    rc = af_getkey (af_afpath (av[i]), af_afname (av[i]), 
X		    af_aftype (av[i]), AF_BUSYVERS, AF_BUSYVERS,
X		    AF_NONAME, &thiskey);
X    if (rc < 0) {
X      (void)sprintf (messg, "can't find busy version for %s.", av[i]);
X      logerr (messg);
X      continue;
X    }
X    mkvstring (fname, &thiskey);
X    if (locked(locker=vc_testlock_v(&thiskey))) {
X      if (lockeruid (locker) == (Uid_t)getuid ()) {
X	oldintent = af_rudattr (&thiskey, INTENT);
X	intent = getintent ((char *)NULL, oldintent);
X	if (oldintent) free (oldintent);
X	intattr = malloc ((unsigned)(strlen (intent) + strlen (INTENT) +1));
X	(void)sprintf (intattr, "%s%s", INTENT, intent);
X	if (fail(af_sudattr (&thiskey, AF_REPLACE, intattr)))
X	  af_sudattr (&thiskey, AF_ADD, intattr);
X	free (intattr);
X	af_dropkey (&thiskey);
X      }
X      else {
X	(void)sprintf (messg, "Can't set intent on %s (locked by %s).",
X		 fname, lockerid (locker));
X	logerr (messg);
X	af_dropkey (&thiskey);
X	rcsum++;
X	continue;
X      }
X    }
X    else {
X      (void)sprintf (messg, "You must have a lock on %s to set change intention.", 
X	       fname);
X      logerr (messg);
X      af_dropkey (&thiskey);
X      rcsum++;
X      continue;
X    }
X  }
X  return rcsum;
X}    
X	
END_OF_FILE
if test 12678 -ne `wc -c <'src/vc/vadm_note.c'`; then
    echo shar: \"'src/vc/vadm_note.c'\" unpacked with wrong size!
fi
# end of 'src/vc/vadm_note.c'
fi
if test -f 'src/vc/vadm_reserve.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/vc/vadm_reserve.c'\"
else
echo shar: Extracting \"'src/vc/vadm_reserve.c'\" \(12489 characters\)
sed "s/^X//" >'src/vc/vadm_reserve.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: vadm_reserve.c[3.13] Thu Feb 23 18:14:17 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/vadm_reserve.c[3.7]
X * 	Thu Feb 23 18:14:17 1989 axel@coma published $
X *  --- empty log message ---
X *  vadm_reserve.c[3.9] Thu Feb 23 18:14:18 1989 axel@coma published $
X *  --- empty log message ---
X *  vadm_reserve.c[3.11] Thu Feb 23 18:14:18 1989 axel@coma published $
X *  --- empty log message ---
X *  vadm_reserve.c[3.12] Thu Feb 23 18:14:18 1989 axel@coma save $
X *  --- empty log message ---
X *  vadm_reserve.c[3.13] Thu Feb 23 18:14:18 1989 axel@coma published $
X *  --- empty log message ---
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <pwd.h>
X#include <stdio.h>
X#include <strings.h>
X
X#include "afs.h"
X#include "vadm.h"
X#include "afsapp.h"
X#include "locks.h"
X
X/* externals */
Xextern char *malloc();
Xextern int newmode;
Xextern Af_user newauthor;
Xextern int def_vnum;
Xextern struct Transaction ThisTransaction;
X
X/* forward */
Xchar *uidname ();
X
X/* locals */
Xstatic char buf[2048];
X
X/**/
XUid_t af_MY_rouid (key) Af_key *key; {
X  /*
X   *  This function returns the userid of the owner of the AFS directory
X   *  containing the AFS object identified by key.
X   */
X  char path[256];
X  struct stat statbuf;
X
X  (void)strcpy (path, af_rsyspath (key));
X  if (strcmp (path, "/") == NULL)
X    (void)strcpy (path, "");
X  (void)strcat (path, "/AFS");
X  if (stat (path, &statbuf) < 0) {
X    perror (path);
X    return -1;
X  }
X  return statbuf.st_uid;
X}
X
Xint do_reserve (set)
X     Af_set *set;
X{
X  register int i;
X  Af_user *locker;
X  int errs = 0;
X  char version[1024], *fn, *mkfn(), *p, *lockerid();
X  struct stat sbuf;
X
X  if (af_sortset (set, AF_ATTHUMAN) == -1)
X    vctl_abort ("do_reserve: af_sortset()");
X      
X  for (i = 0; i < set->af_nkeys; i++) {
X    mkvstring (version, &set->af_klist[i]);
X    if (setjmp (ThisTransaction.tr_env)) continue;
X    /* if (locking == AF_GLOBALLOCK) { /* to be implemented */
X    if (p=rindex(version, '[')) *p = '\0';
X    
X    if (!locked(locker = vc_testlock_g(&set->af_klist[i]))) {
X      logmsg ("WARNING! Administrative locking may lose attribute citations.");
X      if (vc_lock_g(&set->af_klist[i], (Uid_t)geteuid()) == (Af_user *)NULL) {
X	af_perror ("af_lock");
X	continue;
X      }
X      else {
X	if (af_rstate (&set->af_klist[i]) == AF_BUSY) {
X	  char *intent, *getintent();
X	  extern unsigned int options;
X	  if (!IsOptionSet (Vopt_quiet)) {
X	    intent = getintent ("Describe intended changes ?", (char *)NULL);
X	  }
X	  else intent = (char *)NULL;
X	  if (intent) {
X	    char *intattr;
X	    intattr = malloc ((unsigned)(strlen (intent) + 
X					 strlen (INTENT) +1));
X	    (void)sprintf (intattr, "%s%s", INTENT, intent);
X	    if (fail(af_sudattr (&set->af_klist[i], AF_REPLACE, intattr)))
X	       af_sudattr (&set->af_klist[i] , AF_ADD, intattr);
X	    free (intattr);
X	  }
X	}
X	(void)sprintf (buf, "%s reserved.", version);
X	fn = mkfn (&set->af_klist[i]);
X	if (stat (fn, &sbuf) == 0) {
X	  (void)chmod (fn, (int)(sbuf.st_mode | 0200));
X	}
X	logmsg (buf);
X      }
X    }
X    else { /* testlock returned something */
X      if (lockeruid(locker) != (Uid_t)geteuid()) {
X	(void)sprintf (buf, "%s is already locked by %s.", version, 
X		 lockerid (locker));
X	logmsg (buf);
X	errs++;
X	continue;
X      }
X      else {
X	(void)sprintf (buf, "%s reserved.", version);
X	fn = mkfn (&set->af_klist[i]);
X	if (stat (fn, &sbuf) == 0) {
X	  (void)chmod (fn, (int)(sbuf.st_mode | 0200));
X	}
X	logmsg (buf);
X      }
X    }
X  }
X  if (errs)
X    return 1;
X  else
X    return 0;
X}
X
Xint do_chmod (set)
X     Af_set *set;
X{
X  int i;
X  int errs = 0;
X  char version[1024];
X  
X  if (af_sortset (set, AF_ATTHUMAN) == -1)
X    vctl_abort ("do_chmod: af_sortset()");
X      
X  for (i = 0; i < set->af_nkeys; i++) {
X    mkvstring (version, &set->af_klist[i]);
X    if (setjmp (ThisTransaction.tr_env)) continue; 
X    if (af_MY_rouid (&set->af_klist[i]) != (Uid_t)geteuid()) {
X      (void)sprintf (buf, "%s not owned by %s.", version, 
X	       uidname((Uid_t)geteuid()));
X      logmsg (buf);
X      errs++;
X      continue;
X    }
X    else {
X      if (af_chmod (&set->af_klist[i], newmode) < 0) {
X	af_perror ("af_chmod");
X	errs++;
X	continue;
X      }
X      (void)sprintf (buf, "%s done.", version);
X      logmsg (buf);
X    }
X  }
X  if (errs)
X    return 1;
X  else
X    return 0;
X}
X
Xint do_chown (set)
X     Af_set *set;
X{
X  int i;
X  int errs = 0;
X  char version[1024];
X  
X  if (af_sortset (set, AF_ATTHUMAN) == -1)
X    vctl_abort ("do_chown: af_sortset()");
X      
X  for (i = 0; i < set->af_nkeys; i++) {
X    mkvstring (version, &set->af_klist[i]);
X    if (setjmp (ThisTransaction.tr_env)) continue; 
X    if (lockeruid (af_rowner (&set->af_klist[i])) != geteuid()) {
X      (void)sprintf (buf, "%s not owned by %s.", version, 
X	       uidname (geteuid()));
X      logmsg (buf);
X      errs++;
X      continue;
X    }
X    else {
X      logmsg ("This function is not available under BSD.");
X      errs++;
X      continue;
X    }
X  }
X  if (errs)
X    return 1;
X  else
X    return 0;
X}
X
Xint do_chaut (set)
X     Af_set *set;
X{
X  int i;
X  int errs = 0;
X  char version[1024];
X  
X  if (af_sortset (set, AF_ATTHUMAN) == -1)
X    vctl_abort ("do_chaut: af_sortset()");
X      
X  for (i = 0; i < set->af_nkeys; i++) {
X    mkvstring (version, &set->af_klist[i]);
X    if (setjmp (ThisTransaction.tr_env)) continue; 
X    if (af_MY_rouid (&set->af_klist[i]) != (Uid_t)geteuid()) {
X      (void)sprintf (buf, "%s not owned by %s.", version, 
X	       uidname ((Uid_t)geteuid()));
X      logmsg (buf);
X      errs++;
X      continue;
X    }
X    else {
X      if (af_chauthor (&set->af_klist[i], &newauthor) < 0) {
X	af_perror ("af_chaut");
X	errs++;
X	continue;
X      }
X      (void)sprintf (buf, "%s done.", version);
X      logmsg (buf);
X    }
X  }
X  if (errs)
X    return 1;
X  else
X    return 0;
X}
X
X/**/
XDoReserve (ac, av)
X     int ac;
X     char **av;
X{
X  Af_set set;
X  int errs, errput = 0;
X  char **erroneous;
X
X  errs = GetKeysByGenRev (ac,av, AF_BUSYVERS, AF_BUSYVERS, &set, 
X			  &erroneous);
X
X  if (errs) {
X    print_erroneous (erroneous, errs);
X    errput++;
X  }
X
X  if (!set.af_nkeys && !errput) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X
X  if (errs && !ask_confirm ("Continue ?", "yes"))
X    return 1;
X
X  return do_reserve (&set);
X}
X
Xint do_unreserve (set)
X     Af_set *set;
X{
X  int i;
X  Af_user *locker;
X  int errs = 0;
X  char version[1024];
X  char *p;
X  FILE *pip;
X
X  if (af_sortset (set, AF_ATTHUMAN) == -1)
X    vctl_abort ("do_promote: af_sortset()");
X  for (i = 0; i < set->af_nkeys; i++) {
X    mkvstring (version, &set->af_klist[i]);
X    if (setjmp (ThisTransaction.tr_env)) continue;
X    /* if (locking == AF_GLOBALLOCK) { /* to be implemented */
X    if (p=rindex(version, '[')) *p = '\0';
X    if (!locked(locker = af_testlock (&set->af_klist[i], AF_GLOBALLOCK))) {
X      (void)sprintf (buf, "%s unlocked.", version);
X      logmsg (buf);
X      continue;
X    }
X    if (lockeruid (locker) == geteuid()) {
X      (void)vc_unlock_g(&set->af_klist[i]);
X      (void)sprintf (buf, "%s unlocked.", version);
X      logmsg (buf);
X      continue;
X    }
X    else { /* locked by somebody else */
X      /* The following is an evil hack. BSD doesn't allow chmod(2)
X       * for ordinary user processes. 
X       */
X      if (af_MY_rouid (&set->af_klist[i]) == geteuid()) { 
X	/* we've got the power ... */
X	(void)sprintf (buf, "%s currently locked by %s. Break the lock ?", version,
X		 lockerid (locker));
X	if (ask_confirm (buf, "yes")) {
X	  if (vc_unlock_g(&set->af_klist[i]) == NULL) {
X	    af_perror ("af_unlock");
X	    continue;
X	  }
X	  (void)sprintf (buf, MAIL, version, uidname(geteuid()));
X	  (void)strcat (buf, lockerid (locker));
X	  if ((pip = popen (buf, "w")) == NULL) {
X	    logmsg ("WARNING: couldn't notify lockholder...");
X	  }
X	  else {
X	    fprintf (pip, "This message was issued automatically by ");
X	    fprintf (pip, "the version control system.\n");
X	    fprintf (pip, "Your lock on %s was broken by %s.\n",
X		     version, uidname(geteuid()));
X	    (void)pclose (pip);
X	  }
X	  (void)sprintf (buf, "%s unlocked.", version);
X	  logmsg (buf);
X	  continue;
X	}
X	else { /* we don't wanna break the lock */
X	  (void)sprintf (buf, "%s remains locked by %s.", version, 
X		   lockerid (locker));
X	  logmsg (buf);
X	  continue;
X	}
X      }
X      else { /* we cannot unlock the required version */
X	(void)sprintf (buf, "%s is locked by %s.", version, lockerid (locker));
X	logmsg (buf);
X	errs++;
X	continue;
X      }
X    }
X  }
X  if (errs)
X    return 1;
X  else
X    return 0;
X}
X
X/**/
XDoUnreserve (ac, av)
X     int ac;
X     char **av;
X{
X  Af_set set;
X  int errs;
X  char **erroneous;
X
X  errs = GetKeysByGenRev (ac,av, AF_BUSYVERS, AF_BUSYVERS, &set, 
X			  &(erroneous));
X
X  if (errs)
X    print_erroneous (erroneous, errs);
X
X  if (!set.af_nkeys) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X
X  if (errs && !ask_confirm ("Continue ?", "yes"))
X    return 1;
X
X  return do_unreserve (&set);
X}
X
XDoChmod (vlist, ac, av)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X{
X  Af_set set;
X  int errs;
X  char **erroneous;
X
X  if (IsOptionSet(Vopt_version)) {
X    errs = GetKeysByGenRev
X	(ac,av, gen(def_vnum), rev(def_vnum), &set, &erroneous);
X  }
X  else {
X    if (!(vlist->from_version_set) || !(vlist->to_version_set))
X      errs = GetKeysByGenRev 
X	(ac,av, AF_BUSYVERS, AF_BUSYVERS, &set, &erroneous);
X    else
X      errs = GetKeysByName ( ac, av, vlist, &set, &erroneous);
X  }
X  if (errs)
X    print_erroneous (erroneous, errs);
X
X  if (!set.af_nkeys) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X
X  if (errs && !ask_confirm ("Continue ?", "yes"))
X    return 1;
X
X  return do_chmod (&set);
X}
X
XDoChown (ac, av)
X     int ac;
X     char **av;
X{
X  Af_set set;
X  int errs;
X  char **erroneous;
X
X  errs = GetKeysByGenRev (ac,av, AF_BUSYVERS, AF_BUSYVERS, &set, 
X			  &erroneous);
X
X  if (errs)
X    print_erroneous (erroneous, errs);
X
X  if (!set.af_nkeys) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X
X  if (errs && !ask_confirm ("Continue ?", "yes"))
X    return 1;
X
X  return do_chown (&set);
X}
X
XDoChaut (vlist, ac, av)
X     struct vc_vlist *vlist;
X     int ac;
X     char **av;
X{
X  Af_set set;
X  int errs;
X  char **erroneous;
X
X  if (IsOptionSet(Vopt_version)) {
X    errs = GetKeysByGenRev
X	(ac,av, gen(def_vnum), rev(def_vnum), &set, &erroneous);
X  }
X  else {
X    if (!(vlist->from_version_set) || !(vlist->to_version_set))
X      errs = GetKeysByGenRev 
X	(ac,av, AF_LASTVERS, AF_LASTVERS, &set, &erroneous);
X    else
X      errs = GetKeysByName ( ac, av, vlist, &set, &erroneous);
X  }
X  if (errs)
X    print_erroneous (erroneous, errs);
X
X  if (!set.af_nkeys) {
X    logmsg ("Nothing appropriate found.");
X    return 1;
X  }
X
X  if (errs && !ask_confirm ("Continue ?", "yes"))
X    return 1;
X
X  return do_chaut (&set);
X}
X
Xchar *mkfn (key) Af_key *key; {
X  /* construct a unix (busy-)filename for object pointed to by key */
X  static char name[128];
X  char *n, *t;
X
X  name[0] = '\0';
X  t = af_rtype (key); t = *t ? t : NULL;
X  (void)sprintf (name, "%s%s%s", n=af_rname (key), t ? "." : "", t ? t : "");
X  free (n); free (t);
X  return name;
X}
X
Xchar *uidname (uid) Uid_t uid; {
X  struct passwd *pwent = getpwuid ((int)uid);
X  char un[80];
X
X  if (pwent == NULL) {
X    (void)sprintf (un, "somebody (uid=%d)", uid);
X    return un;
X  }
X  else return pwent->pw_name;
X}
X
END_OF_FILE
if test 12489 -ne `wc -c <'src/vc/vadm_reserve.c'`; then
    echo shar: \"'src/vc/vadm_reserve.c'\" unpacked with wrong size!
fi
# end of 'src/vc/vadm_reserve.c'
fi
echo shar: End of archive 14 \(of 33\).
cp /dev/null ark14isdone
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.