rsalz@uunet.uu.net (Rich Salz) (06/05/89)
Submitted-by: Axel Mahler <unido!coma!axel> Posting-number: Volume 19, Issue 29 Archive-name: shape/part16 #! /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 16 (of 33)." # Contents: src/afs/afenviron.c src/misc/citeattr.c src/vc/vlmisc.c # Wrapped by rsalz@papaya.bbn.com on Thu Jun 1 19:27:08 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/afs/afenviron.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/afs/afenviron.c'\" else echo shar: Extracting \"'src/afs/afenviron.c'\" \(15493 characters\) sed "s/^X//" >'src/afs/afenviron.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 * afenviron.c -- communication with the UNIX-Filesystem X * X * Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP) X * (andy@db0tui62.BITNET) X * X * $Header: afenviron.c[1.6] Wed Feb 22 16:27:29 1989 andy@coma published $ X * X * EXPORT: X * af_uniqpath -- build unified pathname X * af_setarchpath -- name directory where archives shall be stored X * af_isarchive -- test if a given file is an archive X * af_garname -- build name for archive file X * af_garown -- get owner of archive file X * af_gbpname -- build name for binary pool db-file X * af_gtmpname -- build name for tmp file X * af_gbusname -- build name of busy version X * af_afpath -- build af-syspath from UNIX-filename X * af_afname -- build af-filename from UNIX-filename X * af_aftype -- build af-filetype from UNIX-filename X * af_unixname -- build UNIX-filename from af-filename/type X * af_gmaxbpsize -- get max. number of files in binary pool X * af_bpfilename -- return filename for binary pool file X * af_rbphashname -- get unique filename for file in binary pool X * af_getuid -- returns uid of user if from local host X * af_getgid -- returns gid of user if from local host X * af_getuser -- returns name and host of caller X */ X X#include <stdio.h> X#include <pwd.h> X#include <string.h> X#ifdef SUNOS_4_0 X#include <strings.h> X#endif X#include <sys/file.h> X#include <sys/types.h> X#include <sys/stat.h> X X#include "typeconv.h" X#include "afsys.h" X#include "afs.h" X#include "afarchive.h" X Xchar *malloc(); X X/*================================================================ X * af_uniqpath -- build unified pathname X * X *================================================================*/ X XEXPORT char *af_uniqpath (path) X char *path; X{ X static char uniqpath[4*MAXNAMLEN], tmppath[4*MAXNAMLEN]; X char *p, *u, *getwd(); X X if ((path == (char *)0) || (path[0] == '\0') || ((path[0] == '.' && path[1] == '\0'))) X return (getwd (uniqpath)); X X /* build absolute pathname if only a relative one is given */ X if (path[0] != '/') X { X if (!strcmp (path, "..")) X { X (void) getwd (uniqpath); X if ((p = rindex (uniqpath, '/')) == uniqpath) X uniqpath[1] = '\0'; X else X *p = '\0'; X return (uniqpath); X } X (void) getwd (tmppath); X (void) strcat (tmppath, "/"); X (void) strcat (tmppath, path); X p = tmppath; X } X else X p = path; X X /* eliminate things like "/usr/./bin" and "/usr/../usr/bin" */ X u = uniqpath; X *u = '/'; X while (*p) X { X if ((p[0] == '/') && (p[1] == '.')) X { X if ((p[2] == '/') || (p[2] == '\0')) X { X p = &p[2]; X continue; X } X else X if ((p[2] == '.') && ((p[3] == '/') || (p[3] == '\0'))) X { X if (u != uniqpath) X do { *u = '\0'; u--; } while (*u != '/'); X p = &p[3]; X continue; X } X } X u++; X *u = p[1]; X p++; X } X X /* cut slash if present at the end */ X u--; X if ((u != uniqpath) && (*u == '/')) X *u = '\0'; X else X u[1] = '\0'; X X return (uniqpath); X} X Xstatic char archpath[4*MAXNAMLEN] = "\0"; X X/*================================================================ X * af_setarchpath X * X *================================================================*/ X XEXPORT af_setarchpath (pathname) X char *pathname; X{ X if (pathname == (char *)0) X archpath[0] = '\0'; X else X (void) strcpy (archpath, af_uniqpath (pathname)); X} X X X/*==================================================================== X * af_isarchive -- test if a given file is an archive X * X *====================================================================*/ X XEXPORT af_isarchive (name) X char *name; X{ X char ext; X X if (!name || strncmp (name, AF_AFSFILEID, AF_IDSTRLEN)) X return (FALSE); X X ext = name[strlen (name) - sizeof (char)]; X if ((ext != AF_ARCHEXT) && (ext != AF_DATAEXT)) X return (FALSE); X X return (TRUE); X} X X X/*================================================================ X * af_garname X * X *================================================================*/ X XEXPORT char *af_garname (pathname, name, type) X char *pathname; X char *name, *type; X{ X char arname[MAXNAMLEN*4]; X X /* see if there is an explicit pathname where archives shall be stored */ X if (archpath[0]) X (void) strcpy (arname, archpath); X else X (void) sprintf (arname, "%s/%s\0", NOTNIL(pathname), AF_SUBDIR); X X if ((type != (char *)0) && (type[0] != '\0')) X (void) sprintf (&arname[strlen (arname)], "/%s%s.%s%c\0", X AF_AFSFILEID, NOTNIL(name), NOTNIL(type), AF_ARCHEXT); X else X (void) sprintf (&arname[strlen (arname)], "/%s%s%c\0", X AF_AFSFILEID, NOTNIL(name), AF_ARCHEXT); X X return (af_entersym (arname)); X} /* af_garname */ X X X/*================================================================ X * af_garown X * X *================================================================*/ X XEXPORT Af_user *af_garown (archname, writeok) X char *archname; X bool *writeok; /* out */ X{ X char ardirname[MAXNAMLEN*4], *namptr; X struct stat ibuf; X X /* build name of directory, where the archive is located */ X (void) strcpy (ardirname, archname); X X /* cut name */ X namptr = rindex (ardirname, '/'); X *namptr = '\0'; X X *writeok = FALSE; X if (stat (ardirname, &ibuf) == ERROR) X return ((Af_user *)0); X else X if (!af_sysaccess (ardirname, W_OK)) X *writeok = TRUE; X X return (af_getuser (ibuf.st_uid)); X} /* af_garown */ X X X/*================================================================ X * af_gbpname X * X *================================================================*/ X XEXPORT char *af_gbpname (pathname) X char *pathname; X{ X char bpname[MAXNAMLEN*4]; X X /* see if there is an explicit pathname where archives shall be stored */ X if (archpath[0]) X (void) strcpy (bpname, archpath); X else X (void) sprintf (bpname, "%s/%s/\0", pathname, AF_SUBDIR); X X if (af_sysaccess (bpname, R_OK)) X return ((char *)0); X X (void) strcat (bpname, AF_BPOOLNAME); X X return (af_entersym (bpname)); X} /* af_garname */ X X X/*================================================================ X * af_gtmpname X * X *================================================================*/ X Xstatic int count=0; X XEXPORT char *af_gtmpname (pathname, filename) X /*ARGSUSED*/ X char *pathname; /* unused up to now */ X char *filename; X{ X char tmpname[MAXNAMLEN*4]; X X (void) sprintf (tmpname, "%s/%s%d%d\0", AF_TMPDIR, filename, getpid(), count++); X return (af_entersym (tmpname)); X} /* af_gtmpname */ X X X/*================================================================ X * af_gbusname X * X *================================================================*/ X XEXPORT char *af_gbusname (pathname, name, type) X char *pathname; X char *name, *type; X{ X char busyname[MAXNAMLEN*4]; X X (void) sprintf (busyname, "%s/%s", pathname, name); X if ((type != (char *)0) && (type[0] != '\0')) X { X (void) strcat (busyname, "."); X (void) strcat (busyname, type); X } X return (af_entersym (busyname)); X} /* af_gbusname */ X X X X/*================================================================ X * af_afpath X * X *================================================================*/ X XEXPORT char *af_afpath (unixname) X char *unixname; X{ X char *nameptr; X static char afpath[MAXNAMLEN]; X X if (unixname) X (void) strcpy (afpath, unixname); X else X afpath[0] = '\0'; X X /* cut name */ X if ((nameptr = rindex (afpath, '/')) != (char *)0) X nameptr[0] = '\0'; X else X { X afpath[0] = '\0'; X return (afpath); X } X X /* cut AFS subdirectory name if present */ X if (((nameptr = rindex (afpath, '/')) != (char *)0) && X !strcmp (AF_SUBDIR, nameptr+1)) X nameptr[0] = '\0'; X else X if (!strcmp (AF_SUBDIR, afpath)) X afpath[0] = '\0'; X X return (afpath); X} X X/*================================================================ X * af_afname X * X *================================================================*/ X XEXPORT char *af_afname (unixname) X char *unixname; X{ X char *typeptr, *nameptr; X static char afname[MAXNAMLEN]; X X if (!unixname) X { X afname[0] = '\0'; X return (afname); X } X X /* set nameptr to beginning of name */ X if ((nameptr = rindex (unixname, '/')) == (char *)0) X nameptr = unixname; X else X nameptr++; X X if (af_isarchive (nameptr)) X { X (void) strcpy (afname, nameptr + strlen (AF_AFSFILEID)); X afname[strlen (afname) - sizeof (char)] = '\0'; X } X else X (void) strcpy (afname, nameptr); X X /* special handling for "." and ".." */ X if (!strcmp (afname, ".") || !strcmp (afname, "..")) X return (afname); X X /* if a UNIX type-extension is given -- cut it, except the dot is */ X /* at position 0 (e.g. .cshrc) */ X if ((typeptr = rindex (afname, '.')) != (char *)0) X if (typeptr != afname) X typeptr[0] = '\0'; X X return (afname); X} X X/*================================================================ X * af_aftype X * X *================================================================*/ X XEXPORT char *af_aftype (unixname) X char *unixname; X{ X char *typeptr, *nameptr; X static char aftype[MAXTYPLEN]; X bool isarch = FALSE; X X if (!unixname) X { X aftype[0] = '\0'; X return (aftype); X } X X /* set nameptr to beginning of name */ X if ((nameptr = rindex (unixname, '/')) == (char *)0) X nameptr = unixname; X else X nameptr++; X X if (af_isarchive (nameptr)) X { X nameptr += strlen (AF_AFSFILEID); X isarch = TRUE; X } X X /* if there is no UNIX type-extension */ X if ((typeptr = rindex (nameptr, '.')) == (char *)0) X aftype[0] = '\0'; X else X { X /* if the found dot indicates a "hidden file" (eg. .cshrc) */ X if (typeptr == nameptr) X aftype[0] = '\0'; X else X { X (void) strcpy (aftype, typeptr + sizeof(char)); X /* if the named file is an archive, cut the name-extension */ X if (isarch) X aftype [strlen (aftype) - sizeof (char)] = '\0'; X } X } X return (aftype); X} X X X/*================================================================ X * af_unixname X * X *================================================================*/ X XEXPORT char *af_unixname (path, name, type) X char *path, *name, *type; X{ X static char unixname[4*MAXNAMLEN]; X X if ((path == (char *)0) || (path[0] == '\0')) X (void) strcpy (unixname, NOTNIL(name)); X else X (void) sprintf (unixname, "%s/%s\0", path, name); X X if ((type != (char *)0) && (type[0] != '\0')) X { X (void) strcat (unixname, "."); X (void) strcat (unixname, type); X } X return (unixname); X} X X X/*================================================================ X * af_gmaxbpsize -- get max. number of files in binary pool X * X *================================================================*/ X XEXPORT int af_gmaxbpsize (name) X /*ARGSUSED*/ X char *name; /* unused up to now */ X{ X char *envval, *getenv(); X X if (envval = getenv (AF_ENVBPSIZE)) X return (atoi (envval)); X else X return AF_MAXBPSIZE; X} X X X/*================================================================ X * af_bpfilename X * X *================================================================*/ X XEXPORT char *af_bpfilename (pathname, name) X char *pathname, *name; X{ X static char bpname[MAXNAMLEN]; X X (void) sprintf (bpname, "%s/%s/%s\0", pathname, AF_SUBDIR, name); X return (bpname); X} X X/*================================================================ X * af_rbphashname -- get unique filename for file in binary pool X * X *================================================================*/ X XEXPORT char *af_rbphashname (name, type, gen, rev, variant, list, count) X char *name, *type, *variant; X int gen, rev; X /*ARGSUSED*/ X Af_revlist *list; /* unused up to now */ X int count; X{ X char hashname[MAXNAMLEN]; X X (void) sprintf (hashname, "%s%s.%s[%d.%d]%s%d\0", AF_BPFILEID, X name, type, gen, rev, variant, count); X X return (af_entersym (hashname)); X} X X X/*======================================================================== X * af_getuid - returns uid of user if from local host X * AF_ERROR if user is unknown X * AF_REMOTE if user is not local X * X *========================================================================*/ X XEXPORT Uid_t af_getuid (name, host) X char *name, *host; X{ X struct passwd *pwent; X X if (name == (char *)0) /* in this case, name and host are null pointers */ X return ((Uid_t) ERROR); X X if (strcmp (af_gethostname(), host)) X return ((Uid_t) AF_REMOTE); X X if ((pwent = getpwnam (name)) == (struct passwd *)0) X FAIL ("getuid", "cannot get user ID", AF_EINTERNAL, (Uid_t) ERROR); X X return (pwent->pw_uid); X} X X X/*======================================================================== X * af_getgid - returns gid of user if from local host X * AF_ERROR if user is unknown X * AF_REMOTE if user is not local X * X *========================================================================*/ X XEXPORT Gid_t af_getgid (name, host) X char *name, *host; X{ X struct passwd *pwent; X X if (name == (char *)0) /* in this case, name and host are null pointers */ X return ((Gid_t) ERROR); X X if (strcmp (af_gethostname(), host)) X return ((Gid_t) AF_REMOTE); X X if ((pwent = getpwnam (name)) == (struct passwd *)0) X FAIL ("getgid", "cannot get group ID", AF_EINTERNAL, (Gid_t) ERROR); X X return (pwent->pw_gid); X} X X X/*======================================================================== X * af_getuser - returns name and host of caller X * X *========================================================================*/ X Xstatic Uid_t calleruid; Xstatic Af_user caller; Xstatic bool initcaller = FALSE; X XEXPORT Af_user *af_getuser (uid) X Uid_t uid; X{ X static Af_user result; X struct passwd *pwent; X X if (!initcaller) /* if caller struct is not yet initialized */ X { X calleruid = getuid(); X (void) strcpy (caller.af_userhost, af_gethostname ()); X if ((pwent = getpwuid ((int) calleruid)) == (struct passwd *)0) X SFAIL ("getuser", "", AF_EINVUSER, (Af_user *)0); X (void) strcpy (caller.af_username, pwent->pw_name); X initcaller = TRUE; X } X if (uid == calleruid) X return (&caller); X X (void) strcpy (result.af_userhost, af_gethostname ()); X if ((pwent = getpwuid ((int) uid)) == (struct passwd *)0) X SFAIL ("getuser", "", AF_EINVUSER, (Af_user *)0); X (void) strcpy (result.af_username, pwent->pw_name); X X return (&result); X} END_OF_FILE if test 15493 -ne `wc -c <'src/afs/afenviron.c'`; then echo shar: \"'src/afs/afenviron.c'\" unpacked with wrong size! fi # end of 'src/afs/afenviron.c' fi if test -f 'src/misc/citeattr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/misc/citeattr.c'\" else echo shar: Extracting \"'src/misc/citeattr.c'\" \(14280 characters\) sed "s/^X//" >'src/misc/citeattr.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ Xstatic char *AFSid = "$Header: citeattr.c[1.6] Thu Feb 23 21:24:18 1989 axel@coma published $"; X X/* X * Log for /u/shape/dist-tape/src/misc/citeattr.c[1.1] X * Thu Feb 23 21:24:18 1989 axel@coma save $ X * --- empty log message --- X * citeattr.c[1.2] Thu Feb 23 21:24:18 1989 axel@coma save $ X * --- empty log message --- X * citeattr.c[1.3] Thu Feb 23 21:24:18 1989 axel@coma save $ X * --- empty log message --- X * citeattr.c[1.4] Thu Feb 23 21:24:18 1989 axel@coma published $ X * Threw out silly #ifdef BSD43 s. X * I think there are also other changes concerning attribute citations. X * X * citeattr.c[1.5] Thu Feb 23 21:24:18 1989 axel@coma published $ X * --- empty log message --- X * citeattr.c[1.6] Thu Feb 23 21:24:18 1989 axel@coma published $ X * --- empty log message --- X */ X X#include <pwd.h> X#include <grp.h> X#include <stdio.h> X#include <strings.h> X#include "afs.h" X#include "afsapp.h" X#include "anames.h" X Xchar *st_table[] = { X "busy", "save", "proposed", X "published", "accessed", "frozen", X (char *)0 X }; X XWriteXPand (buf, bufcnt, dest, curkey) X char *buf; int bufcnt; FILE *dest; Af_key *curkey; { X/* X * WriteXPand scans the char buffer 'buf' to the extent of bufcnt X * for strings of the form '$__attribute_name'. If such a string X * is found, the buffer contents up to the character preceding the X * first '$' will be sent to the destination output 'dest'. X * If an attribute with name 'atttribute_name' is set for the current X * attribute file, the citation-string will be substituted by the value X * of that attribute. Output of 'buf' contents resumes with the first X * character after the blank delimiting the 'attribute_name'. X * There are two built-in pseudo-attributes, 'Header' and 'Log' which X * are substituted by a version header in RCS style or a log-history X * respectively. Lines of the log-history are preceded by a 'comment X * leader' symbol, defined as user-defined attribute CLEAD. X * Header and Log are ended by newline characters. X */ X short stat=0, incite=0, gotattrs=0; X char attrcitebuf[128]; X Af_attrs allattrs; X register int i, j, k; X char *bufp = buf, *attrname = attrcitebuf+3, X *spt, *ept; X X i = 0; X X spt = ept = buf; X X while (i < bufcnt) { X X switch (buf[i]) { X /* scan attribute citation marker */ X case '$': X if (stat) ept = &(buf[i]); X stat = 1; X attrcitebuf[0] = '$'; X break; X case '_': X switch (stat) { X case 0: X ept++; X break; X case 1: X case 2: X attrcitebuf[stat++] = '_'; X break; X } X break; X default: X if (stat) X ept = &(buf[i+1]); X else X ept++; X stat = 0; X break; X } X X if (stat == 3) { /* lets see if there's an attribute citation */ X /* assertion: i is index of 2nd '_' */ X if ((i < bufcnt-1) && (buf[i+1] != ' ')) { X stat = 0; X /* ... yes, there seems to be one */ X i++; incite = 0; X if (af_gattrs (curkey, &allattrs) < 0) { X af_perror ("af_gattrs"); X return; X } X gotattrs = 1; X while ((!index (" \n\t$", buf[i])) && (i < bufcnt)) X attrname[incite++] = buf[i++]; X if (i < bufcnt) { X /* i points to first char after attribute name */ X if (buf[i] == '$') { /* consider '$' part of attr-name */ X attrname[incite++] = '$'; i++; X } X attrname[incite] = '\0'; X /* write out everything up to beginning of cite_mark */ X fwrite (spt, sizeof (*buf), ept - spt, dest); X spt = ept = &(buf[i]); X if (!substitute (attrname, curkey, &allattrs, dest)) X fputs (attrcitebuf, dest); X incite = 0; X } X else { X attrname[incite] = '\0'; X fwrite (spt, sizeof (*buf), ept - spt, dest); X spt = ept = &(buf[i]); X if (!substitute (attrname, curkey, &allattrs, dest)) X fputs (attrcitebuf, dest); X } X } X else { /* blank after citemark or buffer exceeded */ X fputs ("$__", dest); X } X i--; X } X i++; X } X /* Ok, we've had it -- send remaining chars to dest */ X fwrite (spt, sizeof (*buf), ept - spt, dest); X if (gotattrs) { X i = 0; X while (allattrs.af_udattrs[i]) free (allattrs.af_udattrs[i++]); X } X } X X Xstatic substitute (attrname, afkey, afattrs, dest) X char *attrname; Af_key *afkey; Af_attrs *afattrs; FILE *dest; { X /* X * This procedure tries to substitute the occurrence of the X * given attribute name by the corresponding value stored with the X * attribute file version denoted by afkey. The substituted X * value is printed on dest. If 'attrname' actually is the name X * of an attribute and the last character in the name is '$' X * it will be deleted. In case that attrname is not a known X * attributename, nothing happens and a value of 0, indicating X * that no substitution took place, will be returned. Nonzero X * return means successful substitution. X */ X char *ap, *p, clead[32], *note, *IsAStdAttr(); X register char *lp, *ep, *l; X Af_attrs retbuf; X Af_set kset; X Af_key thiskey; X int cgen, crev, tgen, setsz, title_printed = FALSE; X register int k; X X if (l = index (attrname, '$')) *l = '\0'; X if (ap = IsAStdAttr (attrname, afattrs)) { X fputs (ap, dest); X return TRUE; X } X if (strcmp (attrname, HEADER)) { X if (strcmp (attrname, LOG)) { X ap = af_rudattr (afkey, attrname); X if (ap > 0) { X fputs (ap, dest); X free (ap); X return TRUE; X } X if (l) *l = '$'; /* restore '$' if 'attrname' unknown */ X return FALSE; X } X else { /* fill in the logs */ X /* we've got to find all preceding versions */ X X af_initattrs (&retbuf); X strcpy (retbuf.af_syspath, p=af_rsyspath (afkey)); X free (p); X strcpy (retbuf.af_name, p=af_rname (afkey)); X free (p); X strcpy (retbuf.af_type, p=af_rtype (afkey)); X free (p); X af_find (&retbuf, &kset); X af_sortset (&kset, AF_ATTVERSION); X cgen = af_rgen (afkey); X crev = af_rrev (afkey); X setsz = af_nrofkeys (&kset); X X /* determine comment leader sym to prepend it to loglines */ X p = af_rudattr (afkey, CLEAD); X if (p) { X strcpy (clead, p); X } X else clead[0] = '\0'; X free (p); X X /* write log for each version up to current on dest file */ X for (k = 0 ; k < setsz; k++) { X af_setgkey (&kset, k, &thiskey); X if (af_rstate (&thiskey) == AF_BUSY) X continue; /* don't consider busy version */ X if ((tgen = af_rgen (&thiskey)) > cgen) X break; X if ((tgen == cgen) && (af_rrev(&thiskey) > crev)) X break; X if (!title_printed) { X fprintf (dest, "Log for "); X putlongheader (&thiskey, dest, clead); X title_printed = TRUE; X } X else { /* each log preceded by version header */ X fprintf (dest, "%s%s", (clead && clead[0]) ? clead : "", X (clead && clead[0]) ? " " : ""); X putshortheader (&thiskey, dest, TRUE); X X } X note = af_rnote (&thiskey); X lp = note; X /* break log text into separate strings */ X /* assertion: lp == 0 if no log or log is printed */ X while (lp) { X ep = lp; X while ((*ep != '\n') && (*ep != '\0')) X ep++; X if (*ep == '\n') { X *ep++ = '\0'; /* make it end of an ordinary string */ X fprintf (dest, "%s %s\n", clead, lp); X /* ...and let it point to next string segment */ X } X else { X ep = NULL; /* we're ready */ X if (k < setsz-1) /* handle 'last-newline' problem */ X fprintf (dest, "%s %s\n", clead, lp); X else X fprintf (dest, "%s %s", clead, lp); X } X lp = ep; X } X free (note); X /* aw rite --- lets go for the next log entry */ X } X af_dropset (&kset); X } X } X else { /* print standard version header -- do it RCS-style */ X fprintf (dest, "%cHeader: ", '$'); X putshortheader (afkey, dest, FALSE); X } X return TRUE; X } X Xstatic char *vnum (key) Af_key *key; { X int _gen, _rev; X static char vstr[20]; X X _gen = af_rgen (key); X _rev = af_rrev (key); X X if (af_rstate (key) == AF_BUSY) X strcpy (vstr, "busy"); X else X sprintf (vstr, "%d.%d", _gen, _rev); X return vstr; X} X X Xstatic putlongheader (afkey, dest, clead) X Af_key *afkey; FILE *dest; char *clead; { X char *spath, *name, *type, *systime(), *UidString(), *csym; X extern char *st_table[]; X register int i; X Af_attrs allattrs; X X spath = af_rsyspath (afkey); X name = af_rname (afkey); X type = af_rtype (afkey); X af_gattrs (afkey, &allattrs); X csym = (clead && clead[0]) ? clead : ""; X for (i = 0; allattrs.af_udattrs[i]; i++) free (allattrs.af_udattrs[i]); X X fprintf (dest, "%s/%s%s%s[%s]\n%s\t%s %s %s $\n", spath, name, X type[0] ? "." : "", type, vnum(afkey), csym, X systime(), UidString (&(allattrs.af_author)), X st_table[af_rstate(afkey)]); X free (spath); free (name); free (type); X} X Xstatic putshortheader (afkey, dest, nl) X Af_key *afkey; FILE *dest; int nl; { X char *spath, *name, *type, *systime(), *UidString(); X extern char *st_table[]; X register int i; X Af_attrs allattrs; X X spath = af_rsyspath (afkey); X name = af_rname (afkey); X type = af_rtype (afkey); X af_gattrs (afkey, &allattrs); X for (i = 0; allattrs.af_udattrs[i]; i++) free (allattrs.af_udattrs[i]); X X fprintf (dest, "%s%s%s[%s] %s %s %s $%s", name, X type[0] ? "." : "",type, vnum(afkey), X systime(), UidString (&(allattrs.af_author)), X st_table[af_rstate(afkey)], nl ? "\n" : ""); X free (spath); free (name); free (type); X} X Xstatic struct { X char *name; X short code; X} an_tab[] = { X { "atime", ATIME }, /* 0 */ X { "auuid", AUUID }, X { "ctime", CTIME }, X { "generation", GEN }, X { "host", HOST }, X { "lock", LOCK }, X { "ltime", LTIME }, X { "mode", MODE }, X { "mtime", MTIME }, X { "name", NAME }, X { "ownuid", OWNUID }, X { "revision", REV }, X { "size", SIZE }, X { "stime", STIME }, X { "syspath", SYSPATH }, X { "type", TYPE }, X { "variant", VAR }, X { "version", VERSION }, X { "state", STATE } /* 18 */ X}; X Xstatic char *IsAStdAttr (attrname, afattrs) X char *attrname; Af_attrs *afattrs; { X extern char *st_table[]; X char messg[80], *UidString(); X static char rets[32]; X register int i; X int anc = 0; X X for (i = 0; i < AN_TABSIZ; i++) { X if (!(strcmp (attrname, an_tab[i].name))) { X anc = an_tab[i].code; X break; X } X } X if (anc) { X switch (anc) { X case HOST: X return afattrs->af_host; X break; X case SYSPATH: X return afattrs->af_syspath; X break; X case NAME: X return afattrs->af_name; X break; X case TYPE: X return afattrs->af_type; X break; X case GEN: X if (afattrs->af_state == AF_BUSY) return "nogen"; X else { X sprintf (rets, "%d", afattrs->af_gen); X return rets; X } X break; X case REV: X if (afattrs->af_state == AF_BUSY) return "nogen"; X else { X sprintf (rets, "%d", afattrs->af_rev); X return rets; X } X break; X case VERSION: X if (afattrs->af_state == AF_BUSY) return "busy"; X else { X sprintf (rets, "%d.%d", afattrs->af_gen, afattrs->af_rev); X return rets; X } X break; X case VAR: X return (afattrs->af_variant); X break; X case STATE: X return st_table[afattrs->af_state]; X break; X case OWNUID: X return UidString (&(afattrs->af_owner)); X break; X case AUUID: X return UidString (&(afattrs->af_author)); X break; X case SIZE: X sprintf (rets, "%d", afattrs->af_size); X return rets; X break; X case MODE: X sprintf (rets, "%o", afattrs->af_mode); X return rets; X break; X case LOCK: X if (strcmp (afattrs->af_locker.af_username, "")) { X sprintf (rets, "%s@%s", afattrs->af_locker.af_username, X afattrs->af_locker.af_userhost); X return rets; X } X return "nobody"; X break; X case MTIME: X strcpy (rets, asctime(localtime(&afattrs->af_mtime))); X rets[strlen(rets) - 1] = '\0'; X return rets; X break; X case ATIME: X strcpy (rets, asctime(localtime(&afattrs->af_atime))); X rets[strlen(rets) - 1] = '\0'; X return rets; X break; X case CTIME: X strcpy (rets, asctime(localtime(&afattrs->af_ctime))); X rets[strlen(rets) - 1] = '\0'; X return rets; X break; X case STIME: X if (afattrs->af_state == AF_BUSY) return "no_date"; X else { X strcpy (rets, asctime(localtime(&afattrs->af_stime))); X rets[strlen(rets) - 1] = '\0'; X return rets; X } X break; X case LTIME: X strcpy (rets, asctime(localtime(&afattrs->af_ltime))); X rets[strlen(rets) - 1] = '\0'; X return rets; X break; X default: /* shouldn't happen ! */ X sprintf (messg, "illegal standard attribute code %d.", anc); X logerr (anc); X } X } X else return NULL; /* no standard attribute */ X} X Xchar *UidString (user) Af_user *user; { X static char rst[256]; X X rst[0] = '\0'; X if (user) { X sprintf (rst, "%s@%s", user->af_username, user->af_userhost); X } X return rst; X} X Xstatic char *systime () { X char *asctime(); X register char *ts; X struct timeval tm; X struct timezone tz; X X gettimeofday (&tm, &tz); X ts = asctime (localtime (&tm)); X ts[strlen(ts)-1] = '\0'; X return ts; X} END_OF_FILE if test 14280 -ne `wc -c <'src/misc/citeattr.c'`; then echo shar: \"'src/misc/citeattr.c'\" unpacked with wrong size! fi # end of 'src/misc/citeattr.c' fi if test -f 'src/vc/vlmisc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/vc/vlmisc.c'\" else echo shar: Extracting \"'src/vc/vlmisc.c'\" \(14112 characters\) sed "s/^X//" >'src/vc/vlmisc.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ X#ifndef lint Xstatic char *AFSid = "$Header: vlmisc.c[3.11] Thu Feb 23 18:14:52 1989 axel@coma published $"; X#ifdef CFFLGS Xstatic char *ConfFlg = CFFLGS; X /* should be defined from within Makefile */ X#endif X#endif X/* X * Log for /u/shape/dist-tape/src/vc/vlmisc.c[3.5] X * Thu Feb 23 18:14:52 1989 axel@coma published $ X * --- empty log message --- X * vlmisc.c[3.7] Thu Feb 23 18:14:52 1989 uli@coma published $ X * --- empty log message --- X * vlmisc.c[3.9] Thu Feb 23 18:14:52 1989 axel@coma published $ X * --- empty log message --- X * vlmisc.c[3.10] Thu Feb 23 18:14:52 1989 axel@coma save $ X * --- empty log message --- X * vlmisc.c[3.11] Thu Feb 23 18:14:52 1989 axel@coma published $ X * --- empty log message --- X */ X X#include <stdio.h> X#include <pwd.h> X#include <grp.h> X#include <strings.h> X#include <sys/param.h> X#include <sys/types.h> X#include <sys/stat.h> X X#include <afs.h> X#include <afsys.h> X X#include "vl.h" X X/* X * Global, but not exported variables X */ X#define VL_MAX_OWNERNAME 7 /* in real life 8 chars */ X#define VL_MAX_GROUPNAME 7 /* dito. */ X Xstatic char *Progname; /* name of the called process*/ Xstatic char filemode[10]; /* visible file mode (ls(1)) */ Xstatic Af_user author, owner; Xstatic char version_string[80]; /* e.g. -V1.0 */ Xstatic char error_string[80]; /* for {af_}perror */ X Xchar **udattrs; /* Uda sorted */ Xint version_number; /* Version identification X * via option -V */ Xchar *version_states; /* Version states via X * option -s */ X Xchar *GetVersionState (state) X int state; X{ X switch (state) { X case AF_BUSY: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[busy]" : "b"); X case AF_SAVED: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[save]" : "s"); X case AF_PROPOSED: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[prop]" : "p"); X case AF_PUBLISHED: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[publ]" : "P"); X case AF_ACCESSED: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[acce]" : "a"); X case AF_FROZEN: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[froz]" : "f"); X default: X return (IsOptionSet(VL_O_VERSIONSTATE) ? "[????]" : "?"); X } X} X Xchar *GetVersionId (generation, revision) X int generation, revision; X{ X if ( (generation != AF_BUSYVERS) || ( revision != AF_BUSYVERS)) { X (void)sprintf (version_string, "[%d.%d]", generation, revision); X return version_string; X } X else X return ""; X} X XVinfoCleanup () X{ X X} X Xchar *GetMode (mode) X u_short mode; X{ X/* This function should return a capital 'L' in the file-class field */ X/* to indicate a *locked* version. Maybe optional. Instead of Ownername */ X/* the name of the locker is to be printed. */ X (void)sprintf (filemode, "%c%c%c%c%c%c%c%c%c%c", X (mode & S_IFDIR) ? 'd' : '-', X (mode & S_IREAD) ? 'r' : '-', X (mode & S_IWRITE) ? 'w' : '-', X (mode & S_IEXEC) ? 'x' : '-', X (mode & (S_IREAD >> 3)) ? 'r' : '-', X (mode & (S_IWRITE >> 3)) ? 'w' : '-', X (mode & (S_IEXEC >> 3)) ? 'x' : '-', X (mode & (S_IREAD >> 6)) ? 'r' : '-', X (mode & (S_IWRITE >> 6)) ? 'w' : '-', X (mode & (S_IEXEC >> 6)) ? 'x' : '-' X ); X X if (mode & S_ISUID) X filemode[1] = 's'; X if (mode & S_ISGID) X filemode[6] = 's'; X if (mode & S_ISVTX) X filemode[9] = 't'; X X return filemode; X} X Xextern char *GetUserInfo (userdesc) X Af_user *userdesc; X{ X char *uinfo, *tmp; X X if ((tmp = malloc(MAXNAMLEN + MAXHOSTNAMELEN + 2)) == NULL) { X fprintf (stderr, "in GetUserInfo: not enough memory\n"); X exit (1); X } X X if ((uinfo = malloc(20)) == NULL) { X fprintf (stderr, "in GetUserInfo: not enough memory\n"); X exit (1); X } X X (void)sprintf X (tmp, "%s%s%s", userdesc->af_username, userdesc->af_userhost[0] ? X "@" : "", userdesc->af_userhost); X (void)sprintf (uinfo, "%-16s", tmp); X free (tmp); X return uinfo; X} X Xchar *GetDate (date) X time_t date; X{ X char *tmp_time; X extern char *ctime(); X X tmp_time = ctime(&date); X X /* Format is "Sun Sep 16 01:03:52 1973\n\0" */ X tmp_time = tmp_time + 4; X tmp_time[20] = '\0'; X return tmp_time; X} X X XIsDirectory (name) X char *name; X{ X struct stat stbuf; X X if (stat(name, &stbuf)) { X return 0; X } X X return (stbuf.st_mode & S_IFDIR); X} X Xint FileExists (name) X char *name; X{ X struct stat buf; X X return ((stat (name, &buf) == 0) ? 1 : 0); X} X X Xint PutProgramName (name) X char *name; X{ X Progname = ((Progname = rindex (name, '/')) ? ++Progname : name); X} X Xchar *GetProgramName () X{ X return Progname; X} X Xvoid PutVersionStates (states) X char *states; X{ X version_states = states; X} X X#define nxt(s) (s = (*(s+strlen(s)+1) != '\0') ? s+strlen(s)+1 : NULL) X XCopyUdattrs (udaval, udattrs) X char *udaval; X char **udattrs; X{ X /* returns # of udattrs */ X register int i; X X register char *cp; X char *temp; X X if ( (temp = malloc ((unsigned)(strlen (udaval) +2))) == NULL) { X perror ("malloc"); X exit (1); X } X (void)strcpy (temp, udaval); X temp[strlen(udaval)+1] = '\0'; X X cp = temp; /* */ X while (temp && *temp) { X if (*temp == ',') { X *temp = '\0'; X } X ++temp; X } X X i = 0; X while (cp && *cp) { X udattrs[i] = cp; X i++; nxt(cp); /* nxt() is a macro !*/ X } X udattrs[i] = NULL; X X /* X * Now scan for "foo=bar<blank>bar1" and substitute <blank> by <Ctrl-A>. X * Don't ask why. X */ X X for (i=0; udattrs[i]; i++) { X cp = udattrs[i]; X for (cp = udattrs[i]; cp && *cp; cp++) X if (*cp == ' ') X *cp = AF_UDAVALDEL; /* This is a Ctrl-A */ X } X return i; /* return # of udattrs */ X} X Xint AddUdattrs (udas) X char *udas; X{ X int i, length, na; X char **cpp; X X if ( udas && (*udas == ':')) udas++; X length = 0; X /* determine length of current udattrs */ X if (udattrs && *udattrs) { X for (i = 0 ; udattrs[i]; i++) X length++; X } X X length += strlen (udas) + 1; /* plus the new udas */ X length++; X if ((cpp = (char **) malloc ((unsigned)(sizeof (char **) * length))) X == (char **) NULL) { X (void)sprintf (error_string, "%s: in AddUdattra(): malloc", Progname); X perror (error_string); X exit (1); X } X X na = CopyUdattrs (udas, cpp); X X if (udattrs && *udattrs) { X for (i = 0 ; udattrs[i]; i++) /* copy old into new array */ X cpp[na++] = udattrs[i]; X } X X cpp[na] = (char *) NULL; X free ((char *)udattrs); X X udattrs = cpp; X} X XAddHiddenUda (name, val) X char *name, *val; X{ X int length; X char *huda; X X length = strlen (name); X length += strlen (val); X X if ((huda = malloc ((unsigned)(length+2*sizeof(char)))) == (char *) NULL) { X (void)sprintf (error_string, "in AddHiddenUda(): malloc"); X perror (error_string); X exit (1); X } X (void)sprintf (huda, "%s=%s", name, val); X AddUdattrs (huda); X} X Xchar **GetUdattrs () X{ X return udattrs; X} X Xu_long vstates = 0; X#define VL_CHCK_BUSY 01 X#define VL_CHCK_SAVE 02 X#define VL_CHCK_PROPOSED 04 X#define VL_CHCK_PUBLISHED 010 X#define VL_CHCK_ACCESSED 020 X#define VL_CHCK_FROZEN 040 X#define VL_CHCK_ALL 077 X#define VL_MAX_STATES 6 X Xvoid ScanVersionStates () X X /* X * Scans strings of the form: X * bspPaf X * c+ (c is a char) X * c- X * ~c (not) X * !c (not) X * c-,c+ X * c+c- X */ X{ X register last_state; X X if (! (*version_states)) { X vstates = VL_CHCK_ALL; X return; X } X X while (*version_states) { X switch (*version_states) { X case 'b': X vstates |= VL_CHCK_BUSY; X last_state = AF_BUSY; X break; X case 's': X vstates |= VL_CHCK_SAVE; X last_state = AF_SAVED; X break; X case 'p': X vstates |= VL_CHCK_PROPOSED; X last_state = AF_PROPOSED; X break; X case 'P': X vstates |= VL_CHCK_PUBLISHED; X last_state = AF_PUBLISHED; X break; X case 'a': X vstates |= VL_CHCK_ACCESSED; X last_state = AF_ACCESSED; X break; X case 'f': X vstates |= VL_CHCK_FROZEN; X last_state = AF_FROZEN; X break; X case '+': /* -sb+ */ X switch (last_state) { X case AF_BUSY: X vstates |= VL_CHCK_BUSY; X case AF_SAVED: X vstates |= VL_CHCK_SAVE; X case AF_PROPOSED: X vstates |= VL_CHCK_PROPOSED; X case AF_PUBLISHED: X vstates |= VL_CHCK_PUBLISHED; X case AF_ACCESSED: X vstates |= VL_CHCK_ACCESSED; X case AF_FROZEN: X vstates |= VL_CHCK_FROZEN; X break; X default: X fprintf (stderr, "%s: fatal error in ScanVersionStates\n", Progname); X exit (1); X } X break; X case '-': /* -sb- */ X if ( !((*(version_states+1) == ',') || X (!*(version_states+1)))) { /* -sb-f */ X fprintf (stderr, "%s: subrange of states is not allowed\n", X Progname); X exit (1); X } X else { X switch (last_state) { X case AF_FROZEN: X vstates |= VL_CHCK_FROZEN; X case AF_ACCESSED: X vstates |= VL_CHCK_ACCESSED; X case AF_PUBLISHED: X vstates |= VL_CHCK_PUBLISHED; X case AF_PROPOSED: X vstates |= VL_CHCK_PROPOSED; X case AF_SAVED: X vstates |= VL_CHCK_SAVE; X case AF_BUSY: X vstates |= VL_CHCK_BUSY; X break; X default: X fprintf (stderr, "%s: fatal error in ScanVersionStates\n", Progname); X exit (1); X } X } X break; X case ',': /* skip this char */ X break; X case '~': X case '!': X if (!*(version_states + 1)) { X fprintf (stderr, "%s: missing version state after '%c'\n", X Progname, *version_states); X exit (1); X } X vstates = VL_CHCK_ALL; X switch (*(++version_states)) { X case 'b': X vstates &= ~VL_CHCK_BUSY; X last_state = AF_BUSY; X break; X case 's': X vstates &= ~VL_CHCK_SAVE; X last_state = AF_SAVED; X break; X case 'p': X vstates &= ~VL_CHCK_PROPOSED; X last_state = AF_PROPOSED; X break; X case 'P': X vstates &= ~VL_CHCK_PUBLISHED; X last_state = AF_PUBLISHED; X break; X case 'a': X vstates &= ~VL_CHCK_ACCESSED; X last_state = AF_ACCESSED; X break; X case 'f': X vstates &= ~VL_CHCK_FROZEN; X last_state = AF_FROZEN; X break; X default: X fprintf (stderr, "%s: unknown state '%c'. Ignored.\n", X Progname, *version_states); X break; X } X break; X default: X fprintf (stderr, "%s: unknown state '%c'. Asume 'b+'\n", X Progname, *version_states); X vstates = VL_CHCK_ALL; X return; X } X version_states++; X } X} X Xint MatchesVersionStates (attrbuf) X Af_attrs *attrbuf; X{ X register int attrstate; X register int state; X X state = vstates; X attrstate = attrbuf->af_state; X X if (state == VL_CHCK_ALL) return 1; X X switch (attrstate) { X case AF_BUSY: X return (state & VL_CHCK_BUSY); X case AF_SAVED: X return (state & VL_CHCK_SAVE); X case AF_PROPOSED: X return (state & VL_CHCK_PROPOSED); X case AF_PUBLISHED: X return (state & VL_CHCK_PUBLISHED); X case AF_ACCESSED: X return (state & VL_CHCK_ACCESSED); X case AF_FROZEN: X return (state & VL_CHCK_FROZEN); X default: X return 0; X } X} X Xvoid PutAuthorIdentifications (author_id) X char *author_id; X{ X char *cp; X X if (cp=index (author_id, '@')) { X *cp++ = '\0'; X (void)strcpy (author.af_userhost, cp); X } X (void)strcpy (author.af_username, author_id); X} X Xchar *GetAuthoridFromAuthor () X{ X return author.af_username; X} X Xchar *GetAuthorhostFromAuthor () X{ X return author.af_userhost; X} X X Xvoid PutOwnerIdentifications (owner_id) X char *owner_id; X{ X char *cp; X X if (cp=index (owner_id, '@')) { X *cp++ = '\0'; X (void)strcpy (owner.af_userhost, cp); X } X (void)strcpy (owner.af_username, owner_id); X} X Xchar *GetOwneridFromOwner () X{ X return owner.af_username; X} X Xchar *GetOwnerhostFromOwner () X{ X return owner.af_userhost; X} X X/*ARGSUSED*/ Xint Xa_dir_and_a_file (ac, av) X int ac; X char **av; X{ X /* X * Return 1 iff av contains any directory name. X */ X while (av && *av) { X if (IsDirectory (*av)) X return 1; X av++; X } X return 0; X} X Xchar ** Xrearrange_args (ac, av) X int ac; X char **av; X{ X /* X * Sorts av in the following order: first pure files, then directories. X * Returns sorted av. X */ X char **dirs; X char **tdirs; X char **files; X char **tfiles; X char **tav; X X tav = av; X X if ((dirs = (char **) X malloc ((unsigned)((ac + 1) * sizeof(char *)))) == (char **)NULL) { X perror ("malloc"); X exit (1); X } X tdirs = dirs; X X if ((files = (char **) X malloc ((unsigned)((ac + 1) * sizeof(char *)))) == (char **)NULL) { X perror ("malloc"); X exit (1); X } X tfiles = files; X X while (av && *av) { X if (IsDirectory (*av)) { X *dirs = *av; X dirs++; X } X else { X *files = *av; X files++; X } X X av++; X } X X files = (char **) NULL; X dirs = (char **) NULL; X X av = tav; X while (tfiles && *tfiles) { X *av = *tfiles; X av++; tfiles++; X } X X while (tdirs && *tdirs) { X *av = *tdirs; X av++; tdirs++; X } X X return tav; X} X Xint IsHiddenUda (uda) X char *uda; X{ X /* X * A hidden Uda begins and ends with 2 '_'. X */ X X return (!strncmp (uda, "__", 2)); X} X Xint IsHiddenFile(attrbuf) X Af_attrs *attrbuf; X{ X /* Is file a hidden file ? */ X if ( (attrbuf->af_name[0] == '\0') || (attrbuf->af_name[0] == '.') ) X return 1; X else X return 0; X} X Xlogerr (msg) char *msg; { X fprintf (stderr, "%s: %s.\n", Progname, msg); X} END_OF_FILE if test 14112 -ne `wc -c <'src/vc/vlmisc.c'`; then echo shar: \"'src/vc/vlmisc.c'\" unpacked with wrong size! fi # end of 'src/vc/vlmisc.c' fi echo shar: End of archive 16 \(of 33\). cp /dev/null ark16isdone 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.