v19i034: A software configuration management system, Part21/33
Rich Salz
rsalz at uunet.uu.net
Tue Jun 6 00:26:52 AEST 1989
Submitted-by: Axel Mahler <unido!coma!axel>
Posting-number: Volume 19, Issue 34
Archive-name: shape/part21
#! /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 21 (of 33)."
# Contents: src/afs/afsets.c src/vc/vldovl.c
# Wrapped by rsalz at papaya.bbn.com on Thu Jun 1 19:27:13 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/afs/afsets.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/afs/afsets.c'\"
else
echo shar: Extracting \"'src/afs/afsets.c'\" \(19377 characters\)
sed "s/^X//" >'src/afs/afsets.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 at coma.uucp or shape at db0tui62.bitnet
X */
X/*LINTLIBRARY*/
X/*
X * Shape/AFS
X *
X * afsets.c -- Operations on keysets
X *
X * Author: Andreas Lampen, TU-Berlin (andy at coma.UUCP)
X * (andy at db0tui62.BITNET)
X *
X * $Header: afsets.c[1.3] Wed Feb 22 16:27:56 1989 andy at coma published $
X *
X * EXPORT:
X * af_initset -- initialize set descriptor
X * af_copyset -- copy sets
X * af_nrofkeys -- return number of keys in set
X * af_sortset -- sort set by attribute
X * af_dropset -- drop set
X * af_setgkey -- get key from set
X * af_setaddkey -- add key to set
X * af_setrmkey -- remove key from set
X * af_setposrmkey -- remove key (identified by position) from set
X * af_subset -- build subset
X * af_intersect -- build intersection of two sets
X * af_union -- build union of two sets
X * af_diff -- build difference between two sets
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
Xchar *malloc(), *realloc();
X
X/*================================================================
X * af_settest -- test plausibility of set descriptor
X * returnes TRUE (ERROR) if set descr. is invalid,
X * otherwise FALSE (AF_OK).
X *
X *================================================================*/
X
XLOCAL af_settest (set)
X Af_set *set;
X{
X if ((set->af_nkeys < 0) || (set->af_setlen < 0))
X return (ERROR);
X /* if set is not empty, test if first key is valid */
X if (set->af_nkeys >= 1)
X if (af_keytest (&(set->af_klist[0])))
X return (ERROR);
X
X return (AF_OK);
X}
X
X/*================================================================
X * af_initset -- initialize set descriptor
X *
X *================================================================*/
X
XEXPORT af_initset (set)
X Af_set *set;
X{
X set->af_nkeys = 0;
X set->af_setlen = 0;
X set->af_klist = (Af_key *)0;
X}
X
X/*================================================================
X * af_copyset -- copy sets
X *
X *================================================================*/
X
XEXPORT af_copyset (set1, set2)
X Af_set *set1, *set2;
X{
X int i;
X
X if (af_settest (set1) || af_settest (set2))
X SFAIL ("copyset", "", AF_EINVSET, ERROR);
X
X /* allocate memory for new set (incl. space for additional element) */
X set2->af_setlen = set1->af_nkeys + 1;
X if ((set2->af_klist = (Af_key *)malloc ((unsigned) (set2->af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X FAIL ("copyset", "malloc", AF_ESYSERR, ERROR);
X
X /* do copying */
X for (i=0; i<set1->af_nkeys; i++)
X {
X set2->af_klist[i] = set1->af_klist[i];
X /* increase refcount in list descriptor */
X VATTR((&(set2->af_klist[i]))).af_nlinks++;
X (set2->af_klist[i].af_ldes)->af_refcount++;
X }
X set2->af_nkeys = set1->af_nkeys;
X return (set2->af_nkeys);
X}
X
X/*================================================================
X * af_nrofkeys -- return number of keys in set
X *
X *================================================================*/
X
XEXPORT af_nrofkeys (set)
X Af_set *set;
X{
X if (af_settest (set))
X SFAIL ("nrofkeys", "", AF_EINVSET, ERROR);
X return (set->af_nkeys);
X}
X
X/*================================================================
X * af_sortset -- sort set by attribute
X *
X *================================================================*/
X
Xextern struct cmpfun { int (*func) (); };
X
Xextern struct cmpfun af_cmpfuncts[];
X
Xextern char *af_attrlist[], af_udaname[];
X
XEXPORT af_sortset (set, attr)
X Af_set *set;
X char *attr;
X{
X int hi = AF_ATTNUM-1, lo=0, anum, res, af_cmpuda();
X
X if (af_settest (set))
X SFAIL ("sortset", "", AF_EINVSET, ERROR);
X if (!attr)
X SFAIL ("sortset", "invalid attribute name", AF_EMISC, ERROR);
X
X /* get attribute number (binary search) */
X anum = (hi+lo)/2;
X while (hi >= lo)
X {
X res = strcmp (attr, af_attrlist[anum]);
X if (res == 0)
X break;
X if (res < 0)
X hi = anum - 1;
X else lo = anum + 1;
X anum = (hi+lo)/2;
X }
X /* attribute names, that are not in the list of standard attributes */
X /* are assumed to be "user defined attributes" */
X if (res != 0)
X {
X (void) strcpy (af_udaname, attr);
X qsort ((char *)set->af_klist, set->af_nkeys, sizeof(Af_key), af_cmpuda);
X }
X else
X {
X (void) strcpy (af_udaname, attr);
X qsort ((char *)set->af_klist, set->af_nkeys, sizeof(Af_key), af_cmpfuncts[anum].func);
X }
X return (AF_OK);
X}
X
X/*================================================================
X * af_dropset -- drop set
X *
X *================================================================*/
X
XEXPORT af_dropset (set)
X Af_set *set;
X{
X register i;
X
X if (af_settest (set))
X SFAIL ("dropset", "", AF_EINVSET, ERROR);
X
X for (i=0; i<set->af_nkeys; i++)
X {
X /* decrease reference count in corresponding archive */
X VATTR((&(set->af_klist[i]))).af_nlinks--;
X if (--(set->af_klist[i].af_ldes)->af_refcount <= 0)
X (void) af_detlist (set->af_klist[i].af_ldes);
X }
X if (set->af_setlen > 0)
X free ((char *)set->af_klist);
X return (AF_OK);
X}
X
X/*================================================================
X * af_setgkey -- return key from set
X *
X *================================================================*/
X
XEXPORT af_setgkey (set, pos, key)
X Af_set *set;
X int pos;
X Af_key *key; /* out */
X{
X if (af_settest (set))
X SFAIL ("setgkey", "", AF_EINVSET, ERROR);
X
X if ((pos >= set->af_nkeys) || (pos < 0))
X SFAIL ("setgkey", "", AF_ENOPOS, ERROR);
X
X VATTR((&(set->af_klist[pos]))).af_nlinks++;
X (set->af_klist[pos].af_ldes)->af_refcount++;
X
X key->af_ldes = set->af_klist[pos].af_ldes;
X key->af_lpos = set->af_klist[pos].af_lpos;
X return (AF_OK);
X}
X
X/*================================================================
X * af_setaddkey -- add key to set
X *
X *================================================================*/
X
XEXPORT af_setaddkey (set, pos, key)
X Af_set *set;
X int pos;
X Af_key *key;
X{
X register i;
X
X if (af_settest (set))
X SFAIL ("setaddkey", "", AF_EINVSET, ERROR);
X if (af_keytest (key))
X SFAIL ("setaddkey", "", AF_EINVKEY, ERROR);
X if (((pos > set->af_nkeys) || (pos < 0)) && (pos != AF_LASTPOS))
X SFAIL ("setaddkey", "", AF_ENOPOS, ERROR);
X
X if (pos == AF_LASTPOS)
X pos = set->af_nkeys;
X
X /* if set is full, enlarge it */
X if (set->af_nkeys == set->af_setlen)
X {
X if (set->af_setlen == 0)
X {
X if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof(Af_key) * AF_SEGLEN))) == (Af_key *)0)
X FAIL ("setaddkey", "malloc", AF_ESYSERR, ERROR);
X }
X else
X {
X if ((set->af_klist = (Af_key *)realloc ((char *)set->af_klist, (unsigned) (sizeof(Af_key) * (set->af_setlen + AF_SEGLEN)))) == (Af_key *)0)
X FAIL ("setaddkey", "realloc", AF_ESYSERR, ERROR);
X }
X set->af_setlen += AF_SEGLEN;
X }
X
X for ( i=set->af_nkeys; i>pos; i--)
X set->af_klist[i] = set->af_klist[i-1];
X set->af_klist[pos] = *key;
X set->af_nkeys++;
X
X /* increase refcount */
X key->af_ldes->af_refcount++;
X VATTR(key).af_nlinks++;
X
X return (AF_OK);
X}
X
X/*================================================================
X * af_setrmkey -- remove key from set
X *
X *================================================================*/
X
XEXPORT af_setrmkey (set, key)
X Af_set *set;
X Af_key *key;
X{
X register i;
X bool found = FALSE;
X
X if (af_settest (set))
X SFAIL ("setrmkey", "", AF_EINVSET, ERROR);
X if (af_keytest (key))
X SFAIL ("setrmkey", "", AF_EINVKEY, ERROR);
X
X for (i=0; i<set->af_nkeys; i++)
X {
X if (!found)
X {
X if (!af_keycmp (&(set->af_klist[i]), key))
X found = TRUE;
X }
X else /* compress list */
X set->af_klist[i-1] = set->af_klist[i];
X }
X if (!found)
X SFAIL ("setrmkey", "", AF_ENOKEY, ERROR);
X set->af_nkeys--;
X VATTR(key).af_nlinks--;
X if (--key->af_ldes->af_refcount <= 0)
X (void) af_detlist (key->af_ldes);
X
X return (AF_OK);
X}
X
X/*================================================================
X * af_setposrmkey -- remove key (identified by position) from set
X *
X *================================================================*/
X
XEXPORT af_setposrmkey (set, pos)
X Af_set *set;
X int pos;
X{
X register i;
X
X if (af_settest (set))
X SFAIL ("setposrmkey", "", AF_EINVSET, ERROR);
X if ((pos >= set->af_nkeys) || (pos < 0))
X SFAIL ("setposrmkey", "", AF_ENOPOS, ERROR);
X
X VATTR((&(set->af_klist[pos]))).af_nlinks--;
X if (--(set->af_klist[pos].af_ldes)->af_refcount <= 0)
X (void) af_detlist (set->af_klist[pos].af_ldes);
X
X for (i=pos; i<set->af_nkeys-1; i++)
X set->af_klist[i] = set->af_klist[i+1];
X
X set->af_nkeys--;
X
X return (AF_OK);
X}
X
X/*================================================================
X * af_subset -- build subset
X *
X *================================================================*/
X
XEXPORT af_subset (set, attrbuf, newset)
X Af_set *set, *newset;
X Af_attrs *attrbuf;
X{
X register i, j=0, k=0;
X int match;
X Af_set tmpset;
X
X if (af_settest (set))
X SFAIL ("subset", "", AF_EINVSET, ERROR);
X
X /* allocate memory for new set */
X tmpset.af_setlen = set->af_nkeys;
X if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X FAIL ("subset", "malloc", AF_ESYSERR, ERROR);
X
X /* if there are no disqualifying attributes, add key to new set */
X for (i = 0; i < set->af_nkeys; i++)
X {
X /* if an attribute is set an does not match, continue with next key */
X /*** name ***/
X if ( (attrbuf->af_name[0] != '\0') &&
X (strcmp (attrbuf->af_name, VATTR((&(set->af_klist[i]))).af_name)) )
X continue;
X
X /*** type ***/
X if ( (attrbuf->af_type[0] != '\0') &&
X (strcmp (attrbuf->af_type, NOTNIL(VATTR((&(set->af_klist[i]))).af_type))) )
X continue;
X
X /*** syspath ***/
X if ( (attrbuf->af_syspath[0] != '\0') &&
X (strcmp (attrbuf->af_syspath, CATTR((&(set->af_klist[i]))).af_syspath)) )
X continue;
X
X /*** generation number ***/
X if ( (attrbuf->af_gen != AF_NOVNUM) &&
X (attrbuf->af_gen != VATTR((&(set->af_klist[i]))).af_gen) )
X continue;
X
X /*** revision number ***/
X if ( (attrbuf->af_rev != AF_NOVNUM) &&
X (attrbuf->af_rev != VATTR((&(set->af_klist[i]))).af_rev) )
X continue;
X
X /*** variant attribute ***/
X if ( (attrbuf->af_variant[0]) &&
X (strcmp (attrbuf->af_variant, NOTNIL(VATTR((&(set->af_klist[i]))).af_variant))) )
X continue;
X
X /*** state ***/
X if ( (attrbuf->af_state != AF_NOSTATE) &&
X (attrbuf->af_state != VATTR((&(set->af_klist[i]))).af_state) )
X continue;
X
X /*** owner ***/
X if ( (attrbuf->af_owner.af_username[0]) &&
X (strcmp (attrbuf->af_owner.af_username, CATTR((&(set->af_klist[i]))).af_ownname)) )
X continue;
X if ( (attrbuf->af_owner.af_userhost[0]) &&
X (strcmp (attrbuf->af_owner.af_userhost, CATTR((&(set->af_klist[i]))).af_ownhost)) )
X continue;
X
X /*** author ***/
X if ( (attrbuf->af_author.af_username[0]) &&
X (strcmp (attrbuf->af_author.af_username, VATTR((&(set->af_klist[i]))).af_auname)) )
X continue;
X if ( (attrbuf->af_author.af_userhost[0]) &&
X (strcmp (attrbuf->af_author.af_userhost, VATTR((&(set->af_klist[i]))).af_auhost)) )
X continue;
X
X /*** size ***/
X if ( (attrbuf->af_size != AF_NOSIZE) &&
X (attrbuf->af_size != VATTR((&(set->af_klist[i]))).af_fsize) )
X continue;
X
X /*** mode ***/
X if ( (attrbuf->af_mode != AF_NOMODE) &&
X (attrbuf->af_mode != VATTR((&(set->af_klist[i]))).af_mode) )
X continue;
X
X /*** locker ***/
X if ( (attrbuf->af_locker.af_username[0]) &&
X (strcmp (attrbuf->af_locker.af_username, NOTNIL(VATTR((&(set->af_klist[i]))).af_lckname))) )
X continue;
X if ( (attrbuf->af_locker.af_userhost[0]) &&
X (strcmp (attrbuf->af_locker.af_userhost, NOTNIL(VATTR((&(set->af_klist[i]))).af_lckhost))) )
X continue;
X
X /*** date of last modification ***/
X if ( (attrbuf->af_mtime != AF_NOTIME) &&
X (attrbuf->af_mtime != VATTR((&(set->af_klist[i]))).af_mtime) )
X continue;
X
X /*** date of last access ***/
X if ( (attrbuf->af_atime != AF_NOTIME) &&
X (attrbuf->af_atime != VATTR((&(set->af_klist[i]))).af_atime) )
X continue;
X
X /*** date of last status change ***/
X if ( (attrbuf->af_ctime != AF_NOTIME) &&
X (attrbuf->af_ctime != VATTR((&(set->af_klist[i]))).af_ctime) )
X continue;
X
X /*** saving date ***/
X if ( (attrbuf->af_stime != AF_NOTIME) &&
X (attrbuf->af_stime != VATTR((&(set->af_klist[i]))).af_stime) )
X continue;
X
X /*** date of last lock change ***/
X if ( (attrbuf->af_ltime != AF_NOTIME) &&
X (attrbuf->af_ltime != VATTR((&(set->af_klist[i]))).af_ltime) )
X continue;
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 are */
X /* attributes */
X match = TRUE;
X if ((attrbuf->af_udattrs[0][0] != '\0') ||
X (VATTR((&(set->af_klist[i]))).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((&(set->af_klist[i]))).af_uhtab))))
X {
X j++;
X }
X } /* if */
X if (match == FALSE)
X continue;
X } /* if */
X
X
X /* add key to new set */
X tmpset.af_klist[k] = set->af_klist[i];
X /* increase number of links in list descriptor */
X (tmpset.af_klist[k].af_ldes)->af_refcount++;
X VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X k++;
X
X } /* for */
X
X tmpset.af_nkeys = k;
X
X /* if the resulting set shall be stored in the old set */
X if (set == newset)
X {
X (void) af_dropset (set);
X *set = tmpset;
X }
X else
X *newset = tmpset;
X
X return (k);
X}
X
X
X/*================================================================
X * af_intersect -- build intersection of two sets
X *
X *================================================================*/
X
XEXPORT af_intersect (set1, set2, newset)
X Af_set *set1, *set2;
X Af_set *newset;
X{
X register i, j, k;
X Af_set tmpset;
X
X if (af_settest (set1) || af_settest (set2))
X SFAIL ("intersect", "", AF_EINVSET, ERROR);
X
X /* allocate enough memory */
X if (set1->af_nkeys >= set2->af_nkeys)
X tmpset.af_setlen = set1->af_nkeys;
X else
X tmpset.af_setlen = set2->af_nkeys;
X if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X FAIL ("intersect", "malloc", AF_ESYSERR, ERROR);
X
X /* build new set */
X k=0;
X for (i=0; i<set1->af_nkeys; i++)
X for (j=0; j<set2->af_nkeys; j++)
X {
X if (!af_keycmp (&(set1->af_klist[i]), &(set2->af_klist[j])))
X {
X tmpset.af_klist[k] = set1->af_klist[i];
X /* increase number of links in list descriptor */
X (tmpset.af_klist[k].af_ldes)->af_refcount++;
X VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X k++;
X }
X }
X tmpset.af_nkeys = k;
X
X /* if the new set shall be stored in one of the old ones */
X if (newset == set1)
X {
X (void) af_dropset (set1);
X *set1 = tmpset;
X }
X else
X {
X if (newset == set2)
X {
X (void) af_dropset (set2);
X *set2 = tmpset;
X }
X else
X *newset = tmpset;
X }
X
X return (k);
X}
X
X/*================================================================
X * af_union -- build union of two sets
X *
X *================================================================*/
X
XEXPORT af_union (set1, set2, newset)
X Af_set *set1, *set2;
X Af_set *newset;
X{
X register i, j, k;
X bool dbl=FALSE;
X Af_set tmpset;
X
X if (af_settest (set1) || af_settest (set2))
X SFAIL ("union", "", AF_EINVSET, ERROR);
X
X /* allocate enough memory */
X tmpset.af_setlen = set1->af_nkeys+set2->af_nkeys;
X if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X FAIL ("union", "malloc", AF_ESYSERR, ERROR);
X
X /* build new set */
X k=0;
X for (i=0; i<set1->af_nkeys; i++)
X {
X tmpset.af_klist[k] = set1->af_klist[i];
X /* increase number of links in list descriptor */
X (tmpset.af_klist[k].af_ldes)->af_refcount++;
X VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X k++;
X }
X for (j=0; j<set2->af_nkeys; j++)
X {
X for (i=0; i<set1->af_nkeys; i++)
X {
X if (!af_keycmp (&(tmpset.af_klist[i]), &(set2->af_klist[j])))
X dbl = TRUE;
X }
X if (dbl)
X dbl = FALSE;
X else
X {
X tmpset.af_klist[k] = set2->af_klist[j];
X /* increase number of links in list descriptor */
X (tmpset.af_klist[k].af_ldes)->af_refcount++;
X VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X k++;
X }
X }
X tmpset.af_nkeys = k;
X
X /* if the new set shall be stored in one of the old ones */
X if (newset == set1)
X {
X (void) af_dropset (set1);
X *set1 = tmpset;
X }
X else
X {
X if (newset == set2)
X {
X (void) af_dropset (set2);
X *set2 = tmpset;
X }
X else
X *newset = tmpset;
X }
X
X return (k);
X}
X
X/*================================================================
X * af_diff -- build difference between two sets
X *
X *================================================================*/
X
XEXPORT af_diff (set1, set2, newset)
X Af_set *set1, *set2;
X Af_set *newset;
X{
X register i, j, k;
X bool found = FALSE;
X Af_set tmpset;
X
X if (af_settest (set1) || af_settest (set2))
X SFAIL ("diff", "", AF_EINVSET, ERROR);
X
X /* allocate enough memory */
X tmpset.af_setlen = set1->af_nkeys;
X if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X FAIL ("diff", "malloc", AF_ESYSERR, ERROR);
X
X /* build new set */
X k=0;
X for (i=0; i<set1->af_nkeys; i++)
X {
X for (j=0; j<set2->af_nkeys; j++)
X {
X if (!af_keycmp (&(set1->af_klist[i]), &(set2->af_klist[j])))
X found = TRUE;
X }
X if (found)
X found = FALSE;
X else
X {
X tmpset.af_klist[k] = set1->af_klist[i];
X /* increase number of links in list descriptor */
X (tmpset.af_klist[k].af_ldes)->af_refcount++;
X VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X k++;
X }
X }
X tmpset.af_nkeys = k;
X
X /* if the new set shall be stored in one of the old ones */
X if (newset == set1)
X {
X (void) af_dropset (set1);
X *set1 = tmpset;
X }
X else
X {
X if (newset == set2)
X {
X (void) af_dropset (set2);
X *set2 = tmpset;
X }
X else
X *newset = tmpset;
X }
X
X return (k);
X}
END_OF_FILE
if test 19377 -ne `wc -c <'src/afs/afsets.c'`; then
echo shar: \"'src/afs/afsets.c'\" unpacked with wrong size!
fi
# end of 'src/afs/afsets.c'
fi
if test -f 'src/vc/vldovl.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/vc/vldovl.c'\"
else
echo shar: Extracting \"'src/vc/vldovl.c'\" \(18709 characters\)
sed "s/^X//" >'src/vc/vldovl.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 at coma.uucp or shape at db0tui62.bitnet
X */
X#ifndef lint
Xstatic char *AFSid = "$Header: vldovl.c[3.10] Thu Feb 23 18:14:47 1989 axel at 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/vldovl.c[3.4]
X * Thu Feb 23 18:14:48 1989 axel at coma published $
X * --- empty log message ---
X * vldovl.c[3.6] Thu Feb 23 18:14:48 1989 uli at coma published $
X * --- empty log message ---
X * vldovl.c[3.8] Thu Feb 23 18:14:48 1989 axel at coma published $
X * --- empty log message ---
X * vldovl.c[3.9] Thu Feb 23 18:14:48 1989 axel at coma save $
X * --- empty log message ---
X * vldovl.c[3.10] Thu Feb 23 18:14:48 1989 axel at coma published $
X * --- empty log message ---
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include <afs.h>
X#include "vl.h"
X
Xextern int immediate_output;
Xextern int version_number;
X
X/*
X * Global variables
X */
X
Xchar pathname_required = 0;
Xextern char vl_cwd[];
Xchar buf[1000];
Xchar *pending_name; /* Holds the name of a dir */
Xint dir_pending = 0;
X
XAf_attrs AF_attrbuf;
XAf_set AF_fileset;
Xchar error_string[80];
X
Xvoid InitAttrs (AF_attrbuf, name)
X Af_attrs *AF_attrbuf;
X char *name;
X /*
X * Initializes the attribute buffer.
X */
X
X{
X register int i;
X int vno;
X register char **udattrs;
X extern char *GetAuthoridFromAuthor(), *GetOwneridFromOwner(),
X *GetAuthorhostFromAuthor(), *GetOwnerhostFromOwner();
X char cstring[MAXNAMLEN], vstring[16];
X
X af_initattrs (AF_attrbuf);
X
X if (name && name[0] != '\0') {
X if (BoundVersion (name, cstring, vstring)) {
X /* This code kind of assumes, that directory names are not of */
X /* the kind 'dirname[2.9]' -- good luck! */
X vno = mkvno (vstring);
X AF_attrbuf->af_gen = gen(vno);
X AF_attrbuf->af_rev = rev(vno);
X (void)strcpy (AF_attrbuf->af_syspath, af_afpath (cstring));
X (void)strcpy (AF_attrbuf->af_name, af_afname (cstring));
X (void)strcpy (AF_attrbuf->af_type, af_aftype (cstring));
X /* No further options are considered in this case */
X }
X else { /* no bound version notation (e.g. foo.c[4.3]) for 'name' */
X if (IsDirectory (name)) {
X (void)strcpy (AF_attrbuf->af_syspath, name);
X }
X else { /* 'name' is not a directory */
X (void)strcpy (AF_attrbuf->af_syspath, af_afpath (name));
X (void)strcpy (AF_attrbuf->af_name, af_afname (name));
X (void)strcpy (AF_attrbuf->af_type, af_aftype (name));
X }
X }
X }
X /* Invariant: syspath, name and type fields of AF_attrbuf initialized */
X
X if (IsOptionSet(VL_O_UDAGIVEN)) {
X udattrs = GetUdattrs ();
X for (i = 0 ; udattrs[i] ; i++) {
X AF_attrbuf->af_udattrs[i] = udattrs[i];
X }
X }
X
X if (IsOptionSet(VL_O_VERSIONNUM)) {
X if (! (IsOptionSet(VL_O_HISTLOG) || IsOptionSet(VL_O_LOGMSG))) {
X if ((i = gen(version_number)) >= 0) {
X AF_attrbuf->af_gen = i;
X }
X if ((i = rev(version_number)) >= 0) {
X AF_attrbuf->af_rev = i;
X }
X }
X }
X
X if (IsOptionSet(VL_O_AUTHOR)) {
X (void)strcpy (AF_attrbuf->af_author.af_username, GetAuthoridFromAuthor());
X (void)strcpy (AF_attrbuf->af_author.af_userhost, GetAuthorhostFromAuthor());
X }
X
X if (IsOptionSet(VL_O_OWNER)) {
X (void)strcpy (AF_attrbuf->af_owner.af_username, GetOwneridFromOwner());
X (void)strcpy (AF_attrbuf->af_owner.af_userhost, GetOwnerhostFromOwner());
X }
X return;
X}
X
Xint PrintUDA (attrbuf)
X Af_attrs *attrbuf;
X{
X register char *cp;
X register int i;
X register char Checkbyte;
X register first_uda_printed;
X
X if ( (attrbuf->af_udattrs == NULL) || (attrbuf->af_udattrs[0] == '\0'))
X return 0; /* no user defined attributes */
X
X
X if (IsOptionSet(VL_O_LONGOUTPUT)) {
X PrintLongVinfo (attrbuf); printf (":\n");
X }
X else {
X PrintShortVinfo (attrbuf); printf (":");
X }
X
X if (IsOptionSet(VL_O_LISTUDALONG)) {
X Checkbyte = '\0';
X }
X else {
X Checkbyte = '=';
X }
X
X first_uda_printed = 0; /* nothing yet printed */
X
X for (i = 0; attrbuf->af_udattrs[i]; i++){
X cp = attrbuf->af_udattrs[i];
X
X if (!IsOptionSet(VL_O_LISTHIDDENUDAS) && IsHiddenUda (cp))
X continue;
X if (first_uda_printed) {
X (void)putchar (';'); /* seperate udas by ';' */
X }
X else {
X (void)putchar (' ');
X first_uda_printed = 1;
X }
X
X while (cp && *cp && *cp != Checkbyte) {
X if (*cp == AF_UDAVALDEL) {
X (void)putchar (','); /* seperate values of uda by ','
X */
X }
X else {
X (void)putchar (*cp);
X }
X cp++;
X }
X }
X (void)putchar ('\n');
X (void)fflush (stdout);
X return 1;
X}
X
XPrintVinfo (attrbuf)
X Af_attrs *attrbuf;
X{
X if (IsOptionSet(VL_O_LISTUDA|VL_O_LISTUDALONG)) {
X return PrintUDA (attrbuf);
X }
X
X if (IsOptionSet(VL_O_LONGOUTPUT)) {
X PrintLongVinfo (attrbuf);
X return 1;
X }
X
X PrintShortVinfo (attrbuf);
X return 1;
X}
X
XPrintShortVinfo (attrbuf)
X Af_attrs *attrbuf;
X{
X if (immediate_output) { /* set during option scanning */
X if (dir_pending) { /* now we can print the pending dir name */
X printf ("\n%s:\n", pending_name ? pending_name : "");
X dir_pending = 0;
X }
X
X printf ("%s%s%s%s%s%s%s%s",
X (pathname_required) ? attrbuf->af_syspath : "",
X (pathname_required) ? "/" : "",
X attrbuf->af_name,
X (attrbuf->af_type && (attrbuf->af_type[0] != '\0') ? "." : ""),
X attrbuf->af_type,
X GetVersionId (attrbuf->af_gen, attrbuf->af_rev),
X (IsOptionSet(VL_O_VERSIONSTATE)) ? " -> " : "",
X (IsOptionSet(VL_O_VERSIONSTATE)) ? GetVersionState (attrbuf->af_state)
X : "");
X }
X else {
X (void)sprintf (buf, "%s%s%s%s%s%s%s%s",
X (pathname_required) ? attrbuf->af_syspath : "",
X (pathname_required) ? "/" : "",
X attrbuf->af_name,
X (attrbuf->af_type && (attrbuf->af_type[0] != '\0') ? "." : ""),
X attrbuf->af_type,
X GetVersionId (attrbuf->af_gen, attrbuf->af_rev),
X (IsOptionSet(VL_O_VERSIONSTATE)) ? " -> " : "",
X (IsOptionSet(VL_O_VERSIONSTATE)) ? GetVersionState (attrbuf->af_state)
X : "");
X
X AddEntry (buf);
X }
X}
X
XPrintLongVinfo (attrbuf)
X Af_attrs *attrbuf;
X{
X if (immediate_output) { /* set during option scanning */
X char *p1 = NULL, *p2 = NULL;
X if (dir_pending) { /* now we can print the pending dir name */
X printf ("\n%s:\n", pending_name ? pending_name : "");
X dir_pending = 0;
X }
X/* This is the place to put out the name of eventual lockholders */
X printf ("%s %s %s %s %8d %s %s%s%s%s%s%s",
X GetMode (attrbuf->af_mode),
X GetVersionState (attrbuf->af_state),
X p1=GetUserInfo (&(attrbuf->af_owner)),
X (IsOptionSet(VL_O_AUTHOR))
X ? p2=GetUserInfo (&(attrbuf->af_author)) : "",
X attrbuf->af_size,
X (attrbuf->af_state > AF_BUSY) ? GetDate (attrbuf->af_stime)
X : GetDate (attrbuf->af_mtime),
X (pathname_required) ? attrbuf->af_syspath : "",
X (pathname_required) ? "/" : "",
X attrbuf->af_name,
X (attrbuf->af_type && (attrbuf->af_type[0] != '\0')) ? "."
X : "",
X attrbuf->af_type,
X GetVersionId (attrbuf->af_gen, attrbuf->af_rev));
X if (p1) free (p1);
X if (p2) free (p2);
X }
X else {
X (void)sprintf (buf, "%s %s %s %s %8d %s %s%s%s%s%s%s",
X GetMode (attrbuf->af_mode),
X GetVersionState (attrbuf->af_state),
X GetUserInfo (&(attrbuf->af_owner)),
X (IsOptionSet(VL_O_AUTHOR))
X ? GetUserInfo (&(attrbuf->af_author)) : "",
X attrbuf->af_size,
X (attrbuf->af_state > AF_BUSY) ? GetDate (attrbuf->af_stime)
X : GetDate (attrbuf->af_mtime),
X (pathname_required) ? attrbuf->af_syspath : "",
X (pathname_required) ? "/" : "",
X attrbuf->af_name,
X (attrbuf->af_type && (attrbuf->af_type[0] != '\0')) ? "."
X : "",
X attrbuf->af_type,
X GetVersionId (attrbuf->af_gen, attrbuf->af_rev));
X AddEntry (buf);
X }
X}
X
XReportVersionInfo (name)
X char *name;
X
X /*
X * Returns 0 if no info for name found, otherwise 1;
X */
X{
X register int i;
X int numhits, Bnumhits=0;
X int retcode = 1, rc; /* assume failure */
X char *cp;
X Af_set AF_sfileset, AF_bfileset;
X Af_key fkey;
X
X af_initset (&AF_sfileset);
X af_initset (&AF_bfileset);
X if (name && *name) {
X cp = af_afpath(name);
X if ( (! IsDirectory (name))
X && *cp
X && strcmp (cp, vl_cwd)) {
X /*
X * name is a normal file and is not in current working dir
X * require pathname on output
X */
X pathname_required = 1;
X }
X else {
X pathname_required = 0;
X }
X }
X if (IsOptionSet(VL_O_LASTVERS)) {
X rc=af_getkey (af_afpath (name), af_afname (name), af_aftype (name),
X AF_LASTVERS, AF_LASTVERS, "", &fkey);
X if (rc < 0) {
X numhits = 0;
X }
X else {
X af_setaddkey (&AF_sfileset, 0, &fkey);
X numhits = 1;
X }
X }
X else {
X InitAttrs (&AF_attrbuf, name);
X
X /* now go, and get some info.... */
X if ((numhits = af_find (&AF_attrbuf, &AF_sfileset)) == -1) {
X (void)sprintf (error_string,
X "%s: in ReportVersionInfo(): af_find (%s)",
X GetProgramName (), name);
X af_perror (error_string);
X return (1); /*exit (1);*/
X }
X if (IsOptionSet(VL_O_LISTBINARY)) {
X if ((Bnumhits = af_bpfind (&AF_attrbuf, &AF_bfileset)) == -1) {
X (void)sprintf (error_string,
X "%s: in ReportVersionInfo(): af_find (%s)",
X GetProgramName (), name);
X af_perror (error_string);
X return (1); /*exit (1);*/
X }
X }
X }
X if (af_union (&AF_sfileset, &AF_bfileset, &AF_fileset) < 0) {
X af_perror ("af_union");
X return 1;
X }
X numhits += Bnumhits;
X af_dropset (&AF_sfileset);
X af_dropset (&AF_bfileset);
X /* nothing found ? */
X if (numhits == 0) {
X if (!IsOptionSet(VL_O_BEQUIET)) {
X if (name && *name) {
X if (! FileExists (name)) {
X printf ("%s: %s: nothing appropriate found\n", GetProgramName (), name);
X }
X }
X }
X VinfoCleanup ();
X return 1; /* report failure */
X }
X
X if ((*name != '\0') && IsDirectory (name)) {
X if (immediate_output) {
X /*
X * dir name must be printed, iff
X * something is found. But we can determine
X * this not yet.
X */
X dir_pending = 1;
X pending_name = name;
X }
X else
X AddClist (name);
X }
X
X /*
X * sort by name and version number. Busy version first then
X * versions with increasing version numbers.
X */
X
X if (af_sortset (&AF_fileset, AF_ATTHUMAN) == -1) {
X (void)sprintf (error_string,
X "%s: in ReportVersionInfo(): af_sortset by AF_ATTHIMAN",
X GetProgramName);
X af_perror (error_string);
X exit (1);
X }
X
X for (i = 0; i < AF_fileset.af_nkeys; i++) {
X if (af_gattrs (&(AF_fileset.af_klist[i]), &AF_attrbuf) == -1) {
X (void)sprintf (error_string, "%s: in ReportVersionInfo(): af_gattrs");
X af_perror (error_string);
X exit (1);
X }
X else {
X if (IsHiddenFile(&AF_attrbuf) && !IsOptionSet(VL_O_LISTHIDDEN))
X continue;
X
X if (IsOptionSet(VL_O_STATEGIVEN)) {
X if (!MatchesVersionStates (&AF_attrbuf))
X continue;
X }
X
X if (!IsOptionSet(VL_O_BEQUIET)) {
X if (IsOptionSet(VL_O_LOGMSG)) {
X if (IsInHistoryLogMsgList (&AF_attrbuf)) {
X if (PrintVinfo (&AF_attrbuf)) {
X (void)putchar (':'); (void)putchar ('\n');
X PrintLogMsg (&(AF_fileset.af_klist[i]));
X retcode = 0; /* success */
X }
X }
X }
X else {
X (void)PrintVinfo (&AF_attrbuf);
X retcode = 0; /* success */
X }
X }
X }
X }
X/* VinfoCleanup (); */
X return retcode;
X}
X
XInitReportVersion ()
X{
X InitCList ();
X}
X
Xint PrintLogMsg (key)
X Af_key *key;
X{
X register char *logmsg;
X
X if ((logmsg = af_rnote (key)) == NULL) {
X (void)sprintf (error_string, "%s: af_rnote", GetProgramName ());
X af_perror (error_string);
X exit (1);
X }
X
X printf ("%s", logmsg);
X if (logmsg[strlen(logmsg)-1] != '\n') {
X (void)putchar ('\n');
X (void)fflush (stdout);
X }
X free (logmsg);
X
X}
X
Xint IsInHistoryLogMsgList (attrbuf)
X Af_attrs *attrbuf;
X{
X if (attrbuf->af_state == AF_BUSY)
X return 0; /* is busy version */
X if (IsOptionSet(VL_O_HISTLOG) &&
X ! IsOptionSet(VL_O_VERSIONNUM))
X return 1;
X
X if (!IsOptionSet(VL_O_HISTLOG|VL_O_VERSIONNUM))
X return 1;
X else {
X if (IsOptionSet(VL_O_HISTLOGPLUS)) {
X if (attrbuf->af_gen > gen(version_number))
X return 1;
X if ((gen(version_number) == attrbuf->af_gen) &&
X (attrbuf->af_rev > rev(version_number)))
X return 1;
X }
X else {
X if (attrbuf->af_gen < gen(version_number))
X return 1;
X if ((gen(version_number) == attrbuf->af_gen) &&
X (attrbuf->af_rev < rev(version_number)))
X return 1;
X }
X if ((gen(version_number) == attrbuf->af_gen) &&
X (rev(version_number) == attrbuf->af_rev)) return 1;
X }
X return 0;
X}
X
Xstruct entry {
X char *repr;
X struct entry *next;
X};
X
Xstruct clist { /* column list */
X char *dir; /* name of dir */
X struct entry *entry;
X struct clist *next;
X};
X
Xstruct clist *clistroot;
Xstruct clist *curclist;
Xstruct entry *curentry;
X
XInitCList ()
X{
X if ((clistroot = (struct clist*) malloc (sizeof (struct clist))) == NULL) {
X (void)strcpy (error_string, "in InitClist (): malloc,1");
X perror (error_string);
X exit (1);
X }
X
X clistroot->dir = NULL; /* has never a name */
X
X/* if ((clistroot->next = (struct clist*) malloc (sizeof (struct clist)))
X == NULL) {
X (void)strcpy (error_string, "in InitClist (): malloc,2");
X perror (error_string);
X exit (1);
X }
X */
X clistroot->next = NULL;
X curclist = clistroot;
X
X if ((curentry = (struct entry*) malloc (sizeof (struct entry))) == NULL) {
X (void)strcpy (error_string, "in InitClist (): malloc,3");
X perror (error_string);
X exit (1);
X }
X curentry->repr = NULL;
X curentry->next = NULL;
X
X clistroot->entry = curentry;
X}
X
XAddClist (name)
X char *name;
X{
X struct clist *this_clist;
X
X if ((this_clist = (struct clist*) malloc (sizeof (struct clist))) == NULL) {
X (void)strcpy (error_string, "in AddCList (): malloc,1");
X perror (error_string);
X exit (1);
X }
X
X if ((this_clist->dir = malloc ((unsigned)(strlen (name)+1))) == NULL) {
X (void)strcpy (error_string, "in AddCList (): malloc,2");
X perror (error_string);
X exit (1);
X }
X
X if ((this_clist->entry = (struct entry*) malloc (sizeof (struct entry)))
X == NULL) {
X (void)strcpy (error_string, "in AddCList (): malloc,2");
X perror (error_string);
X exit (1);
X }
X
X (void)strcpy (this_clist->dir, name);
X this_clist->next = NULL;
X curentry = this_clist->entry;
X curentry->repr = NULL;
X curentry->next = NULL;
X
X curclist->next = this_clist;
X curclist = this_clist;
X
X}
X
XAddEntry (str)
X char *str;
X{
X struct entry* this_entry;
X
X if ((curentry->repr = malloc ((unsigned)(strlen (str)+1))) == NULL) {
X (void)strcpy (error_string, "in AddEntry (): malloc,2");
X perror (error_string);
X exit (1);
X }
X
X (void)strcpy (curentry->repr, str);
X
X if ((this_entry = (struct entry*) malloc (sizeof (struct entry))) == NULL) {
X (void)strcpy (error_string, "in AddEntry (): malloc,1");
X perror (error_string);
X exit (1);
X }
X
X this_entry->repr = NULL;
X this_entry->next = NULL;
X curentry->next = this_entry;
X curentry = this_entry;
X}
X
Xint computemaxlength (root)
X struct entry *root;
X{
X struct entry *this_entry;
X int length = 0, maxlength = 0;
X
X if (!root) return 0;
X
X for (this_entry = root;
X this_entry->repr && this_entry->next;
X this_entry = this_entry->next) {
X length = strlen (this_entry->repr);
X if (length > maxlength) {
X maxlength = length;
X }
X }
X return maxlength;
X}
X
XPrintList (root, wordsperline, colwidth, newline_required, group_it)
X struct clist *root;
X int wordsperline, colwidth, newline_required, group_it;
X{
X struct entry *this_entry;
X int nwordsprinted = 0; /* number of words per line yet printed */
X int ntabs = 0;
X int length;
X
X if (/*root->entry && */root->entry->repr) {
X if (root->dir) {
X if (newline_required) (void)putchar ('\n');
X
X printf ("%s:\n", root->dir);
X }
X }
X
X if (!group_it) {
X for (this_entry = root->entry;
X this_entry->repr && this_entry->next;
X this_entry = this_entry->next) {
X printf ("%s\n", this_entry->repr);
X }
X }
X else {
X for (this_entry = root->entry;
X this_entry->repr && this_entry->next;
X this_entry = this_entry->next) {
X nwordsprinted++;
X if (!(nwordsprinted % wordsperline)) { /* if last word in this line */
X printf ("%s\n", this_entry->repr);
X }
X else {
X printf ("%s", this_entry->repr);
X
X /* compute #tabs to get to the next word position */
X length = strlen (this_entry->repr);
X ntabs = (colwidth - length) / 8;
X if ((colwidth - length) % 8)
X ntabs++;
X
X while (ntabs--) (void)putchar ('\t');
X }
X }
X if (nwordsprinted % wordsperline) printf ("\n");
X }
X}
X
XFlushIt (root)
X struct clist *root;
X{
X struct clist *this_clist;
X int colwidth = 0, wordsperline = 0;
X int maxlength = 0, newline_required = 0;
X
X for (this_clist = root; this_clist; this_clist = this_clist->next) {
X
X if (this_clist->entry && (this_clist->entry->repr == (char *) NULL))
X continue; /* skip empty list */
X
X if (multicol_output_is_possible ()) {
X /* compute length of longest word in this list */
X maxlength = computemaxlength (this_clist->entry);
X
X /* compute length to next tab stop */
X colwidth = (maxlength / 8) + 1;
X colwidth *= 8;
X
X /* compute # words that fit in a line */
X#define maxcol 80
X if (!(wordsperline = maxcol / colwidth)) wordsperline++;
X
X }
X
X PrintList (this_clist, wordsperline, colwidth, newline_required,
X multicol_output_is_possible ());
X newline_required++;
X }
X}
X
Xvoid FlushInfo ()
X{
X if (!immediate_output)
X FlushIt (clistroot); /* Print now */
X}
END_OF_FILE
if test 18709 -ne `wc -c <'src/vc/vldovl.c'`; then
echo shar: \"'src/vc/vldovl.c'\" unpacked with wrong size!
fi
# end of 'src/vc/vldovl.c'
fi
echo shar: End of archive 21 \(of 33\).
cp /dev/null ark21isdone
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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list