mkid 02/11 (identifier cross reference tool)
Tom Horsley
tom at ssd.csd.harris.com
Thu Dec 13 01:40:04 AEST 1990
#! /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 2 (of 11)."
# Contents: Status bitsvec.c fid.c hash.c id.h kshgetwd.c opensrc.c
# stoi.c unsymlink.c
# Wrapped by tom at hcx2 on Wed Dec 12 07:21:55 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Status' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Status'\"
else
echo shar: Extracting \"'Status'\" \(1521 characters\)
sed "s/^X//" >'Status' <<'END_OF_FILE'
XThis is the mkid package originally posted to the net around September of
X1987 by Greg McGary (who then vanished from the net). Since then I have been
Xextensively hacking it, and so have others. In an effort to have all of us
Xbenefit from the modifications and improvements we all have made, I have
X(probably foolishly :-) volunteered to "take over" mkid.
X
XTo get the ball rolling, I am posting this version to alt.sources, and I
Xexpect people to send me their patches. I will merge them all and eventually
Xpost an "official" version to comp.sources.unix.
X
XI know there are probably portability problems with this version of the
Xsource, I have some stuff in here that references functions you only have if
Xyour system supports symbolic links, etc, so it will need to have some
Xconfig parameters and ifdef code added for sure.
X
XAnyway, keep those patches rolling in...
X
X======================================================================
Xdomain: tahorsley at csd.harris.com USMail: Tom Horsley
X uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle
X Delray Beach, FL 33444
X+==== Censorship is the only form of Obscenity ======================+
X| (Wait, I forgot government tobacco subsidies...) |
X+====================================================================+
X
XP.S.
X
X The TUTORIAL has not been changed since 1987, so a lot of stuff is not
X well documented. This situation also need to improve prior to the
X official release.
END_OF_FILE
if test 1521 -ne `wc -c <'Status'`; then
echo shar: \"'Status'\" unpacked with wrong size!
fi
# end of 'Status'
fi
if test -f 'bitsvec.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'bitsvec.c'\"
else
echo shar: Extracting \"'bitsvec.c'\" \(1614 characters\)
sed "s/^X//" >'bitsvec.c' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
Xstatic char sccsid[] = "@(#)bitsvec.c 1.1 86/10/09";
X
X#include <stdio.h>
X#include <bitops.h>
X#include <string.h>
X#include <extern.h>
X#include <id.h>
X
Xint vecToBits();
Xint bitsToVec();
Xchar *intToStr();
Xint getsFF();
Xint strToInt();
Xvoid skipFF();
X
Xint
XvecToBits(bitArray, vec, size)
X register char *bitArray;
X register char *vec;
X int size;
X{
X register int i;
X int count;
X
X for (count = 0; (*vec & 0xff) != 0xff; count++) {
X i = strToInt(vec, size);
X BITSET(bitArray, i);
X vec += size;
X }
X return count;
X}
X
Xint
XbitsToVec(vec, bitArray, bitCount, size)
X register char *vec;
X char *bitArray;
X int bitCount;
X int size;
X{
X register char *element;
X register int i;
X int count;
X
X for (count = i = 0; i < bitCount; i++) {
X if (!BITTST(bitArray, i))
X continue;
X element = intToStr(i, size);
X switch (size) {
X case 4: *vec++ = *element++;
X case 3: *vec++ = *element++;
X case 2: *vec++ = *element++;
X case 1: *vec++ = *element++;
X }
X count++;
X }
X *vec++ = 0xff;
X
X return count;
X}
X
Xchar *
XintToStr(i, size)
X register int i;
X int size;
X{
X static char buf0[4];
X register char *bufp = &buf0[size];
X
X switch (size)
X {
X case 4: *--bufp = (i & 0xff); i >>= 8;
X case 3: *--bufp = (i & 0xff); i >>= 8;
X case 2: *--bufp = (i & 0xff); i >>= 8;
X case 1: *--bufp = (i & 0xff);
X }
X return buf0;
X}
X
Xint
XstrToInt(bufp, size)
X register char *bufp;
X int size;
X{
X register int i = 0;
X
X bufp--;
X switch (size)
X {
X case 4: i |= (*++bufp & 0xff); i <<= 8;
X case 3: i |= (*++bufp & 0xff); i <<= 8;
X case 2: i |= (*++bufp & 0xff); i <<= 8;
X case 1: i |= (*++bufp & 0xff);
X }
X return i;
X}
END_OF_FILE
if test 1614 -ne `wc -c <'bitsvec.c'`; then
echo shar: \"'bitsvec.c'\" unpacked with wrong size!
fi
# end of 'bitsvec.c'
fi
if test -f 'fid.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fid.c'\"
else
echo shar: Extracting \"'fid.c'\" \(2394 characters\)
sed "s/^X//" >'fid.c' <<'END_OF_FILE'
Xstatic char copyright[] = "@(#)Copyright (c) 1986, Greg McGary";
Xstatic char sccsid[] = "@(#)fid.c 1.2 86/10/17";
X
X#include <bool.h>
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <radix.h>
X#include <id.h>
X#include <bitops.h>
X#include <extern.h>
X
Xvoid fileId();
X
XFILE *IdFILE;
Xstruct idhead Idh;
Xstruct idarg *IdArgs;
X
Xchar *MyName;
Xstatic void
Xusage()
X{
X fprintf(stderr, "Usage: %s [-f<file>] file1 file2\n", MyName);
X exit(1);
X}
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X char *idFile = IDFILE;
X char *arg;
X float occurPercent = 0.0;
X int occurNumber = 0;
X int op;
X
X MyName = basename(GETARG(argc, argv));
X
X while (argc) {
X arg = GETARG(argc, argv);
X switch (op = *arg++)
X {
X case '-':
X case '+':
X break;
X default:
X UNGETARG(argc, argv);
X goto argsdone;
X }
X while (*arg) switch (*arg++)
X {
X case 'f': idFile = arg; goto nextarg;
X default: usage();
X }
X nextarg:;
X }
Xargsdone:
X
X if ((idFile = LookUp(idFile)) == NULL) {
X filerr("open", idFile);
X exit(1);
X }
X if ((IdFILE = initID(idFile, &Idh, &IdArgs)) == NULL) {
X filerr("open", idFile);
X exit(1);
X }
X
X if (argc < 1 || argc > 2)
X usage();
X
X fileId(argc, argv);
X exit(0);
X}
X
Xvoid
XfileId(argc, argv)
X int argc;
X char **argv;
X{
X char *buf;
X int want, got;
X int bitoff[2];
X int i, j;
X int argLength;
X int pathLength;
X int lengthDiff;
X char *pathVec;
X register struct idarg *idArgs;
X
X want = 0;
X for (j = 0; j < argc; j++, argv++) {
X want |= (1<<j);
X argLength = strlen(*argv);
X bitoff[j] = -1;
X for (idArgs = IdArgs, i = 0; i < Idh.idh_pthc; i++, idArgs++) {
X pathLength = strlen(idArgs->ida_arg);
X if (argLength > pathLength)
X continue;
X lengthDiff = pathLength - argLength;
X if (strequ(&idArgs->ida_arg[lengthDiff], *argv)) {
X bitoff[j] = i;
X break;
X }
X }
X if (bitoff[j] < 0) {
X fprintf(stderr, "%s: not found\n", *argv);
X exit(1);
X }
X }
X
X buf = malloc((int)Idh.idh_bsiz);
X fseek(IdFILE, Idh.idh_namo, 0);
X
X for (i = 0; i < Idh.idh_namc; i++) {
X pathVec = 1 + buf + fgets0(buf, Idh.idh_bsiz, IdFILE);
X getsFF(pathVec, IdFILE);
X got = 0;
X while ((*pathVec & 0xff) != 0xff) {
X j = strToInt(pathVec, Idh.idh_vecc);
X if ((want & (1<<0)) && j == bitoff[0])
X got |= (1<<0);
X if ((want & (1<<1)) && j == bitoff[1])
X got |= (1<<1);
X if (got == want) {
X printf("%s\n", ID_STRING(buf));
X break;
X }
X pathVec += Idh.idh_vecc;
X }
X }
X}
END_OF_FILE
if test 2394 -ne `wc -c <'fid.c'`; then
echo shar: \"'fid.c'\" unpacked with wrong size!
fi
# end of 'fid.c'
fi
if test -f 'hash.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'hash.c'\"
else
echo shar: Extracting \"'hash.c'\" \(2237 characters\)
sed "s/^X//" >'hash.c' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
Xstatic char sccsid[] = "@(#)hash.c 1.1 86/10/09";
X
Xchar *hashSearch();
Xint h1str();
Xint h2str();
X
X/*
X Look for `key' in the hash table starting at address `base'.
X `base' is a table containing `nel' elements of size `width'.
X The hashing strategy we use is open addressing. Apply the
X primary hash function `h1' and the secondary hash function
X `h2' when searching for `key' or an empty slot. `compar'
X is the comparison function that should be used to compare
X the key with an element of the table. It is called with two
X arguments. The first argument is the address of the key, and
X the second argument is the address of the hash table element
X in question. `compar' should return 0 if the key matches the
X element or the empty slot, and non-zero otherwise.
X
X If a pointer to a long is provided for `probes' we will keep
X a running total of open addressing hash probes.
X*/
Xchar *
XhashSearch(key, base, nel, width, h1, h2, compar, probes)
X char *key; /* key to locate */
X char *base; /* base of hash table */
X register int nel; /* number of elements in table */
X int width; /* width of each element */
X unsigned int (*h1)(); /* primary hash function */
X unsigned int (*h2)(); /* secondary hash function */
X int (*compar)(); /* key comparison function */
X long *probes;
X{
X register unsigned int hash1;
X register unsigned int hash2;
X register char *slot;
X
X hash1 = (*h1)(key) % nel;
X slot = &base[hash1 * width];
X
X if (probes)
X (*probes)++;
X if ((*compar)(key, slot) == 0)
X return slot;
X
X hash2 = (*h2)(key);
X for (;;) {
X hash1 = (hash1 + hash2) % nel;
X slot = &base[hash1 * width];
X
X if (probes)
X (*probes)++;
X if ((*compar)(key, slot) == 0)
X return slot;
X }
X}
X
X#define ABS(n) ((n) < 0 ? -(n) : (n))
X
X/*
X A Primary hash function for string keys.
X*/
Xint
Xh1str(key)
X register char *key;
X{
X register int sum;
X register int s;
X
X for (sum = s = 0; *key; s++)
X sum += ((*key++) << s);
X
X return ABS(sum);
X}
X
X/*
X A Secondary hash function for string keys.
X*/
Xint
Xh2str(key)
X register char *key;
X{
X register int sum;
X register int s;
X char *keysav;
X
X keysav = key;
X key = &key[strlen(key)];
X
X for (sum = s = 0; key > keysav; s++)
X sum += ((*--key) << s);
X
X return ABS(sum) | 1;
X}
END_OF_FILE
if test 2237 -ne `wc -c <'hash.c'`; then
echo shar: \"'hash.c'\" unpacked with wrong size!
fi
# end of 'hash.c'
fi
if test -f 'id.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'id.h'\"
else
echo shar: Extracting \"'id.h'\" \(1716 characters\)
sed "s/^X//" >'id.h' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)id.h 1.1 86/10/09 */
X
X#define IDFILE "ID"
X
Xstruct idhead {
X char idh_magic[2]; /* magic number */
X#define IDH_MAGIC "\311\304" /* magic-number ("ID" with hi bits) */
X short idh_vers; /* id-file version number */
X#define IDH_VERS 2 /* current version */
X int idh_argc; /* # of args for mkid update */
X int idh_pthc; /* # of paths for mkid update */
X int idh_namc; /* # of identifiers */
X int idh_vecc; /* # of bytes in a path vector entry */
X int idh_bsiz; /* # of bytes in entry (bufsiz for lid) */
X long idh_argo; /* file offset of args for mkid update */
X long idh_namo; /* file offset of identifier names */
X long idh_endo; /* file offset of EOF */
X};
X
Xstruct idarg {
X struct idarg *ida_next;
X char *ida_arg;
X int ida_index;
X char ida_flags;
X#define IDA_ADJUST 0x01
X#define IDA_SCAN 0x02
X#define IDA_PATH 0x04
X#define IDA_ARG 0x08
X#define IDA_BLANK 0x10
X};
X
Xstruct idname {
X char *idn_name;
X char *idn_bitv;
X char idn_flags;
X#define IDN_SOLO 0x01 /* occurs only once */
X#define IDN_NUMBER 0x02 /* is a number */
X#define IDN_NAME 0x04 /* is a name */
X#define IDN_STRING 0x08 /* is a string */
X#define IDN_LITERAL 0x10 /* occurs as a literal (not string) */
X#define IDN_NOISE 0x20 /* occurs very frequently */
X};
X
X/*
X Extract the various logical fields of a name:
X
X NAME: null-terminated ascii string
X TAG: index of name within a sorted array of all names
X SOLO: boolean indicating that this name occurs exactly once
X*/
X#define ID_PATHS(b) ((b)+strlen(b)+1)
X#define ID_FLAGS(b) (*(b))
X#define ID_STRING(b) ((b)+1)
X
X#define NEW(type) ((type *)calloc(1, sizeof(type)))
X
X#define GETARG(argc, argv) ((argc)--, *(argv)++)
X#define UNGETARG(argc, argv) ((argc)++, *--(argv))
END_OF_FILE
if test 1716 -ne `wc -c <'id.h'`; then
echo shar: \"'id.h'\" unpacked with wrong size!
fi
# end of 'id.h'
fi
if test -f 'kshgetwd.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kshgetwd.c'\"
else
echo shar: Extracting \"'kshgetwd.c'\" \(1781 characters\)
sed "s/^X//" >'kshgetwd.c' <<'END_OF_FILE'
X#include <string.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X
Xextern char * getenv();
Xextern void cannoname();
Xextern char * unsymlink();
Xextern char * getwd();
X
X/* kshgetwd is a routine that acts just like getwd, but is optimized
X * for ksh users, taking advantage of the fact that ksh maintains
X * an environment variable named PWD holding path name of the
X * current working directory.
X *
X * The primary motivation for this is not really that it is algorithmically
X * simpler, but that it is much less likely to bother NFS if we can just
X * guess the name of the current working directory using the hint that
X * ksh maintains. Anything that avoids NFS gettar failed messages is
X * worth doing.
X */
Xchar *
Xkshgetwd(pathname)
X char * pathname;
X{
X struct stat kshstat, dotstat ;
X char kshname[MAXPATHLEN] ;
X char * kshp ;
X
X kshp = getenv("PWD") ;
X if (kshp) {
X /* OK, there was a PWD environment variable */
X strcpy(kshname, kshp) ;
X if (unsymlink(kshname)) {
X /* And we could resolve the symbolic links through it */
X if (kshname[0] == '/') {
X /* And the name we have is an absolute path name */
X if (stat(kshname, &kshstat) == 0) {
X /* And we can stat the name */
X if (stat(".", &dotstat) == 0) {
X /* And we can stat "." */
X if ((kshstat.st_dev == dotstat.st_dev) &&
X (kshstat.st_ino == dotstat.st_ino)) {
X /* By golly, that name is the same file as "." ! */
X return(strcpy(pathname, kshname)) ;
X }
X }
X }
X }
X }
X }
X /* Oh well, something did not work out right, do it the hard way */
X return(getwd(pathname)) ;
X}
END_OF_FILE
if test 1781 -ne `wc -c <'kshgetwd.c'`; then
echo shar: \"'kshgetwd.c'\" unpacked with wrong size!
fi
# end of 'kshgetwd.c'
fi
if test -f 'opensrc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'opensrc.c'\"
else
echo shar: Extracting \"'opensrc.c'\" \(2529 characters\)
sed "s/^X//" >'opensrc.c' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
Xstatic char sccsid[] = "@(#)opensrc.c 1.1 86/10/09";
X
X#include <stdio.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
Xchar *findSrcFILE();
Xchar *getSCCS();
Xchar *coRCS();
X
XFILE *
XopenSrcFILE(path, sccsDir, rcsDir, filter)
X char *path;
X char *sccsDir;
X char *rcsDir;
X char *filter;
X{
X char *command = NULL;
X char *what = NULL;
X char *get = "get SCCS file";
X char *checkout = "checkout RCS file";
X char *dirName;
X char *baseName;
X struct stat statb;
X char popcom[1024];
X FILE *srcFILE;
X
X if (stat(path, &statb) != 0) {
X if ((baseName = strrchr(path, '/')) == NULL) {
X dirName = ".";
X baseName = path;
X } else {
X dirName = path;
X *baseName++ = '\0';
X }
X
X if (rcsDir && (command = coRCS(dirName, baseName, rcsDir)))
X what = checkout;
X else if (sccsDir && (command = getSCCS(dirName, baseName, sccsDir)))
X what = get;
X else if ((command = coRCS(dirName, baseName, "RCS"))
X || (command = coRCS(dirName, baseName, ".")))
X what = checkout;
X else if ((command = getSCCS(dirName, baseName, "SCCS"))
X || (command = getSCCS(dirName, baseName, "sccs"))
X || (command = getSCCS(dirName, baseName, ".")))
X what = get;
X
X if (dirName == path)
X *--baseName = '/';
X
X if (!command) {
X filerr("open", path);
X return NULL;
X }
X
X system(command);
X fprintf(stderr, "%s\n", command);
X }
X if (stat(path, &statb) != 0) {
X filerr("open", path);
X return NULL;
X }
X if (filter != NULL) {
X sprintf(popcom,filter,path);
X srcFILE = popen(popcom, "r");
X } else {
X srcFILE = fopen(path, "r");
X }
X if (srcFILE == NULL) {
X filerr("open", path);
X }
X return srcFILE;
X}
X
Xvoid
XcloseSrcFILE(fp, filter)
X FILE *fp;
X char *filter;
X{
X if (filter != NULL) {
X pclose(fp);
X } else {
X fclose(fp);
X }
X}
X
Xchar *
XgetSCCS(dir, base, sccsDir)
X char *dir;
X char *base;
X char *sccsDir;
X{
X static char cmdBuf[BUFSIZ];
X char fileBuf[BUFSIZ];
X struct stat statBuf;
X
X if (!*sccsDir)
X sccsDir = ".";
X
X sprintf(fileBuf, "%s/%s/s.%s", dir, sccsDir, base);
X if (stat(fileBuf, &statBuf) < 0)
X return NULL;
X sprintf(cmdBuf, "cd %s; get -s %s/s.%s", dir, sccsDir, base);
X
X return cmdBuf;
X}
X
Xchar *
XcoRCS(dir, base, rcsDir)
X char *dir;
X char *base;
X char *rcsDir;
X{
X static char cmdBuf[BUFSIZ];
X char fileBuf[BUFSIZ];
X struct stat statBuf;
X
X if (!*rcsDir)
X rcsDir = ".";
X
X sprintf(fileBuf, "%s/%s/%s,v", dir, rcsDir, base);
X if (stat(fileBuf, &statBuf) < 0)
X return NULL;
X sprintf(cmdBuf, "cd %s; co -q %s/%s,v", dir, rcsDir, base);
X
X return cmdBuf;
X}
END_OF_FILE
if test 2529 -ne `wc -c <'opensrc.c'`; then
echo shar: \"'opensrc.c'\" unpacked with wrong size!
fi
# end of 'opensrc.c'
fi
if test -f 'stoi.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'stoi.c'\"
else
echo shar: Extracting \"'stoi.c'\" \(1883 characters\)
sed "s/^X//" >'stoi.c' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
Xstatic char sccsid[] = "@(#)stoi.c 1.1 86/10/09";
X
X#include <radix.h>
X#include <ctype.h>
X
Xint dtoi();
Xint otoi();
Xint radix();
Xint stoi();
Xint xtoi();
X
X/*
X Use the C lexical rules to determine an ascii number's radix.
X The radix is returned as a bit map, so that more than one radix
X may apply. In particular, it is impossible to determine the
X radix of 0, so return all possibilities.
X*/
Xint
Xradix(name)
X register char *name;
X{
X if (!isdigit(*name))
X return 0;
X if (*name != '0')
X return RADIX_DEC;
X name++;
X if (*name == 'x' || *name == 'X')
X return RADIX_HEX;
X while (*name && *name == '0')
X name++;
X return (RADIX_OCT | ((*name)?0:RADIX_DEC));
X}
X
X/*
X Convert an ascii string number to an integer.
X Determine the radix before converting.
X*/
Xint
Xstoi(name)
X char *name;
X{
X switch (radix(name))
X {
X case RADIX_DEC: return(dtoi(name));
X case RADIX_OCT: return(otoi(&name[1]));
X case RADIX_HEX: return(xtoi(&name[2]));
X case RADIX_DEC|RADIX_OCT: return(0);
X default: return(-1);
X }
X}
X
X/*
X Convert an ascii octal number to an integer.
X*/
Xint
Xotoi(name)
X char *name;
X{
X register int n = 0;
X
X while (*name >= '0' && *name <= '7') {
X n *= 010;
X n += *name++ - '0';
X }
X if (*name == 'l' || *name == 'L')
X name++;
X return (*name ? -1 : n);
X}
X
X/*
X Convert an ascii decimal number to an integer.
X*/
Xint
Xdtoi(name)
X char *name;
X{
X register int n = 0;
X
X while (isdigit(*name)) {
X n *= 10;
X n += *name++ - '0';
X }
X if (*name == 'l' || *name == 'L')
X name++;
X return (*name ? -1 : n);
X}
X
X/*
X Convert an ascii hex number to an integer.
X*/
Xint
Xxtoi(name)
X char *name;
X{
X register int n = 0;
X
X while (isxdigit(*name)) {
X n *= 0x10;
X if (isdigit(*name))
X n += *name++ - '0';
X else if (islower(*name))
X n += 0xa + *name++ - 'a';
X else
X n += 0xA + *name++ - 'A';
X }
X if (*name == 'l' || *name == 'L')
X name++;
X return (*name ? -1 : n);
X}
END_OF_FILE
if test 1883 -ne `wc -c <'stoi.c'`; then
echo shar: \"'stoi.c'\" unpacked with wrong size!
fi
# end of 'stoi.c'
fi
if test -f 'unsymlink.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'unsymlink.c'\"
else
echo shar: Extracting \"'unsymlink.c'\" \(2622 characters\)
sed "s/^X//" >'unsymlink.c' <<'END_OF_FILE'
X#include <string.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X
Xextern void cannoname();
X
X/* unsymlink is a routine that resolves all symbolic links in
X * a file name, transforming a name to the "actual" file name
X * instead of the name in terms of symbolic links.
X *
X * If it can resolve all links and discover an actual file
X * it returns a pointer to its argument string and transforms
X * the argument in place to the actual name.
X *
X * If no such actual file exists, or for some reason the links
X * cannot be resolved, it returns a NULL pointer and leaves the
X * name alone.
X */
Xchar *
Xunsymlink(n)
X char * n;
X{
X char newname[MAXPATHLEN];
X char partname[MAXPATHLEN];
X char linkname[MAXPATHLEN];
X char * s;
X char * d;
X char * lastcomp;
X int linksize;
X struct stat statb;
X
X /* Just stat the file to automagically do all the symbolic
X * link verification checks and make sure we have access to
X * directories, etc.
X */
X if (stat(n, &statb) != 0) return(NULL) ;
X strcpy(newname, n);
X /* Now loop, lstating each component to see if it is a symbolic
X * link. For symbolic link components, use readlink() to get
X * the real name, put the read link name in place of the
X * last component, and start again.
X */
X cannoname(newname) ;
X s = &newname[0] ;
X d = &partname[0] ;
X if (*s == '/') {
X *d++ = *s++ ;
X }
X lastcomp = d ;
X for ( ; ; ) {
X if ((*s == '/') || (*s == '\0')) {
X /* we have a complete component name in partname, check it out */
X *d = '\0' ;
X if (lstat(partname, &statb) != 0) return(NULL) ;
X if ((statb.st_mode & S_IFMT) == S_IFLNK) {
X /* This much of name is a symbolic link, do a readlink
X * and tack the bits and pieces together
X */
X linksize = readlink(partname, linkname, MAXPATHLEN) ;
X if (linksize < 0) return(NULL) ;
X linkname[linksize] = '\0' ;
X strcpy(lastcomp, linkname) ;
X lastcomp += linksize ;
X strcpy(lastcomp, s) ;
X strcpy(newname, partname) ;
X cannoname(newname) ;
X s = &newname[0] ;
X d = &partname[0] ;
X if (*s == '/') {
X *d++ = *s++ ;
X }
X lastcomp = d ;
X } else {
X /* Not a symlink, just keep scanning to next component */
X if (*s == '\0') break ;
X *d++ = *s++ ;
X lastcomp = d ;
X }
X } else {
X *d++ = *s++ ;
X }
X }
X strcpy(n, newname) ;
X return(n) ;
X}
END_OF_FILE
if test 2622 -ne `wc -c <'unsymlink.c'`; then
echo shar: \"'unsymlink.c'\" unpacked with wrong size!
fi
# end of 'unsymlink.c'
fi
echo shar: End of archive 2 \(of 11\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 11 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
--
======================================================================
domain: tahorsley at csd.harris.com USMail: Tom Horsley
uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle
Delray Beach, FL 33444
+==== Censorship is the only form of Obscenity ======================+
| (Wait, I forgot government tobacco subsidies...) |
+====================================================================+
More information about the Alt.sources
mailing list