[comp.sources.unix] v19i031: A software configuration management system, Part18/33

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

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



#! /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 18 (of 33)."
# Contents:  src/afs/aflib.c src/afs/afretr.c src/afsit/rcsit.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:10 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/afs/aflib.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/afs/aflib.c'\"
else
echo shar: Extracting \"'src/afs/aflib.c'\" \(16973 characters\)
sed "s/^X//" >'src/afs/aflib.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 *	aflib.c -- Miscellaneous functions
X *
X *	Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X *					  (andy@db0tui62.BITNET)
X *
X *	$Header: aflib.c[1.6] Wed Feb 22 16:27:41 1989 andy@coma published $
X *
X *	EXPORT:
X *
X *      af_errno -- global variable holding the actual error code
X *	af_serr -- report error without writing error protocol
X *	af_err -- write error protocol
X *	af_wng -- print out warning message
X *      af_perror -- print AFS-error
X *      af_regtmpfile -- register tmp file
X *      af_unregtmpfile -- unregister tmp file
X *      af_reglckfile -- register lock file
X *      af_cpfile -- copy files
X *      af_cleanup -- do cleanup (e.g. upon signal)
X *      af_malloc -- allocate memory
X *      af_realloc -- reallocate memoty
X *      af_free -- free allocated memory segment
X *      af_frmemlist -- free list of allocated memory segments
X *      af_bsearch -- binary search on ordered list of strings
X *      af_checkread -- check read permissions of AF-file
X *      af_checkperm -- check access permissions for AF-file
X */
X
X#include <stdio.h>
X#include <string.h>
X#ifdef SUNOS_4_0
X#include <strings.h>
X#endif
X#ifdef SYSLOG
X#include <syslog.h>
X#endif
X
X#include "typeconv.h"
X#include "afsys.h"
X#include "afs.h"
X#include "afarchive.h"
X
X#ifdef MEMDEBUG
Xextern FILE *memprot;
X#endif
X#ifdef TMPDEBUG
Xextern FILE *tmpprot;
X#endif
X
Xchar  *getlogin();
X
X/*=========================================================================
X *     af_serr -- report error without writing error protocol
X *
X *=========================================================================*/
X
Xextern int errno;
X
XEXPORT int af_errno, af_nodiag = FALSE;
X
XEXPORT void af_serr (routine, called, errcd)
X     char  *routine;
X     char  *called;
X     int   errcd;
X{
X  af_nodiag = TRUE;
X  af_err (routine, called, errcd);
X  af_nodiag = FALSE;
X}    
X
X/*=========================================================================
X *     af_err -- write error protocol
X *
X *=========================================================================*/
X
Xstatic char diagstr[265]; /* for diagnistics of AF_EMISC */
X
Xstatic char *errors[] = 
X  {
X    "", "", "",
X    "permission denied",				/*  3 */
X    "archive file has changed since last read",		/*  4 */
X    "archive file is locked for writing",		/*  5 */
X    "no additional space in binary pool",		/*  6 */
X    "specified revision must not be a busy version",	/*  7 */
X    "specified revision is a derived object",		/*  8 */
X    "illegal format of var or uda string",		/*  9 */
X    "invalid key",					/* 10 */
X    "invalid set",					/* 11 */
X    "invalid user",					/* 12 */
X    "bad version number",				/* 13 */
X    "invalid location of archive",			/* 14 */
X    "miscellaneous errors",				/* 15 */
X    "invalid mode",					/* 16 */
X    "AFS subdirectory missing or not writable",		/* 17 */
X    "key does not exist in set",			/* 18 */
X    "invalid position in set",				/* 19 */
X    "specified revision does not exist",		/* 20 */
X    "specified object is no busy version",		/* 21 */
X    "specified object is no derived object",		/* 22 */
X    "version is not locked or locked by someone else",	/* 23 */
X    "specified object is no regular file",		/* 24 */
X    "specified object has no versions",			/* 25 */
X    "user defined attribute does not exist",		/* 26 */
X    "saved versions cannot be modified",		/* 27 */
X    "invalid state transition",				/* 28 */
X    "string too long",					/* 29 */
X    "too many user defined attributes",			/* 30 */
X    "wrong state",					/* 31 */
X    "error during delta operation",			/* 32 */
X    "Archive file inconsistent",			/* 33 */
X    "internal error",					/* 34 */
X    "no AFS file",					/* 35 */
X  };
X
X
XEXPORT void af_err (routine, called, errcd)
X     char  *routine;
X     char  *called;
X     int   errcd;
X{
X#ifndef SYSLOG
X  FILE *errfile;
X  char *af_asctime();
X#endif
X
X  if (af_nodiag)
X    {
X      af_errno = errcd;
X      if (af_errno == AF_EMISC)
X	(void) strcpy (diagstr, called);
X      return; /* do nothing */
X    }
X
X#ifdef SYSLOG
X  if (!openlog ("AFS", LOG_PID, LOG_LOCAL1))
X#else
X  if ((errfile = fopen (AF_ERRLOG, "a")) == (FILE *)0)
X#endif
X    {
X      fprintf (stderr, "AFS: cannot open Error-logfile\n");
X      return;
X    }
X  (void) chmod (AF_ERRLOG, 0666);
X
X#ifdef SYSLOG
X  switch (errcd)
X    {
X    case AF_ESYSERR: syslog (LOG_ERR, "%s called af_%s: %s error in %s (%m)", 
X			     getlogin(), routine, errors [abs(errcd)], called);
X                     break;
X    case AF_EINCONSIST:
X    case AF_ENOAFSFILE:
X    case AF_EINTERNAL: syslog (LOG_ERR, "%s called af_%s: %s (%s)", getlogin(),
X			       routine, errors [abs(errcd)], called);
X                      break;
X    case AF_EMISC: syslog (LOG_ERR, "%s called af_%s: %s ", getlogin(),
X			   routine, called);
X                   (void) strcpy (diagstr, called);
X                   break;
X    default: syslog (LOG_ERR, "%s called af_%s: %s", getlogin(), 
X		     routine, errors [abs(errcd)]);
X    }
X#else
X  fprintf (errfile, "%s pid[%d] %s",af_gethostname(),getpid (), af_asctime ());
X  switch (errcd)
X    {
X    case AF_ESYSERR: fprintf (errfile, "\t%s called af_%s: %s error in %s\n", 
X			     (char *) getlogin(), routine, errors [abs(errcd)], called);
X                     break;
X    case AF_EINCONSIST:
X    case AF_ENOAFSFILE:
X    case AF_EINTERNAL: fprintf (errfile, "\t%s called af_%s: %s (%s)\n", (char *) getlogin(), routine, errors [abs(errcd)], called);
X                       break;
X    case AF_EMISC: fprintf (errfile, "\t%s called af_%s: %s\n", (char *) getlogin(), routine, called);
X                   (void) strcpy (diagstr, called);
X                   break;
X    default: fprintf (errfile, "\t%s called af_%s: %s\n", (char *) getlogin(), routine, errors [abs(errcd)]);
X    }
X#endif
X
X#ifdef SYSLOG
X  closelog ();
X#else
X  (void) fclose (errfile);
X#endif
X
X  af_errno = errcd;
X  return;
X}
X
X/*=========================================================================
X *     af_wng -- write warning to error protocol
X *
X *=========================================================================*/
X
XEXPORT void af_wng (routine, comment)
X     char  *routine, *comment;
X{
X#ifndef SYSLOG
X  FILE *errfile;
X  char *af_asctime();
X#endif
X
X#ifdef SYSLOG
X  if (!openlog ("AFS", LOG_PID, LOG_LOCAL1))
X#else
X  if ((errfile = fopen (AF_ERRLOG, "a")) == (FILE *)0)
X#endif
X    {
X      fprintf (stderr, "AFS: cannot open Error-logfile\n");
X      return;
X    }
X  (void) chmod (AF_ERRLOG, 0666);
X
X#ifdef SYSLOG
X  syslog (LOG_WARNING, "%s called af_%s: %s", getlogin(), routine, comment);
X#else
X  fprintf (errfile, "%s pid[%d] %s", af_gethostname(), getpid (), af_asctime ());
X  fprintf (errfile, "\t%s called af_%s: %s\n", (char *) getlogin(), routine, comment);
X#endif
X
X#ifdef SYSLOG
X  closelog ();
X#else
X  (void) fclose (errfile);
X#endif
X  return;
X}
X
X
X/*=========================================================================
X *     af_perror -- print AFS-error message
X *
X *=========================================================================*/
X
XEXPORT void af_perror (string)
X     char  *string;
X{
X  switch (af_errno)
X    {
X    case AF_ESYSERR: perror (string);
X                     break;
X    case AF_EMISC: fprintf (stderr, "%s: %s\n", string, diagstr);
X                  break;
X    default: fprintf (stderr, "%s: %s\n", string, errors [abs(af_errno)]);
X    }
X}
X
X/**************************************************************************/
X
X/*================================================================
X *      list of tmp files
X *
X *================================================================*/
X
Xstatic char *tmpfilelist[NOFILE];
X
XLOCAL void rmtmpfiles ()
X{
X  register i;
X
X  for (i=0; i < NOFILE; i++)
X    if (tmpfilelist[i] != (char *)0)
X      (void) af_unlink (tmpfilelist[i]);
X}
X
XEXPORT void af_regtmpfile (name) /* registrate tmp file */
X     char *name;
X{
X  register int i;
X
X#ifdef TMPDEBUG
X  fprintf (tmpprot, "TMP: register %s\n", name);
X#endif
X  /* look for free space in list */
X  for (i=0; i < NOFILE; i++)
X    if (tmpfilelist[i] == (char *)0)
X      {
X	tmpfilelist[i] = name;
X	break;
X      }
X  if (i == NOFILE) /* list is full */
X    af_wng ("regtmpfile", "tmpfile list is full -- couldn't register");
X}
X
XEXPORT void af_unregtmpfile (name) /* remove tmp file entry */
X     char *name;
X{
X  register i;
X#ifdef TMPDEBUG
X  fprintf (tmpprot, "TMP: unregister %s\n", name);
X#endif
X  for (i=0; i < NOFILE; i++)
X    if (tmpfilelist[i] == name)
X      {
X	tmpfilelist[i] = (char *)0;
X	break;
X      }
X  if (i == NOFILE) /* name not found */
X    af_wng ("unregtmpfile", "name of tmpfile has not been registered before");
X}  
X
X/*=========================================================================
X *     af_reglckfile -- register lock file
X *
X *=========================================================================*/
X
Xstatic char *lckfilename;
X
XEXPORT af_reglckfile (name)
X     char *name;
X{
X  lckfilename = af_entersym (name);
X}
X
XLOCAL rmlckfiles ()
X{
X  (void) unlink (lckfilename);
X}
X
X/*=========================================================================
X *     af_cpfile -- copy files
X *
X *=========================================================================*/
X
XEXPORT af_cpfile (source, size, dest)
X     char *source;
X     off_t size;
X     char *dest;
X{
X  char   cont[BUFSIZ];
X  int    bufsiz = BUFSIZ;
X  FILE   *sfile, *dfile;
X  
X  if ((sfile = fopen (source, "r")) == (FILE *)0)
X    {
X      free (cont);
X      return (ERROR);
X    }
X  if ((dfile = fopen (dest, "w")) == (FILE *) 0)
X    {
X      free (cont);
X      (void) fclose (sfile);
X      return (ERROR);
X    }
X
X  while (size > 0)
X    {
X      if (size >= BUFSIZ)
X	size -= BUFSIZ;
X      else
X	{
X	  bufsiz = size;
X	  size = 0;
X	}
X      if (!fread (cont, sizeof(char), bufsiz, sfile))
X	{
X	  (void) fclose (sfile);
X	  (void) fclose (dfile);
X	  return (ERROR);
X	}
X      if (!fwrite (cont, sizeof(char), bufsiz, dfile))
X	{
X	  (void) fclose (sfile);
X	  (void) fclose (dfile);
X	  return (ERROR);
X	}
X    }
X
X  (void) fclose (sfile);
X  (void) fclose (dfile);
X  return (AF_OK);
X}
X
X
X/**************************************************************************/
X
X/*=========================================================================
X *     af_cleanup -- do cleanup
X *
X *=========================================================================*/
X
XEXPORT af_cleanup ()
X{
X  /* remove tmp files */
X  rmtmpfiles ();
X  rmlckfiles ();
X}
X
X/*=========================================================================
X *     af_malloc -- allocate memory and registrate it
X *     af_realloc -- reallocate memory and registrate it
X *
X * all memory allocated for data in an archive is preceeded by a pointer
X * pointing to the prevoiusly allocated memory segment.
X * So we get a chain of allocated memory segments.
X * ( probably not portable )
X *
X *=========================================================================*/
X
XEXPORT char *af_malloc (list, size)
X     Af_revlist *list;
X     unsigned   size;
X{
X  char **mem, *malloc();
X
X  if ((mem = (char **)malloc ((unsigned) (size + sizeof (mem)))) == (char **)0)
X    return (char *)0;
X#ifdef MEMDEBUG
X      fprintf (memprot, "%x (alloc) %d bytes\n", mem, size + sizeof (mem));
X#endif
X
X  *mem = list->af_mem;
X  list->af_mem = (char *)mem;
X
X  mem++; /* increment by sizeof ptr */
X
X  return ((char *)mem);
X}
X
X
XEXPORT char *af_realloc (list, ptr, size)
X     Af_revlist *list;
X     char       *ptr;
X     unsigned   size;
X{
X  char **mem, **segptr, **nextptr, *realloc();
X
X  if ((mem = (char **)realloc (ptr, (unsigned) (size + sizeof (mem)))) == (char **)0)
X    return (char *)0;
X#ifdef MEMDEBUG
X      fprintf (memprot, "realloc: old - %x , new - %x %d bytes\n", ptr, mem, size + sizeof (mem));
X#endif
X
X  if ((char *)mem == ptr - sizeof ((char *)0)) /* no registration necessary */
X    return ((char *)mem);
X
X  segptr = &(list->af_mem); /* remove the implicitely freed memory segment */
X  while (*segptr != ptr - sizeof ((char *)0))
X    segptr = (char **)*segptr;
X  nextptr = (char **)*segptr;
X  *segptr = *nextptr;
X
X  *mem = list->af_mem; /* registrate new segment */
X  list->af_mem = (char *)mem;
X
X  mem++; /* increment by sizeof ptr */
X
X  return ((char *)mem);
X}
X
XEXPORT void af_free (list, ptr)
X     Af_revlist *list;
X     char       *ptr;
X{
X  char **segptr, **nextptr;
X
X#ifdef MEMDEBUG
X      fprintf (memprot, "%x (free)\n", ptr - sizeof ((char *)0));
X#endif
X  free (ptr - sizeof ((char *)0));
X
X  segptr = &(list->af_mem); /* remove memory segment from registration list */
X  while (*segptr != ptr - sizeof ((char *)0))
X    segptr = (char **)*segptr;
X  nextptr = (char **)*segptr;
X  *segptr = *nextptr;
X}
X
X
XEXPORT void af_frmemlist (list)
X     Af_revlist *list;
X{
X  char **ptr;
X
X  ptr = &(list->af_mem);
X  while ((char *)*ptr)
X    {
X#ifdef MEMDEBUG
X      fprintf (memprot, "%x (free)\n", *ptr);
X#endif
X      free (*ptr);
X      ptr = (char **)*ptr;
X    }
X  list->af_mem = (char *)0;
X}
X
X/*========================================================================
X * af_bsearch -- do binary search on ordered list of strings
X *               returns position (-1 if target not found)
X *
X *========================================================================*/
X
XEXPORT af_bsearch (list, size, target)
X     char **list;
X     int  size;
X     char *target;
X{
X  int hi = size-1, lo=0, pos, res;
X
X  pos = (hi+lo)/2;
X  while (hi >= lo)
X    {
X      if ((res = strcmp (target, list[pos])) == 0)
X	return (pos);
X      else
X	{	  
X	  if (res < 0)
X	    hi = pos - 1;
X	  else /* res > 0 */
X	    lo = pos + 1;
X	  pos = (hi+lo)/2;
X	}
X    }
X  /* the target string was not found */
X  return (ERROR);
X}
X
X
X/*====================================================================
X *   af_checkread -- see if AF-file is readable
X *
X *====================================================================*/
X
XEXPORT af_checkread (key)
X     Af_key *key;
X{
X  Uid_t uid, auuid, ownuid;
X  Gid_t augid, owngid;
X  int   i, ngroups, gidset[NGROUPS];
X
X  if ((VATTR(key).af_mode & 0004) == 0004) /* readable for world */
X    return (AF_OK);
X
X  if ((VATTR(key).af_mode & 0040) == 0040) /* readable for group */
X    {
X      /* this then part is BSD specific */
X      ngroups = getgroups (NGROUPS, gidset);
X      augid = af_getgid (VATTR(key).af_auname, VATTR(key).af_auhost);
X      owngid = af_getgid (CATTR(key).af_ownname, CATTR(key).af_ownhost);
X      for (i=0; i < ngroups; i++)
X	{
X	  if ((augid == (Gid_t)gidset[i]) || (owngid == (Gid_t)gidset[i]))
X	    return (AF_OK);
X	}
X    }
X
X  if ((VATTR(key).af_mode & 0400) == 0400) /* readable by owner */
X    {
X      uid = getuid();
X      auuid = af_getuid (VATTR(key).af_auname, VATTR(key).af_auhost);
X      ownuid = af_getuid (CATTR(key).af_ownname, CATTR(key).af_ownhost);
X      if ((auuid == uid) || (ownuid == uid))
X	return (AF_OK);
X    }
X
X  return (ERROR);
X}
X
X
X/*====================================================================
X *   af_checkperm -- check access permissions for AF-file
X *
X *====================================================================*/
X
XEXPORT af_checkperm (key, mode)
X     Af_key *key;
X     int    mode;
X{
X  Uid_t uid = getuid(), lockeruid;
X  bool ok = FALSE;
X
X  if (mode & AF_OWNER)
X    {
X      if (uid == af_getuid (CATTR(key).af_ownname, CATTR(key).af_ownhost))
X	ok = TRUE;
X    }
X  if (!ok && (mode & AF_LOCKHOLDER))
X    {
X      if ((lockeruid = af_getuid (VATTR(key).af_lckname, 
X				  VATTR(key).af_lckhost)) == uid)
X	ok = TRUE;
X      else
X	{
X	  /* if object is locked by someone else */
X	  if (lockeruid != (Uid_t) ERROR) 
X	    goto exit;
X	}
X    }
X  if (!ok && (mode & AF_AUTHOR))
X    {
X      if (uid == af_getuid (VATTR(key).af_auname, VATTR(key).af_auhost))
X	ok = TRUE;
X    }
X  if (!ok && (mode & AF_WORLD))
X    {
X      ok = TRUE;
X    }
X  
X exit:
X  /* if access is not ok, or AFS subdir is not writable */
X  if (!ok)
X    SFAIL ("checkperm", "", AF_EACCES, ERROR);
X  if (!(key->af_ldes->af_extent & AF_UXWRITE))
X    SFAIL ("checkperm", "", AF_ENOAFSDIR, ERROR);
X  return (AF_OK);
X}
END_OF_FILE
if test 16973 -ne `wc -c <'src/afs/aflib.c'`; then
    echo shar: \"'src/afs/aflib.c'\" unpacked with wrong size!
fi
# end of 'src/afs/aflib.c'
fi
if test -f 'src/afs/afretr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/afs/afretr.c'\"
else
echo shar: Extracting \"'src/afs/afretr.c'\" \(16910 characters\)
sed "s/^X//" >'src/afs/afretr.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 *	afretr.c - retrieve interface 
X *
X *	Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP
X *					   andy@db0tui62.BITNET)
X *
X *	$Header: afretr.c[1.4] Wed Feb 22 16:27:50 1989 andy@coma published $
X *
X *	EXPORT:
X *	af_bpfind -- find derived files by attributes
X *	af_find -- find source files by attributes
X *	af_getkey -- find single file by unique attributes
X *	af_dropkey -- release memory associated with filekey 
X *	af_initattrs -- initialize attribute buffer
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/* #include <sys/dir.h> */
X
X#include "typeconv.h"
X#include "afsys.h"
X#include "afs.h"
X#include "afarchive.h"
X
Xextern int af_errno;
X
Xextern Af_hashent af_hashentry;
X
X/*================= collect_lists ====================================*/
X
XLOCAL Af_revlist **collect_lists (pathname, name, type, revlist, nlists)
X     char       *pathname, *name, *type;
X     Af_revlist **revlist;
X     int        *nlists; /* out */
X{
X  DIR           *dirp;
X  struct direct *dirent;
X  char          *afpath, *afname, *aftype, dirpath[MAXNAMLEN*4];
X  char          fullname[MAXNAMLEN*4], *realloc();
X  bool          seconddir = FALSE, mode;
X  int           listsiz, i;
X  Af_revlist    *af_readattrs();
X
X  listsiz = AF_SEGLEN;
X  *nlists = 0;
X
X  /* open named directory  */
X  if ((dirp = opendir (pathname)) == (DIR *)0)
X    FAIL ("collect_lists", "opendir", AF_ESYSERR, (Af_revlist **)0);
X
X  (void) strcpy (dirpath, pathname);
X
Xloop:
X  /* lookup all files */
X  while ((dirent = readdir (dirp)) != (struct direct *)0)
X    {
X      (void) sprintf (fullname, "%s/%s\0", dirpath, dirent->d_name);
X
X      /* if entry belongs to binary pool */
X      if (af_isbpfile (dirent->d_name))
X	continue;
X
X      afname = af_entersym (af_afname (fullname));
X      aftype = af_entersym (af_aftype (fullname));
X
X      /* if ((no name given || name equal) && (no type || type equal)) */
X      if ( ((name[0] == '*') || !strcmp (name, afname)) &&
X	   ((type[0] == '*') || !strcmp (type, aftype))    )
X	{
X	  (*nlists)++;
X	  if (*nlists >= listsiz)
X	    {
X	      /* realloc memory for revlist */
X	      if ((revlist = (Af_revlist **)realloc ((char *)revlist, (unsigned) (sizeof((Af_revlist *)0)*(listsiz + AF_SEGLEN)))) == (Af_revlist **)0)
X		FAIL ("collect_lists","realloc", AF_ESYSERR, (Af_revlist **)0);
X	      listsiz += AF_SEGLEN;
X	    }
X	  afpath = af_entersym (af_afpath (fullname));
X	  mode = TRUE;
X	  if ((revlist[(*nlists)-1] = 
X	       af_readattrs (afpath, afname, aftype, &mode))
X	                                            == (Af_revlist *)0)
X	    {
X	      if (af_errno == AF_ENOAFSFILE)
X		{
X		  (*nlists)--;
X		  continue;
X		}
X	      else
X		return ((Af_revlist **)0);
X	    }
X	  if (mode)
X	    {
X	      /* see if list is already in "revlists" */
X	      /* this loop may be time-consuming */
X	      i = 0;
X	      while (i < (*nlists)-1)
X		{
X		  if ((revlist[i]->af_list[0].af_name == afname) &&
X		      (revlist[i]->af_cattrs.af_syspath == afpath) &&
X		      (revlist[i]->af_list[0].af_type == aftype))
X		    {
X		      (*nlists)--;
X		      break;
X		    }
X		  i++;
X		}
X	    }
X	}
X    }
X  closedir (dirp);
X
X  if (!seconddir)
X    {
X      (void) sprintf (dirpath, "%s%c%s\0", pathname, '/', AF_SUBDIR);
X      /* open AFS subdirectory if it exists */
X      if ((dirp = opendir (dirpath)) != (DIR *)0)
X	{
X	  seconddir = TRUE;
X	  goto loop;
X	}
X    }
Xreturn (revlist);
X}
X
X/*====================================================================
X *    af_abufcmp -- compare attrbuf with version attributes
X *                  returns TRUE if attrs do not match
X *
X *====================================================================*/
X
XLOCAL af_abufcmp (attrbuf, key)
X     Af_attrs *attrbuf;
X     Af_key   *key;
X{
X  int match, j;
X
X  /* if (attribute is set && attributes does not match) -- return ERROR */
X  
X  /*** generation number ***/
X  if ((attrbuf->af_gen != AF_NOVNUM) && (attrbuf->af_gen != VATTR(key).af_gen))
X    return (ERROR);
X  
X  /*** revision number ***/
X  if ((attrbuf->af_rev != AF_NOVNUM) && (attrbuf->af_rev != VATTR(key).af_rev))
X    return (ERROR);
X
X  /*** variant attribute ***/
X  if ((attrbuf->af_variant[0]) &&
X      (strcmp (attrbuf->af_variant, NOTNIL(VATTR(key).af_variant))))
X    return (ERROR);
X
X  /*** state ***/
X  if ((attrbuf->af_state != AF_NOSTATE) &&
X      (attrbuf->af_state != VATTR(key).af_state))
X    return (ERROR);
X
X  /*** owner ***/
X  if ( (attrbuf->af_owner.af_username[0]) &&
X       (strcmp (attrbuf->af_owner.af_username, CATTR(key).af_ownname)) )
X    return (ERROR);
X  if ( (attrbuf->af_owner.af_userhost[0]) &&
X       (strcmp (attrbuf->af_owner.af_userhost, CATTR(key).af_ownhost)) )
X    return (ERROR);
X  
X  /*** author ***/
X  if ( (attrbuf->af_author.af_username[0]) &&
X       (strcmp (attrbuf->af_author.af_username, VATTR(key).af_auname)) )
X    return (ERROR);
X  if ( (attrbuf->af_author.af_userhost[0]) &&
X       (strcmp (attrbuf->af_author.af_userhost, VATTR(key).af_auhost)) )
X    return (ERROR);
X  
X  /*** size ***/
X  if ((attrbuf->af_size != AF_NOSIZE) &&
X      (attrbuf->af_size != VATTR(key).af_fsize) )
X    return (ERROR);
X
X  /*** mode ***/
X  if ((attrbuf->af_mode != AF_NOMODE) &&
X      (attrbuf->af_mode != VATTR(key).af_mode))
X    return (ERROR);
X
X  /*** locker ***/
X  if ( (attrbuf->af_locker.af_username[0]) &&
X       (strcmp (attrbuf->af_locker.af_username,
X		NOTNIL(VATTR(key).af_lckname))) )
X    return (ERROR);
X  if ( (attrbuf->af_locker.af_userhost[0]) &&
X       (strcmp (attrbuf->af_locker.af_userhost,
X		NOTNIL(VATTR(key).af_lckhost))) )
X    return (ERROR);
X  
X  /*** date of last modification ***/
X  if ((attrbuf->af_mtime != AF_NOTIME) &&
X      (attrbuf->af_mtime != VATTR(key).af_mtime) )
X    return (ERROR);
X
X  /*** date of last access ***/
X  if ((attrbuf->af_atime != AF_NOTIME) &&
X      (attrbuf->af_atime != VATTR(key).af_atime) )
X    return (ERROR);
X
X  /*** date of last status change ***/
X  if ((attrbuf->af_ctime != AF_NOTIME) &&
X      (attrbuf->af_ctime != VATTR(key).af_ctime) )
X    return (ERROR);
X
X  /*** saving date ***/
X  if ((attrbuf->af_stime != AF_NOTIME) &&
X      (attrbuf->af_stime != VATTR(key).af_stime) )
X    return (ERROR);
X  
X  /*** date of last lock change ***/
X  if ((attrbuf->af_stime != AF_NOTIME) &&
X      (attrbuf->af_stime != VATTR(key).af_stime) )
X    return (ERROR);
X  
X  /*** user defined attributes ***/
X  if (attrbuf->af_udattrs[0] != (char *)0)
X    {
X      /* if list of user defined attributes is not empty or there */
X                                                /* are attributes */
X      match = TRUE;
X      if ((attrbuf->af_udattrs[0][0] != '\0') || (VATTR(key).af_udanum != 0))
X	{
X	  /* test all given entries */
X	  j=0;
X	  while ((attrbuf->af_udattrs[j] != (char *)0) 
X		 && (match = !af_match (attrbuf->af_udattrs[j],
X					&(VATTR(key).af_uhtab))))
X	    j++;
X	} /* if */
X      if (match == FALSE)
X	return (ERROR);
X    } /* if */
Xreturn (AF_OK);
X}
X
X
X/*====================================================================
X *    af_bpfind
X *
X *====================================================================*/
X
XEXPORT af_bpfind (attrbuf, set)
X     Af_attrs *attrbuf;
X     Af_set   *set;     /* out */
X{
X  Af_revlist *bplist, *af_rbplist();
X  int        i, maxindex;
X  char       *pathname, *getwd(), *malloc();
X  Af_key     key;
X
X  /* init set */
X  set->af_nkeys = 0;
X  set->af_setlen = 0;
X  set->af_klist = (Af_key *)0;
X
X  /* build pathname (default is current directory) */
X  pathname = af_uniqpath (attrbuf->af_syspath);
X
X  if ((bplist = af_rbplist (pathname)) == (Af_revlist *)0)
X    if (af_errno == AF_ENOAFSDIR)
X      return (0);
X    else
X      return (ERROR);
X
X  /* alloacte memory for set */
X  if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof (Af_key) * bplist->af_nrevs))) == (Af_key *)0)
X    FAIL ("bpfind", "malloc", AF_ESYSERR, ERROR);
X  set->af_setlen = bplist->af_nrevs;
X
X  /* add all desired bpfiles to set */
X  maxindex = bplist->af_nrevs;
X  for (i=0; i < maxindex; i++)
X    {
X      /* skip invalid bpfiles */
X      if (!(bplist->af_list[i].af_class & AF_VALID))
X	{
X	  maxindex++;
X	  continue;
X	}
X      if (((attrbuf->af_name[0] != '*') &&
X	   (strcmp (attrbuf->af_name, bplist->af_list[i].af_name))) ||
X	  ((attrbuf->af_type[0] != '*') &&
X	   (strcmp (attrbuf->af_type, NOTNIL(bplist->af_list[i].af_type)))))
X	continue;
X
X      key.af_ldes = bplist;
X      key.af_lpos = i;
X      if (af_abufcmp (attrbuf, &key))
X	continue;
X      
X      /* else add bpfile to set */
X      set->af_klist[set->af_nkeys].af_ldes = bplist;
X      set->af_klist[set->af_nkeys].af_lpos = i;
X      set->af_nkeys++;
X      bplist->af_refcount++;
X      bplist->af_list[i].af_nlinks++;
X    }
X  /* if set is empty */
X  if (set->af_nkeys == 0)
X    {
X      free ((char *)set->af_klist);
X      set->af_setlen = 0;
X    }
X
X  if (bplist->af_refcount <= 0)
X    (void) af_detlist (bplist);
X
X  return (set->af_nkeys);
X}
X
X
X/*====================================================================
X *    af_find
X *
X *====================================================================*/
X
XEXPORT af_find (attrbuf, set)
X     Af_attrs *attrbuf;
X     Af_set   *set;     /* out */
X{
X  char          *pathname, *getwd(), *malloc();
X  register int  i;
X  int           nlists, maxindex;
X  Af_revlist    *af_readattrs(), **revlist;
X  Af_key        key;
X  bool          mode = FALSE;
X
X  /* alloc memory for revlist */
X  if ((revlist = (Af_revlist **)malloc ((unsigned) (sizeof((Af_revlist *)0)*AF_SEGLEN))) == (Af_revlist **)0)
X    FAIL ("find", "malloc", AF_ESYSERR, ERROR);
X
X  /* init set */
X  set->af_nkeys = 0;
X  set->af_setlen = 0;
X  set->af_klist = (Af_key *)0;
X
X  /* build pathname (default is current directory) */
X  pathname = af_uniqpath (attrbuf->af_syspath);
X
X  if ((attrbuf->af_name[0] == '*') || (attrbuf->af_type[0] == '*'))
X    {
X      if ((revlist = collect_lists (pathname, attrbuf->af_name,
X				    attrbuf->af_type, revlist, &nlists))
X	  == (Af_revlist **)0)
X	return (ERROR);
X    }
X  else
X    {
X      if (!attrbuf->af_name[0] && !attrbuf->af_type[0])
X	{
X	  free ((char *)revlist);
X	  return (set->af_nkeys); /* no Af-files found */
X	}
X      if ((revlist[0] =
X	   af_readattrs (pathname, attrbuf->af_name,
X			 attrbuf->af_type, &mode)) == (Af_revlist *)0)
X	{
X	  free ((char *)revlist);
X	  if (af_errno == AF_ENOAFSFILE)
X	    nlists = 0;
X	  else
X	    return (ERROR);
X	}
X      else
X	nlists = 1;
X    }
X
X  if (nlists == 0)
X    return (set->af_nkeys); /* no Af-files found */
X
X  /* alloacte memory for set */
X  if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof (Af_key) * AF_SEGLEN))) == (Af_key *)0)
X    FAIL ("find", "malloc", AF_ESYSERR, ERROR);
X  set->af_setlen = AF_SEGLEN;
X
X  /* lookup all revisions in all lists */
X  /* this part is implemented quite dull up to now */
X  /*     -- the number of "if"'s should be reduced */
X  for (;nlists > 0; nlists--)
X    {
X      maxindex = revlist[nlists-1]->af_nrevs;
X      for (i = 0; i < maxindex; i++)
X	{
X	  /* skip holes in the list */
X	  if (!(revlist[nlists-1]->af_list[i].af_class & AF_VALID))
X	    {
X	      maxindex++;
X	      continue;
X	    }
X
X	  /* test all attributes -- returnes true if attrs do not match */
X	  key.af_ldes = revlist[nlists-1];
X	  key.af_lpos = i;
X	  if (af_abufcmp (attrbuf, &key))
X	    continue;
X
X	  /********************************************/
X	  /********** put AF-file into set ************/
X	  /********************************************/
X
X	  /* if set is full, enlarge it */
X	  if (set->af_nkeys == set->af_setlen)
X	    {
X	      if ((set->af_klist = 
X		   (Af_key *)realloc ((char *)set->af_klist, (unsigned) (sizeof(Af_key) * (set->af_setlen + AF_SEGLEN)))) == (Af_key *)0)
X		FAIL ("find", "realloc", AF_ESYSERR, ERROR);
X	      set->af_setlen += AF_SEGLEN;
X	    }
X
X	  /* add revision to key-set */
X	  set->af_klist[set->af_nkeys].af_ldes = revlist[nlists-1];
X	  set->af_klist[set->af_nkeys].af_lpos = i;
X	  set->af_nkeys++;
X	  revlist[nlists-1]->af_refcount++;
X	  revlist[nlists-1]->af_list[i].af_nlinks++;
X	} /* for all revisions in archive */
X
X      /* if revlist does not contribute to hit set */
X      if (revlist[nlists-1]->af_refcount <= 0)
X	(void) af_detlist (revlist[nlists-1]);
X
X    } /* for all archives */
X
X  /* if set is empty */
X  if (set->af_nkeys == 0)
X    {
X      free ((char *)set->af_klist);
X      set->af_setlen = 0;
X    }
X
X  free ((char *)revlist);
X  return (set->af_nkeys);
X}
X
X
X/*====================================================================
X *    af_getkey
X *
X *====================================================================*/
X
XEXPORT af_getkey (syspath, name, type, gen, rev, variant, key)
X     char   *syspath, *name, *type;
X     int    gen, rev;
X     /*ARGSUSED*/
X     char   *variant; /* unused */
X     Af_key *key;
X{
X  Af_revlist *list, *af_readattrs();
X  char *path;
X  bool mode = FALSE;
X
X  /* build pathname (default is current directory) */
X  path = af_uniqpath (syspath);
X
X  if ((list = af_readattrs (path, name, type, &mode)) == (Af_revlist *)0)
X    SFAIL ("getkey", "", AF_ENOREV, ERROR);
X  key->af_ldes = list;
X 
X  /* handle special cases */
X  if ((gen < 0) || (rev < 0))
X    {
X      switch (gen)
X	{
X	case AF_BUSYVERS: if (af_buildkey (list, gen, rev, key) == ERROR)
X	                    SFAIL ("getkey", "", AF_ENOREV, ERROR);
X	                  break;
X	case AF_LASTVERS: if ((rev != AF_LASTVERS) || (list->af_nrevs == 0))
X	                     SFAIL ("getkey", "", AF_ENOREV, ERROR);
X	                  /* if busy version is valid */
X	                  key->af_lpos = list->af_listlen-1;
X			  while (!(VATTR(key).af_class & AF_VALID) || 
X				 (VATTR(key).af_state == AF_BUSY))
X			    {
X			      if (key->af_lpos-- == 0)
X				SFAIL ("getkey", "", AF_ENOREV, ERROR);
X			    }
X			  break;
X	case AF_FIRSTVERS: if ((rev != AF_FIRSTVERS) || (list->af_nrevs == 0))
X	                     SFAIL ("getkey", "", AF_ENOREV, ERROR);
X			   key->af_lpos = 0;
X			   while ((VATTR(key).af_state == AF_BUSY) ||
X				  (!(VATTR(key).af_class & AF_VALID)))
X			     {
X			       if (key->af_lpos++ == list->af_listlen-1)
X				 SFAIL ("getkey", "", AF_ENOREV, ERROR);
X			     }
X			   break;
X	default: SFAIL ("getkey", "", AF_ENOREV, ERROR);
X	}
X    }
X  else
X    {
X      if (af_buildkey (list, gen, rev, key) == ERROR)
X	SFAIL ("getkey", "", AF_ENOREV, ERROR);
X    }
X
X  list->af_refcount++;
X  VATTR(key).af_nlinks++;
X  return (AF_OK);
X}
X
X
X/*====================================================================
X *    af_dropkey
X *
X *====================================================================*/
X
XEXPORT af_dropkey (key)
X     Af_key *key;
X{
X  if (af_keytest (key))
X    SFAIL ("dropkey", "", AF_EINVKEY, ERROR);
X
X  /* decrease reference count in corresponding archive and in attrbuf */
X  if (--(key->af_ldes)->af_refcount <= 0)
X    (void) af_detlist (key->af_ldes);
X  else
X    VATTR(key).af_nlinks--;
X  return (AF_OK);
X}
X
X
X/*====================================================================
X *    af_initattrs
X *
X *====================================================================*/
X
XEXPORT af_initattrs (attrs)
X     Af_attrs *attrs;
X{
X  attrs->af_host[0] = '\0';
X  attrs->af_syspath[0] = '\0';
X  attrs->af_name[0] = '*';
X  attrs->af_name[1] = '\0';
X  attrs->af_type[0] = '*';
X  attrs->af_type[1] = '\0';
X  attrs->af_gen = AF_NOVNUM;
X  attrs->af_rev = AF_NOVNUM;
X  attrs->af_variant[0] = '\0';
X  attrs->af_state = AF_NOSTATE;
X  attrs->af_owner.af_username[0] = '\0';
X  attrs->af_owner.af_userhost[0] = '\0';
X  attrs->af_author.af_username[0] = '\0';
X  attrs->af_author.af_userhost[0] = '\0';
X  attrs->af_size = AF_NOSIZE;
X  attrs->af_mode = AF_NOMODE;
X  attrs->af_locker.af_username[0] = '\0';
X  attrs->af_locker.af_userhost[0] = '\0';
X  attrs->af_mtime = AF_NOTIME;
X  attrs->af_atime = AF_NOTIME;
X  attrs->af_ctime = AF_NOTIME;
X  attrs->af_stime = AF_NOTIME;
X  attrs->af_ltime = AF_NOTIME;
X  attrs->af_udattrs[0] = (char *)0;
X}
X
END_OF_FILE
if test 16910 -ne `wc -c <'src/afs/afretr.c'`; then
    echo shar: \"'src/afs/afretr.c'\" unpacked with wrong size!
fi
# end of 'src/afs/afretr.c'
fi
if test -f 'src/afsit/rcsit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/afsit/rcsit.c'\"
else
echo shar: Extracting \"'src/afsit/rcsit.c'\" \(16773 characters\)
sed "s/^X//" >'src/afsit/rcsit.c' <<'END_OF_FILE'
X/*
X * $Header: rcsit.c,v 1.20 87/05/04 21:50:53 src Exp $
X *---------------------------------------------------------
X * $Source: /src/tools/rcs/src/rcsit/RCS/rcsit.c,v $
X * $Revision: 1.20 $
X * $Date: 87/05/04 21:50:53 $
X * $State: Exp $
X * $Author: src $
X * $Locker: src $
X *---------------------------------------------------------
X * Michael Cooper (mcooper@usc-oberon.arpa)
X * University of Southern California,
X * University Computing Services,
X * Los Angeles, California,   90089-0251
X * (213) 743-3469
X *---------------------------------------------------------
X *
X * $Log:	rcsit.c,v $
X * Revision 1.20  87/05/04  21:50:53  src
X * added -F - flag. This option causes an additional header field for
X * inclusion of compile-time options into object-files to be inserted
X * into the C-source. The man-entry is also updated.
X * 
X * Revision 1.19  86/06/12  20:29:43  src
X * The previous version was unable to look up templates in the 
X * directory $TEMPLATES, when -t - option is absent but the
X * environment-variable TEMPLATES is set. Fixed that. If no -t - option
X * was given, but $TEMPLATES is non NULL, then -t is assumed and
X * $TEMPLATES is used as path to template-files.
X * 
X * Revision 1.18  85/11/26  17:03:32  mcooper
X * Change message telling of what header was added.
X * 
X * Revision 1.17  85/11/26  16:40:55  mcooper
X * Changed the default -t option to FALSE.
X * Added specifying directory to look for .template.*
X * files in via -tdirectory.
X * 
X * Revision 1.16  85/11/11  21:35:34  mcooper
X * Added call to access() to see if the file
X * could be read.
X * 
X * Revision 1.15  85/11/11  21:22:33  mcooper
X * Changed comment char for fortran files
X * from "*" to "c".  This is what RCS uses.
X * 
X * Revision 1.14  85/11/11  20:08:43  mcooper
X * Added descriptions for fortran (.f) files.
X * 
X * Revision 1.13  85/11/11  19:52:17  mcooper
X * Modified default header templates to not bother specifying
X * the RCS file name of the file.  co(1) worries about it.
X * 
X * Revision 1.12  85/10/27  19:10:07  mcooper
X * Fixed bug that would not use template files if a file
X * type was forced with -c, -h, etc.
X * 
X * Revision 1.11  85/10/27  18:48:27  mcooper
X * Extended template file.  You can now have template
X * files describing all the types of files that
X * rcsit "knows" about.  The file $HOME/.template.*
X * (where ``*'' is a ``.'' suffix rcsit can guess at or
X * the type of file that is specified with an override)
X * is checked for existance.  If not present, the default
X * header (built into rcsit) will be used.
X * 
X * Revision 1.10  85/10/27  16:15:53  mcooper
X * Added printing of what rcsit is doing if tflag is
X * true.  Also added new headers.
X * 
X * Revision 1.9  85/10/27  14:47:39  mcooper
X * Added new template feature.  If the file
X * .template exists in the users HOME directory,
X * then that file is used as the header file instead
X * of the defaults for each type of file.  This can
X * be disabled with the -t option in case the file
X * is say a shell script.  With the template feature
X * turned off, the auto guessing is re-inabled.
X * Also, rcsit now removes its temporary files.
X * 
X * Revision 1.8  85/09/28  14:11:45  mcooper
X * Added feature: if the environment variable RCSDIR is
X * present, rcsit will attempt to make a symbolic
X * link to the directory when the -I flag is used.
X * This is done only when -I is specified AND the 
X * directory RCS is not present.  You may disable this
X * feature with the -d option.  Note also that if RCSDIR
X * is not in the environment and the above conditions
X * are true, that a normal directory called RCS will
X * be created.
X * 
X * Revision 1.7  85/09/19  15:59:53  mcooper
X * Kludge part 2 -- If you specify a ci -l of a
X * man file, then the header is messed up. 
X * Fix: After initializing the comment string,
X * unlink the file and then run co -l.
X * 
X * Revision 1.6  85/09/19  15:39:57  mcooper
X * Now knows about ``Manual'' type files.
X * 
X * Revision 1.5  85/09/19  14:23:24  mcooper
X * Added lineprint() function to print things out
X * nicely.  Fixed bug for Manual type files.  Due
X * to the fact that RCS does not not the suffixes of
X * manuals, it therefor does not know what kind of
X * comment string to use.  Thus, I kludge by running
X * a ``rcs -c`... ' file'' to tell rcs the comment
X * string.
X * 
X * Revision 1.4  85/09/19  13:28:22  mcooper
X * Fixed bug in auto_guess.  Would not continue through function
X * when file type was ``Makefile''.
X * 
X * Revision 1.3  85/09/19  13:19:50  mcooper
X * Added ``Shell Script'' file type.
X * 
X * Revision 1.2  85/09/19  10:08:36  mcooper
X * Added code to run RCS commands (rcs & ci) on files.
X * Fixed bug that limited number of command line files specified to
X * nine.  Several other minor fixes and improvements.
X * 
X * Revision 1.1  85/09/17  11:33:33  mcooper
X * Initial revision
X * 
X */
X
X/*
X * rcsit -- 	Prepare files for RCS.  rcsit puts the correct headings
X *		at the top of files to prepare them for RCS headings
X *		and log tracking.
X *
X * Michael Cooper	(mcooper@usc-oberon.arpa)
X * University Computing Services, USC
X *
X * 9-16-85
X */
X
X#include <sys/file.h>
X#include <stdio.h>
X#include <ctype.h>
X#include <strings.h>
X
X#ifdef NULL
X#undef NULL
X#endif
X#define NULL		'\0'
X#define LENGTH		512		/* length of line */
X#define TRUE		1
X#define FALSE		0
X
X#ifdef DEBUG
X int debugon = TRUE;
X#else
X int debugon = FALSE;
X#endif
X
Xstatic char 	*progname;		/* program name */
Xstatic char 	*rcsdir;
X
X/*
X * Messages to be printed for the user.
X */
Xstatic char	*msg_name;		
Xstatic char 	*m_stdc = "Standard C",
X                *m_stdcflg = "Standard C with compile flags",
X		*m_include = "C Include",
X		*m_fortran = "Fortran",
X		*m_pascal = "Pascal",
X		*m_make	= "Makefile",
X		*m_shell = "Shell Script",
X		*m_manual = "Manual";
X
X/*
X * The headers to put at the beginning of the file(s).
X * Notice that the words Header and Log do not appear here
X * because RCS will put in the keyword substitutions when rcsit.c
X * is co'ed.
X */
Xstatic char	*header;
X#ifdef AFSIT
Xstatic char	*h_stdc = 
X	"#ifndef lint\nstatic char *AFSid = \"$%s$\";\n#endif\n/*\n * $%s$\n */\n\n";
Xstatic char	*h_stdcflg = 
X	"#ifndef lint\nstatic char *AFSid = \"$%s$\";\n#ifdef CFFLGS\n\
Xstatic char *ConfFlg = CFFLGS;\n\t/* should be defined from within\
X Makefile */\n#endif\n#endif\n/*\n * $%s$\n */\n\n";
X#else
Xstatic char	*h_stdc = 
X	"#ifndef lint\nstatic char *RCSid = \"$%s$\";\n#endif\n/*\n * $%s$\n */\n\n";
Xstatic char	*h_stdcflg = 
X	"#ifndef lint\nstatic char *RCSid = \"$%s$\";\n#ifdef CFFLGS\n\
Xstatic char *ConfFlg = CFFLGS;\n\t/* should be defined from within\
X Makefile */\n#endif\n#endif\n/*\n * $%s$\n */\n\n";
X#endif
Xstatic char	*h_include = 
X	"/*\n * $%s$\n *\n * $%s$\n */\n\n";
Xstatic char	*h_make =
X	"#\n# $%s$\n#\n# $%s$\n#\n";
Xstatic char 	*h_manual =
X	"...\n... $%s$\n... \n... $%s$\n...\n";
Xstatic char 	*h_fortran =
X	"c\nc $%s$\nc\nc $%s$\nc\n";
X
X/*
X * Template file names
X */
Xstatic char	*template_c 	= ".template.c";	/* .c template */
Xstatic char 	*template_h 	= ".template.h";	/* .h template */
Xstatic char 	*template_f 	= ".template.f";	/* .f template */
Xstatic char 	*template_p 	= ".template.p";	/* .p template */
Xstatic char 	*template_man 	= ".template.man";	/* man template */
Xstatic char	*template_make	= ".template.make";	/* make template */
Xstatic char	*template_sh	= ".template.sh";	/* sh script template */
Xstatic char	*tpath;					/* path to template */
Xstatic char	tfile[BUFSIZ];				/* template file */
Xstatic char	tbuf[BUFSIZ];				/* current tfile */
X
X/*
X * Command line flags
X */
Xint	Iflag	= FALSE;			/* run ci(1) */
Xint	rcsflag = FALSE;			/* run rcs(1) */
Xint	aflag	= TRUE;				/* do auto guess */
Xint	dflag	= TRUE;				/* creat RCS dir. */
Xint	qflag	= FALSE;			/* be quiet! */
Xint 	cflag	= FALSE;			/* std c file */
Xint	fflag	= FALSE;			/* fortran file */
Xint     Fflag   = FALSE;                        /* insert C-Flags header */
Xint	pflag	= FALSE;			/* pascal file */
Xint	hflag	= FALSE;			/* include file */
Xint	sflag	= FALSE;			/* shell script */
Xint 	mflag	= FALSE;			/* Makefile */
Xint	Mflag	= FALSE;			/* manual */
Xint	tflag	= FALSE;			/* template flag */
X
Xmain(argc, argv)
Xint	argc;
Xchar 	*argv[];
X{
X	int x;
X	char	tmp[LENGTH];
X	char	*file;
X	char	*flags;
X	char 	tmpfile[32];
X	char    *cp;
X	char 	*mktemp();
X	char	*gettmp();
X	char	*getenv();
X	FILE 	*fd, 
X		*fdtmp,
X		*fopen();
X
X	progname = (cp = rindex (argv[0], '/')) ? ++cp : argv[0];
X	sprintf (tmpfile, "/tmp/%sXXXXXX", progname);
X	for (x = 1; x < argc; x++) {
X		if (argv[x][0] != '-')
X			break;
X		switch (argv[x][1]) {
X			case 'a':
X				aflag = FALSE;
X				break;
X			case 'q':
X				qflag = TRUE;
X				break;
X			case 'd':
X				dflag = FALSE;
X				break;
X			case 'f':
X				fflag = TRUE;
X				break;
X                        case 'F':
X				Fflag = TRUE;
X				cflag = TRUE; /* Only for C-files yet */
X				break;
X			case 'h':
X				hflag = TRUE;
X				break;
X			case 's':
X				sflag = TRUE;	
X				break;
X			case 'm':
X				mflag = TRUE;
X				break;
X			case 'M':
X				Mflag = TRUE;
X				break;
X			case 'i':
X			case 'I':
X				Iflag = TRUE;
X				flags = &argv[x][2];
X				break;
X			case 'r':
X			case 'R':
X				rcsflag = TRUE;
X				flags = &argv[x][2];
X				break;
X			case 't':
X				tflag = TRUE;
X				tpath = &argv[x][2];
X				break;
X			case 'c':
X				cflag = TRUE;
X				break;
X			default:
X				fatal("Unknown flag %s.",argv);
X		}
X	}
X	argc -= (x - 1);
X	argv += (x - 1);
X
X	if((hflag && (mflag || Mflag || cflag)) ||
X		(mflag && (hflag || cflag || Mflag)) ||
X		(Mflag && (cflag || hflag || mflag)) ||
X		(cflag && (hflag || Mflag || mflag))) {
X			fatal("Only ONE of -c,-f,-m,-M,-h,-s may be specified.");
X	}
X	if(Iflag && rcsflag) {
X			fatal("Only ONE of ``-i'' and ``-r'' may be specified.");
X	}
X
X	if(cflag || hflag || mflag || Mflag || fflag || sflag)
X		aflag = FALSE;
X
X	if((rcsdir = getenv("RCSDIR")) == NULL)
X		rcsdir = "RCS";
X	if(Iflag && dflag)
X		checkdir();	/* Make RCS directory for ci */
X	if((!tflag) && ((tpath = getenv ("TEMPLATE")) != NULL))
X	        tflag = TRUE;   /* fixed by axel@coma.uucp */
X	if((*tpath == NULL) && ((tpath = getenv("TEMPLATE")) == NULL))
X		if((tpath = getenv("HOME")) == NULL)
X			fatal("Cannot find environment variable HOME or TEMPLATE");
X
X	/*
X	 * make tmp file once.
X	 */
X	mktemp(tmpfile);
X
X	while (--argc) {	/* Main loop */
X		file = *++argv;
X		debug(sprintf(tmp, "...file (*++argv) = %s...", file));
X
X		if(access(file, 4) != 0)
X			fatal("Cannot access %s.  No read permission OR file does not exist.",
X				file);
X		if((fdtmp = fopen(tmpfile, "w")) == NULL) {
X			fatal("Cannot open tmpfile (%s).", tmpfile);
X		}
X
X		if(aflag)
X			auto_guess(file); /* try and guess file type */
X		else
X			set_flags();	  /* check and set flags */
X
X		if(tflag) {
X			/*
X			 * first get names of templates, then create
X			 * path name to it.
X			 */
X			get_temp();
X			sprintf(tfile, "%s/%s", tpath, tbuf);
X		}
X		if(access(tfile, 0) == 0 && tflag) {
X			if(!qflag || debugon)
X				printf("Adding %s header file to %s...",
X					msg_name, file);
X			copy(tfile, tmpfile, "w");
X			copy(file, tmpfile, "a");
X		} else {
X			if(!qflag || debugon)
X				printf(
X				"Adding default header (%s format) to %s...",
X					msg_name, file);
X			/*
X			 * put the Keywords into header string
X			 */
X#ifdef AFSIT
X			sprintf(tmp, header, "__Header", "__Log");
X#else
X			sprintf(tmp, header, "Header", "Log");
X#endif
X			fputs(tmp, fdtmp);
X			/*
X			 * fclose'em, just in case.
X			 */
X			fclose(fdtmp);
X			copy(file, tmpfile, "a");
X		}
X		unlink(file);
X		copy(tmpfile, file, "w");
X		unlink(tmpfile);
X
X		if(!qflag || debugon)
X			printf("done.\n");
X		if (Fflag)
X		  puts ("-> Don't forget to define CFFLGS on compiler\
X commandline <-\n");
X
X		if(Iflag){
X			rcs("ci", file, flags);
X			if(Mflag){	/* kludge to tell rcs about manuals */
X				rcs("rcs", file, "c'... '");
X				/*
X				 * kludge part 2 - if the user tried a ci
X				 * with a -l option, then the header is
X				 * messed up in the currently checked out
X				 * man file.  So we have to co the file to 
X				 * clean up the header.  Plus we use the
X				 * -l option of co to insure file locking.
X				 */
X				if(checkfor("l", flags)){
X					unlink(file);
X					rcs("co", file, "l");
X				}
X			}
X		}
X		if(rcsflag)
X			rcs("rcs", file, flags);
X	}
X}
X
X/*
X * debug - print (useless) debugging info.
X */
X 
Xdebug(msg)
Xchar *msg;
X{
X#ifdef DEBUG
X	fprintf(stderr, msg);
X	putchar ('\n');
X#endif
X}
X
X/*
X * auto_guess - try and be intelligent and guess type of file
X *		by looking at the suffix or the whole name
X *		in the case of a makefile.
X */
X
Xauto_guess(file)
Xchar	*file;
X{
X	char *suffix;
X	char *rindex();
X
X	suffix = rindex(file, '.')+1;
X	if((strcmp(file, "makefile") == 0) || (strcmp(file, "Makefile") == 0) ||
X	    (strcmp(suffix, "mk") == 0)) {	/* sys V std suffix */
X		mflag = TRUE;
X		sflag = FALSE;
X		cflag = FALSE;
X		hflag = FALSE;
X		Mflag = FALSE;
X		fflag = FALSE;
X	}
X	if((strcmp(suffix, "sh") == 0) || (strcmp(suffix, "csh") == 0)) {
X		sflag = TRUE;
X		cflag = FALSE;
X		hflag = FALSE;
X		mflag = FALSE;
X		Mflag = FALSE;
X		fflag = FALSE;
X	}
X	if(strcmp(suffix, "c") == 0){
X		cflag = TRUE;
X		hflag = FALSE;
X		mflag = FALSE;
X		Mflag = FALSE;
X		sflag = FALSE;
X		fflag = FALSE;
X	}
X	if(strcmp(suffix, "h") == 0){
X		hflag = TRUE;
X		cflag = FALSE;
X		mflag = FALSE;
X		Mflag = FALSE;
X		sflag = FALSE;
X		fflag = FALSE;
X	}
X	if(strcmp(suffix, "f") == 0){
X		fflag = TRUE;
X		hflag = FALSE;
X		cflag = FALSE;
X		mflag = FALSE;
X		Mflag = FALSE;
X		sflag = FALSE;
X	}
X	if(isdigit(*suffix) != 0) {
X		Mflag = TRUE;
X		hflag = FALSE;
X		cflag = FALSE;
X		mflag = FALSE;
X		sflag = FALSE;
X		fflag = FALSE;
X	}
X	set_flags();
X	if(!qflag || debugon)
X		printf("Hmm.  This file looks like a %s file.\n", msg_name);
X}
X
X/*
X * set_flags - set & check flags
X */
X 
Xset_flags()
X{
X	if(cflag || hflag || mflag || Mflag || sflag || fflag) {
X		if(cflag) {
X			msg_name = m_stdc;
X			header = h_stdc;
X		}
X		if (Fflag) { /* This is more than just cflag - axel@coma */
X		        msg_name = m_stdcflg;
X			header = h_stdcflg;
X		}
X		if(hflag) {
X			msg_name = m_include;
X			header = h_include;
X		}
X		if(mflag) {
X			msg_name = m_make;
X			header = h_make;
X		}
X		if(Mflag) {
X			msg_name = m_manual;
X			header = h_manual;
X		}
X		if(sflag) {
X			msg_name = m_shell;
X			header = h_make;
X		}
X		if(fflag) {
X			msg_name = m_fortran;
X			header = h_fortran;
X		}
X	} else {
X		cflag = TRUE;
X		set_flags();
X	}
X}
X
X/*
X * copy from -> to
X */
X
Xcopy(from, to, mode)
Xchar *from;
Xchar *to;
Xchar *mode;
X{
X	FILE *fdfrom, *fdto, *fopen();
X	char tmp[LENGTH];
X	char s[LENGTH];
X
X	if((fdfrom = fopen(from, "r")) == NULL) {
X		fatal("Cannot open %s for reading.",from);
X	}
X	if((fdto = fopen(to, mode)) == NULL) {
X		fatal("Cannot open %s for \"%s\".",to,mode);
X	}
X	while(fgets(s, sizeof(s), fdfrom) != NULL)
X		fputs(s, fdto);
X	fclose(fdfrom);
X	fclose(fdto);
X}
X
X/*
X * Run RCS's rcsprog on file with flags.
X */
X
Xrcs(rcsprog, file, flags)
Xchar *rcsprog;
Xchar *file;
Xchar *flags;
X{
X	char buf[LENGTH];
X	char tmp[LENGTH];
X
X	if(!checkfor("q", flags) && qflag)
X		flags = "q";
X	if(strcmp(flags, NULL) == 0)
X		sprintf(buf, "%s %s", rcsprog, file);
X	else
X		sprintf(buf, "%s -%s %s", rcsprog, flags, file);
X	debug(sprintf(tmp,"Running ``%s''...\n", buf));
X	if(!qflag)
X		lineprint(sprintf(tmp, "Start of ``%s''", buf));
X	system(buf);
X	if(!qflag)
X		lineprint(sprintf(tmp, "End of ``%s''", buf));
X}
X
X/*
X * checkdir - make RCS directory if not present.
X */
X
Xcheckdir()
X{
X	if(access("RCS", 0) != 0){
X		if(!qflag || debugon)
X			printf("Cannot find \"RCS\" directory.  Creating...\n");
X		if(strcmp(rcsdir, "RCS") != 0) { 
X			if(symlink(rcsdir, "RCS") != 0)
X				fatal("Symbolic link of %s to RCS failed.", 
X					rcsdir);
X		} else {
X			if(mkdir(rcsdir, 0755) != 0)
X				fatal("Cannot create \"%s\" directory.", 
X					rcsdir);
X		}
X	}
X}
X
X/*
X * checkfor(x, str) -- check for x in str.  Return 1 (TRUE) if exists.
X *			Otherwise 0 (FALSE).
X */
X
Xcheckfor(x, str)
Xchar 	*x;
Xchar 	*str;
X{
X	while(*str) {
X		if(strcmp(str, x) == 0)
X			return(TRUE);
X		*str++;
X	}
X	return(FALSE);
X}
X
X/*
X * lineprint - print msg in a nice line
X */
X
Xlineprint(msg)
Xchar *msg;
X{
X	int len, left, right, x;
X
X	len = strlen(msg);
X	right = (75-len)/2;
X	left = right;
X	for(x = 0; x < right; ++x)
X		putchar('-');
X	printf("[ %s ]", msg);
X	for(x = 0; x < left; ++x)
X		putchar('-');
X	putchar('\n');
X}
X
X/*
X * fatal - print error and then exit(1).
X */
Xfatal(format, str)
Xchar *format;
X{
X	static char namefmt[100];
X
X	sprintf(namefmt, "%s: %s\n", progname, format);
X	_doprnt(namefmt, &str, stderr);
X	exit(1);
X}
X
X/*
X * zap str with NULL's
X */
X
Xzap(str)
Xchar str[];
X{
X	int i, x;
X
X	i = strlen(str);
X	for(x = 0; x <= i; )
X		str[x++] = NULL;
X}
X
X/*
X * get template names
X */
X
Xget_temp()
X{
X	zap(tbuf);
X	if(mflag)
X		strcpy(tbuf, template_make);
X	if(Mflag)
X		strcpy(tbuf, template_man);
X	if(hflag)
X		strcpy(tbuf, template_h);
X	if(cflag)
X		strcpy(tbuf, template_c);
X	if(sflag)
X		strcpy(tbuf, template_sh);
X	if(fflag)
X		strcpy(tbuf, template_f);
X}
END_OF_FILE
if test 16773 -ne `wc -c <'src/afsit/rcsit.c'`; then
    echo shar: \"'src/afsit/rcsit.c'\" unpacked with wrong size!
fi
# end of 'src/afsit/rcsit.c'
fi
echo shar: End of archive 18 \(of 33\).
cp /dev/null ark18isdone
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.