lenny@icus.islp.ny.us (Lenny Tropiano) (08/03/89)
Enclosed is some library routines that I find very useful, especially when taking programs that have SVR3 calls, SVR2 calls that don't appear on the UNIX pc, or POSIX compatible library calls. This group of library routines is found in the News 3.0 beta distribution. The routines were written by Eric S. Raymond, Henry Spencer, and Doug Gwyn. Many people were looking for the DIRENT library routines, well they are found here too (this will help those who want to compile Gil's "man" program). I take no responsibility for the code, but I know it's worked time and time for me. Especially when compiling things with mkdir(), rename(), and other SVR3 routines. There are 5 shar files to prevent any munging by news sites... Unshar all 5 parts and then make the Makefile with: $ sh Makeposix -Lenny --- cut here --- --- cut here --- --- cut here --- --- cut here --- #! /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 1 (of 5)." # Contents: MANIFEST Makefile.dst README bsearch.c closedir.c dirent.h # getopt.c lfind.c lsearch.c memccpy.c memchr.c memcmp.c memory.h # memset.c mkdirtest.c posix.lint putpwent.3c putpwent.c readdir.c # rename.c rewinddir.c rmdir.c search.h ssignal.c strchr.c strcspn.c # strdup.c string.h strpbrk.c strrchr.c strspn.c strtok.c # sys.dirent.h telldir.c testdir.c tfind.c unistd.h # Wrapped by lenny@icus on Wed Aug 2 21:40:15 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f MANIFEST -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"MANIFEST\" else echo shar: Extracting \"MANIFEST\" \(1024 characters\) sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST' X File Name Archive # Description X----------------------------------------------------------- X DIRENT.INSTALL 3 X DIRENT.NOTES 3 X MANIFEST 1 X Makefile.dst 1 X Makeposix 5 X README 1 X bsearch.3c 3 X bsearch.c 1 X closedir.c 1 X directory.3c 3 X dirent.4 2 X dirent.h 1 X getcwd.c 3 X getdents.2 2 X getdents.c 4 X getopt.c 1 X lfind.c 1 X lsearch.3c 2 X lsearch.c 1 X memccpy.c 1 X memchr.c 1 X memcmp.c 1 X memcpy.c 2 X memory.3c 2 X memory.h 1 X memset.c 1 X mkdir.3 2 X mkdir.c 3 X mkdirtest.c 1 X opendir.c 2 X posix.lint 1 END_OF_MANIFEST echo shar: Missing newline added to \"MANIFEST\" if test 1024 -ne `wc -c <MANIFEST`; then echo shar: \"MANIFEST\" unpacked with wrong size! fi # end of overwriting check fi if test -f Makefile.dst -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makefile.dst\" else echo shar: Extracting \"Makefile.dst\" \(118 characters\) sed "s/^X//" >Makefile.dst <<'END_OF_Makefile.dst' XMakefile: posix_conf X Xposix_conf: Makeposix X Makeposix X Xclean: X rm -f libposix.a *.o posix_conf Makefile profiled/* X END_OF_Makefile.dst if test 118 -ne `wc -c <Makefile.dst`; then echo shar: \"Makefile.dst\" unpacked with wrong size! fi # end of overwriting check fi if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(2463 characters\) sed "s/^X//" >README <<'END_OF_README' XThis directory provides sources for POSIX/SVID/X3J11 standard routines Xwhich you can compile and install in your system libraries or in a libposix.a. XThey include: X X strings(3) -- string function package by Henry Spencer and Eric Raymond X directory(3) -- directory-scanning functions by Doug Gwyn X strtol(3) -- string-to-long conversion by an anonymous hacker. X getopt(3) -- string-to-long conversion by Henry Spencer X memory(3) -- memory functions by Eric S. Raymond X [btl]search(3) -- binary/tree/linear-search code by Eric S. Raymond X gsignal(3) -- user software signals code by Eric S. Raymond X putpwent(3) -- write password entry to file X XManual pages are provided for all. To install, run Makeposix and follow the Xinstructions in the Makefile header comment and DIRENT.INSTALL. X XNote that Makeposix makes some fairly rigid assumptions about what facilities Xare associated with which modules in your C library. Some implementations may Xviolate these assumptions (for example, in 4.2BSD the rewinddir() function Xlives in a rewinddir.o; in SVr3, it is present but the code lives in one of the Xother directory library modules). X XAs a result, the generated Makefile may want to link modules into your Xlibrary that duplicate code it aleady contains. This should be harmless, Xbecause ar adds the new stuff at the end of the library but does its link- Xresolution searches from the beginning. But there's no point in altering Xyour C library if you don't need to, so Makeposix provides a way for you to Xtell it that particular facilties are in place. Simply call it with one of Xthe following arguments: X X SVR1 -- assume all System V Release 1 facilities are present X SVR2 -- assume all System V Release 1 & 2 facilities are present X SVR3 -- assume all System V Release 1, 2 & 3 facilities are present X 4.2BSD -- assume all Berkeley 4.2 facilities are present X 4.3BSD -- assume all Berkeley 4.2 & 4.3 facilities are present X XThis will tell it to act on the assumption that anything normally supported Xby the given system is present, even if its module checks suggest otherwise. X XTo update your lint library to include the right things, you'll need to Xrecompile your lint library into .ln form. You can do this with lint's -C Xoption on BSD systems, or its -c option on System V Release 2 sites -- others Xwill have to dig into the local lint script to find the right magic. A relint Xproduction that should work for SVr{2,3} sites is provided in the generated XMakefile. END_OF_README if test 2463 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f bsearch.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bsearch.c\" else echo shar: Extracting \"bsearch.c\" \(897 characters\) sed "s/^X//" >bsearch.c <<'END_OF_bsearch.c' X/* X * A binary search generalized from Knuth (6.2.1) Algorithm B just X * like the AT&T man page says... X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X Xchar *bsearch(key, base, nel, width, compar) Xchar *key; /* Key to be located */ Xchar *base; /* Beginning of table */ Xunsigned nel; /* Number of elements in the table */ Xunsigned width; /* Width of an element (bytes) */ Xint (*compar)(); /* Comparison function */ X{ X int doublewidth = width + width; X X char *last = base + width * (nel - 1); X X while (last >= base) X { X register char *p = base + width * ((last - base)/doublewidth); X register int cmp = (*compar)(key, p); X X if (cmp == 0) X return (p); /* aha, we found it! */ X if (cmp < 0) X last = p - width; X else X base = p + width; X } X return ((char *) 0); /* didn't find it */ X} END_OF_bsearch.c if test 897 -ne `wc -c <bsearch.c`; then echo shar: \"bsearch.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f closedir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"closedir.c\" else echo shar: Extracting \"closedir.c\" \(568 characters\) sed "s/^X//" >closedir.c <<'END_OF_closedir.c' X/* X closedir -- close a directory stream X X last edit: 25-Apr-1987 D A Gwyn X*/ X X#include <sys/errno.h> X#include <sys/types.h> X#include <dirent.h> X Xtypedef char *pointer; /* (void *) if you have it */ X Xextern void free(); Xextern int close(); X Xextern int errno; X X#ifndef NULL X#define NULL 0 X#endif X Xint Xclosedir( dirp ) X register DIR *dirp; /* stream from opendir() */ X { X if ( dirp == NULL || dirp->dd_buf == NULL ) X { X errno = EFAULT; X return -1; /* invalid pointer */ X } X X free( (pointer)dirp->dd_buf ); X free( (pointer)dirp ); X return close( dirp->dd_fd ); X } END_OF_closedir.c if test 568 -ne `wc -c <closedir.c`; then echo shar: \"closedir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f dirent.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"dirent.h\" else echo shar: Extracting \"dirent.h\" \(730 characters\) sed "s/^X//" >dirent.h <<'END_OF_dirent.h' X/* X <dirent.h> -- definitions for SVR3 directory access routines X X last edit: 25-Apr-1987 D A Gwyn X X Prerequisite: <sys/types.h> X*/ X X#include "sys/dirent.h" X X#define DIRBUF 8192 /* buffer size for fs-indep. dirs */ X /* must in general be larger than the filesystem buffer size */ X Xtypedef struct X { X int dd_fd; /* file descriptor */ X int dd_loc; /* offset in block */ X int dd_size; /* amount of valid data */ X char *dd_buf; /* -> directory block */ X } DIR; /* stream data from opendir() */ X Xextern DIR *opendir(); Xextern struct dirent *readdir(); Xextern off_t telldir(); Xextern void seekdir(); Xextern void rewinddir(); Xextern int closedir(); X X#ifndef NULL X#define NULL 0 /* DAG -- added for convenience */ X#endif END_OF_dirent.h if test 730 -ne `wc -c <dirent.h`; then echo shar: \"dirent.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f getopt.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"getopt.c\" else echo shar: Extracting \"getopt.c\" \(1223 characters\) sed "s/^X//" >getopt.c <<'END_OF_getopt.c' X/* X * getopt - get option letter from argv X * X * Copyright (c) Henry Spencer. X * Written by Henry Spencer. X * X */ X X/* X * changed index() calls to strchr() - darwin, oct 87. X */ X X#include <stdio.h> X Xchar *optarg; /* Global argument pointer. */ Xint optind = 0; /* Global argv index. */ X Xstatic char *scan = NULL; /* Private scan pointer. */ X Xextern char *strchr(); X Xint Xgetopt(argc, argv, optstring) Xint argc; Xchar *argv[]; Xchar *optstring; X{ X register char c; X register char *place; X X optarg = NULL; X X if (scan == NULL || *scan == '\0') { X if (optind == 0) X optind++; X X if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') X return(EOF); X if (strcmp(argv[optind], "--")==0) { X optind++; X return(EOF); X } X X scan = argv[optind]+1; X optind++; X } X X c = *scan++; X place = strchr(optstring, c); X X if (place == NULL || c == ':') { X (void) fprintf(stderr, "%s: unknown option -%c\n", argv[0], c); X return('?'); X } X X place++; X if (*place == ':') { X if (*scan != '\0') { X optarg = scan; X scan = NULL; X } else if (optind < argc) { X optarg = argv[optind]; X optind++; X } else { X (void) fprintf(stderr, X "%s: -%c argument missing\n", argv[0], c); X return('?'); X } X } X X return(c); X} END_OF_getopt.c if test 1223 -ne `wc -c <getopt.c`; then echo shar: \"getopt.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f lfind.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"lfind.c\" else echo shar: Extracting \"lfind.c\" \(745 characters\) sed "s/^X//" >lfind.c <<'END_OF_lfind.c' X/* X * Linear search algorithm, generalized from Knuth (6.1) Algorithm S. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X Xextern char *memcpy(); X Xchar *lfind(key, base, nelp, width, compar) Xregister char * key; /* key to be searched for */ Xregister char * base; /* base of table */ Xunsigned *nelp; /* char * to current table size */ Xunsigned width; /* width of an element (bytes) */ Xint (*compar)(); /* ordering function */ X{ X register char *next; X X for (next = base + *nelp * width ; base < next; base += width) X if ((*compar)(key, base) == 0) X return (base); /* we found it! */ X return (char *)(-1); /* it's not there */ X} X X/* lfind.c ends here */ END_OF_lfind.c if test 745 -ne `wc -c <lfind.c`; then echo shar: \"lfind.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f lsearch.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"lsearch.c\" else echo shar: Extracting \"lsearch.c\" \(814 characters\) sed "s/^X//" >lsearch.c <<'END_OF_lsearch.c' X/* X * Linear search algorithm, generalized from Knuth (6.1) Algorithm S. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X Xchar *lsearch(key, base, nelp, width, compar) Xregister char *key; /* key to be searched for */ Xregister char *base; /* base of table */ Xunsigned *nelp; /* pointer to current table size */ Xunsigned width; /* size of an element (chars) */ Xint (*compar)(); /* ordering function */ X{ X register char *next; X extern char *memcpy(); X X for (next = base + *nelp * width ; base < next; base += width) X if ((*compar)(key, base) == 0) X return (base); /* we found it! */ X ++*nelp; /* key not found, add it */ X return(memcpy(base, key, (int)width)); /* bump next ptr */ X} X X/* lsearch.c ends here */ END_OF_lsearch.c if test 814 -ne `wc -c <lsearch.c`; then echo shar: \"lsearch.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f memccpy.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memccpy.c\" else echo shar: Extracting \"memccpy.c\" \(470 characters\) sed "s/^X//" >memccpy.c <<'END_OF_memccpy.c' X/* X * memccpy.c X * X * Copy no more than n bytes of t to s, stopping if char c is copied. Return X * a pointer to the byte following character c, or NULL if c is not found X * in the first n bytes. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ X Xchar *memccpy(t, s, c, n) Xregister char *t, *s; Xregister int c, n; X{ X while (--n >= 0) X if ((*t++ = *s++) == c) X return(t); X return(0); X} END_OF_memccpy.c if test 470 -ne `wc -c <memccpy.c`; then echo shar: \"memccpy.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f memchr.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memchr.c\" else echo shar: Extracting \"memchr.c\" \(400 characters\) sed "s/^X//" >memchr.c <<'END_OF_memchr.c' X/* X * memchr.c X * X * Return address in 1st n chars of sp at which the character c appears; X * NULL if not found; don't terminate at \0. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ X Xchar *memchr(sp, c, n) Xregister char *sp, c; Xregister int n; X{ X while (--n >= 0) X if (*sp++ == c) X return(--sp); X return(0); X} END_OF_memchr.c if test 400 -ne `wc -c <memchr.c`; then echo shar: \"memchr.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f memcmp.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memcmp.c\" else echo shar: Extracting \"memcmp.c\" \(533 characters\) sed "s/^X//" >memcmp.c <<'END_OF_memcmp.c' X/* X * memcmp.c X * X * Compare n bytes using normal lexicographic ordering, so that if X * sp1 is less than sp2 the result comes out negative, if sp1 == sp2 it X * is zero, and if sp1 is greater than sp2 it is positive. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ X Xint memcmp(sp1, sp2, n) Xregister char *sp1, *sp2; Xregister int n; X{ X int delta; X X if (sp1 != sp2) X while (--n >= 0) X if (delta = *sp1++ - *sp2++) X return(delta); X return(0); X} END_OF_memcmp.c if test 533 -ne `wc -c <memcmp.c`; then echo shar: \"memcmp.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f memory.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memory.h\" else echo shar: Extracting \"memory.h\" \(110 characters\) sed "s/^X//" >memory.h <<'END_OF_memory.h' X/* memory.h -- memory-area library functions */ X Xextern char X *memccpy(), X *memchr(), X *memcpy(), X *memset(); END_OF_memory.h if test 110 -ne `wc -c <memory.h`; then echo shar: \"memory.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f memset.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memset.c\" else echo shar: Extracting \"memset.c\" \(342 characters\) sed "s/^X//" >memset.c <<'END_OF_memset.c' X/* X * Fill an array of n chars starting at sp with the character c. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ X Xchar *memset(sp, c, n) Xregister char *sp, c; Xregister int n; X{ X register char *base = sp; X X while (--n >= 0) X *sp++ = c; X return(base); X} END_OF_memset.c if test 342 -ne `wc -c <memset.c`; then echo shar: \"memset.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f mkdirtest.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"mkdirtest.c\" else echo shar: Extracting \"mkdirtest.c\" \(885 characters\) sed "s/^X//" >mkdirtest.c <<'END_OF_mkdirtest.c' X/* mkdirtest.c -- test mkdir and rmdir functions */ X#include <stdio.h> X#include <errno.h> X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int dstat, perms; X extern int errno; X X if (strcmp(argv[1], "-d") == 0) X { X if ((dstat = rmdir(argv[2])) != 0) X (void) fprintf(stderr, X "mkdirtest: cannot rmdir %s: errno = %d\n",argv[1],errno); X exit(dstat); X } X X /* give user a chance to set the umask before attempting a mkdir */ X if (strncmp(argv[1], "-u", 2) == 0) X { X (void) sscanf(argv[1] + 2, "%o", &perms); X (void) fprintf(stderr, "mkdirtest: setting umask to %o\n", perms); X (void) umask(perms); X ++argv; --argc; X } X X if (argc > 2) X (void) sscanf(argv[2], "%o", &perms); X else X perms = 0777; X X if (mkdir(argv[1], perms) == -1) X (void) fprintf(stderr, X "mkdirtest: cannot mkdir %s: errno = %d\n", argv[1], errno); X} X X/* mkdirtest.c ends here */ X END_OF_mkdirtest.c if test 885 -ne `wc -c <mkdirtest.c`; then echo shar: \"mkdirtest.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f posix.lint -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"posix.lint\" else echo shar: Extracting \"posix.lint\" \(663 characters\) sed "s/^X//" >posix.lint <<'END_OF_posix.lint' X/* POSIX library extensions */ Xint lockf(fd, fn, sz) int fd, fn; long sz; {return 0;} X/* DIRECTORY(3C) */ X#include <dirent.h> Xint getdents(f, b, n) int f; char *b; unsigned n; { return 0; } Xint closedir(p) DIR *p; { return 0; } XDIR *opendir(f) char *f; {return (DIR *)NULL;} Xstruct dirent *readdir(p) DIR *p; {return (struct dirent*)NULL;} Xvoid seekdir(p, l) DIR *p; long l; {} Xlong telldir(p) DIR *p; {return 1L;} X/* MKDIR(3) */ Xint mkdir(s, p) char *s; int p; {return (0);} X/* RMDIR(3) */ Xint rmdir(s) char *s; {return (0);} X/* STRING(3C) */ Xchar * strdup(a) char *a; { return (a); } X/* MEMORY(3C) */ X/* RENAME(3) */ Xint rename(s, t) char *s, *t; {return (0);} END_OF_posix.lint if test 663 -ne `wc -c <posix.lint`; then echo shar: \"posix.lint\" unpacked with wrong size! fi # end of overwriting check fi if test -f putpwent.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"putpwent.3c\" else echo shar: Extracting \"putpwent.3c\" \(759 characters\) sed "s/^X//" >putpwent.3c <<'END_OF_putpwent.3c' X.TH PUTPWENT 3C "Standard Extension" X.SH NAME Xputpwent \- write password file entry X.SH SYNOPSIS X.B #include <pwd.h> X.PP X.B int putpwent (p, f) X.br X.B struct passwd \(**p; X.br X.B \s-1FILE\s+1 \(**f; X.SH DESCRIPTION X.I Putpwent Xis the inverse of X.IR getpwent (3C). XGiven a pointer to a Xpasswd Xstructure created by X.I getpwent X(or X.I getpwuid Xor X.IR getpwnam ), X.I putpwent Xwrites a line on the stream X.IR f , Xwhich matches the format of X.BR /etc/passwd . X.SH DIAGNOSTICS X.I Putpwent Xreturns non-zero if an error was detected during its operation, Xotherwise zero. X.SH "SEE ALSO" Xgetpwent(3C). X.SH WARNING XThe above routine uses \fB<stdio.h>\fP, which causes Xit to increase the size of programs, Xnot otherwise using standard I/O, more Xthan might be expected. END_OF_putpwent.3c if test 759 -ne `wc -c <putpwent.3c`; then echo shar: \"putpwent.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f putpwent.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"putpwent.c\" else echo shar: Extracting \"putpwent.c\" \(633 characters\) sed "s/^X//" >putpwent.c <<'END_OF_putpwent.c' X/* X * putpwent.c -- write a password file entry X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X#include <stdio.h> X#include <pwd.h> X Xint putpwent(pw, fp) Xstruct passwd *pw; XFILE *fp; X{ X (void) fprintf(fp, "%s:%s", pw->pw_name, pw->pw_passwd); X#ifdef USG X if (pw->pw_age[0] != '\0') X (void) fprintf(fp, ",%s", pw->pw_age); X#endif /* USG */ X (void) fprintf(fp, ":%u:%u:%s:%s:%s", X pw->pw_uid, X pw->pw_gid, X pw->pw_gecos, X pw->pw_dir, X pw->pw_shell); X (void) putc('\n', fp); X return(ferror(fp)); X} X X/* putpwent.c ends here */ END_OF_putpwent.c if test 633 -ne `wc -c <putpwent.c`; then echo shar: \"putpwent.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f readdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"readdir.c\" else echo shar: Extracting \"readdir.c\" \(991 characters\) sed "s/^X//" >readdir.c <<'END_OF_readdir.c' X/* X readdir -- read next entry from a directory stream X X last edit: 25-Apr-1987 D A Gwyn X*/ X X#include <sys/errno.h> X#include <sys/types.h> X#include <dirent.h> X Xextern int getdents(); /* SVR3 system call, or emulation */ X Xextern int errno; X X#ifndef NULL X#define NULL 0 X#endif X Xstruct dirent * Xreaddir( dirp ) X register DIR *dirp; /* stream from opendir() */ X { X register struct dirent *dp; /* -> directory data */ X X if ( dirp == NULL || dirp->dd_buf == NULL ) X { X errno = EFAULT; X return NULL; /* invalid pointer */ X } X X do { X if ( dirp->dd_loc >= dirp->dd_size ) /* empty or obsolete */ X dirp->dd_loc = dirp->dd_size = 0; X X if ( dirp->dd_size == 0 /* need to refill buffer */ X && (dirp->dd_size = X getdents( dirp->dd_fd, dirp->dd_buf, (unsigned)DIRBUF ) X ) <= 0 X ) X return NULL; /* EOF or error */ X X dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc]; X dirp->dd_loc += dp->d_reclen; X } X while ( dp->d_ino == 0L ); /* don't rely on getdents() */ X X return dp; X } END_OF_readdir.c if test 991 -ne `wc -c <readdir.c`; then echo shar: \"readdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f rename.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rename.c\" else echo shar: Extracting \"rename.c\" \(377 characters\) sed "s/^X//" >rename.c <<'END_OF_rename.c' X/* rename.c -- file renaming routine for systems without rename(2) X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/* LINTLIBRARY */ X Xint rename(from,to) Xregister char *from, *to; X{ X (void) unlink(to); X if (link(from, to) < 0) X return(-1); X X (void) unlink(from); X return(0); X} X X/* rename.c ends here */ END_OF_rename.c if test 377 -ne `wc -c <rename.c`; then echo shar: \"rename.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f rewinddir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rewinddir.c\" else echo shar: Extracting \"rewinddir.c\" \(746 characters\) sed "s/^X//" >rewinddir.c <<'END_OF_rewinddir.c' X/* X rewinddir -- rewind a directory stream X X last edit: 25-Apr-1987 D A Gwyn X X This is not simply a call to seekdir(), because seekdir() X will use the current buffer whenever possible and we need X rewinddir() to forget about buffered data. X*/ X X#include <sys/errno.h> X#include <sys/types.h> X#include <dirent.h> X Xextern off_t lseek(); X Xextern int errno; X X#ifndef NULL X#define NULL 0 X#endif X X#ifndef SEEK_SET X#define SEEK_SET 0 X#endif X Xvoid Xrewinddir( dirp ) X register DIR *dirp; /* stream from opendir() */ X { X if ( dirp == NULL || dirp->dd_buf == NULL ) X { X errno = EFAULT; X return; /* invalid pointer */ X } X X dirp->dd_loc = dirp->dd_size = 0; /* invalidate buffer */ X (void)lseek( dirp->dd_fd, (off_t)0, SEEK_SET ); /* may set errno */ X } END_OF_rewinddir.c if test 746 -ne `wc -c <rewinddir.c`; then echo shar: \"rewinddir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f rmdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rmdir.c\" else echo shar: Extracting \"rmdir.c\" \(489 characters\) sed "s/^X//" >rmdir.c <<'END_OF_rmdir.c' X/* rmdir.c -- remove a directory. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ X Xint rmdir(dir) Xchar *dir; X{ X extern char *malloc(); X char *path = malloc(strlen(dir) + 25); X int status; X X if (path == (char *)0) X status = -1; X else X { X (void) sprintf(path, "/bin/rmdir %s 2>/dev/null", dir); X status = system(path); X } X (void) free(path); X return(status); X} X X/* rmdir.c ends here */ END_OF_rmdir.c if test 489 -ne `wc -c <rmdir.c`; then echo shar: \"rmdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f search.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"search.h\" else echo shar: Extracting \"search.h\" \(259 characters\) sed "s/^X//" >search.h <<'END_OF_search.h' X/* search.h -- declarations for POSIX/SVID-compatible search functions */ X X/* HSEARCH(3C) */ Xtypedef struct entry { char *key, *data; } ENTRY; Xtypedef enum { FIND, ENTER } ACTION; X X/* TSEARCH(3C) */ Xtypedef enum { preorder, postorder, endorder, leaf } VISIT; END_OF_search.h if test 259 -ne `wc -c <search.h`; then echo shar: \"search.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f ssignal.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"ssignal.c\" else echo shar: Extracting \"ssignal.c\" \(769 characters\) sed "s/^X//" >ssignal.c <<'END_OF_ssignal.c' X/* X * ssignal -- user-settable software signals facility X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X#include <signal.h> X X#define SIGMAX 16 X Xstatic int (*sigs[SIGMAX])(); X Xint (*ssignal(sig, fn))() Xregister int sig, (*fn)(); X{ X register int (*oldfn)(); X X if(sig >= 1 && sig <= SIGMAX) X { X oldfn = sigs[sig - 1]; X sigs[sig - 1] = fn; X } X else X oldfn = SIG_DFL; X return(oldfn); X} X Xint gsignal(sig) Xregister int sig; X{ X register int (*sigfn)(); X X if (sig < 1 || sig > SIGMAX || (sigfn = sigs[sig - 1]) == SIG_DFL) X return(0); X else if (sigfn == SIG_IGN) X return(1); X else X { X sigs[sig - 1] = SIG_DFL; X return((*sigfn)(sig)); X } X} X X/* ssignal.c ends here */ END_OF_ssignal.c if test 769 -ne `wc -c <ssignal.c`; then echo shar: \"ssignal.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strchr.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strchr.c\" else echo shar: Extracting \"strchr.c\" \(355 characters\) sed "s/^X//" >strchr.c <<'END_OF_strchr.c' X/* X * Local copy of strchr (a.k.a. index) for portability. X * Totally public domain. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X X#include <stdio.h> X Xchar * Xstrchr(s, c) Xchar *s, c; X{ X char *x = s; X X while (*x != c) X if (*x == '\0') X return(NULL); X else X ++x; X return(x); X} X END_OF_strchr.c if test 355 -ne `wc -c <strchr.c`; then echo shar: \"strchr.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strcspn.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strcspn.c\" else echo shar: Extracting \"strcspn.c\" \(556 characters\) sed "s/^X//" >strcspn.c <<'END_OF_strcspn.c' X/* X * strcspn - find length of initial segment of s1 consisting entirely X * of characters not from s2 X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X Xint strcspn(s1, s2) Xchar *s1, *s2; X{ X register char *scan1; X register char *scan2; X register int count; X X count = 0; X for (scan1 = s1; *scan1 != '\0'; scan1++) { X for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ X if (*scan1 == *scan2++) X return(count); X count++; X } X return(count); X} X X/* strcspn.c ends here */ END_OF_strcspn.c if test 556 -ne `wc -c <strcspn.c`; then echo shar: \"strcspn.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strdup.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strdup.c\" else echo shar: Extracting \"strdup.c\" \(331 characters\) sed "s/^X//" >strdup.c <<'END_OF_strdup.c' X/* strdup.c -- duplicate string contents using malloc(3) X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X Xchar X*strdup(str) Xchar *str; X{ X extern char *malloc(), *strcpy(); X X char *copy = malloc(strlen(str) + 1); X X return(strcpy(copy, str)); X} X X/* strdup.c ends here */ END_OF_strdup.c if test 331 -ne `wc -c <strdup.c`; then echo shar: \"strdup.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f string.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"string.h\" else echo shar: Extracting \"string.h\" \(348 characters\) sed "s/^X//" >string.h <<'END_OF_string.h' X/* string.h -- POSIX/X3J11/SVID string and memory-handling declarations */ X Xextern char *strcpy(), *strncpy(), *strcat(), *strncat(); Xextern char *strchr(), *strrchr(), *strpbrk(), *strtok(); Xextern int strcmp(), strncmp(), strlen(), strspn(), strcspn(), memcmp(); Xextern char *memcpy(), *memccpy(), *memchr(), *memset(); X X/* string.h ends here */ END_OF_string.h if test 348 -ne `wc -c <string.h`; then echo shar: \"string.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f strpbrk.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strpbrk.c\" else echo shar: Extracting \"strpbrk.c\" \(1342 characters\) sed "s/^X//" >strpbrk.c <<'END_OF_strpbrk.c' X/* strpbrk.c -- return ptr to 1st instance of any char in arg 2 within arg 1 X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/* LINTLIBRARY */ X Xchar * Xstrpbrk(str, chars) Xregister char *str, *chars; X{ X register char *cp; X X do { X cp = chars - 1; X while (*++cp) { X if (*str == *cp) X return str; X } X } while X (*str++); X return (char *)0; X} X X/************************************************************************** X XIf you happen to be a 3b2, 3b5, 3b10, or 3b15 (but not a 3b1!) you can use this X X .file "strpbrk.u3b" # think of this line as an offering to the gods X X# char *strpbrk(s1, s2) char *s1, *s2; X# Finds first occurance in s1 of a character in s2. X X .text X .globl strpbrk X .align 4 Xstrpbrk: X save &2 # save r7 and r8 X movw 0(%ap), %r0 # r0 = s1 X movw 4(%ap), %r8 # r8 = s2 X movw &0, %r2 # string termination character X jmp L2 XL1: # while (*s1 != '\0') { X movw %r8, %r7 # get s2 X locce %r7, %r1, %r2 # strchr(s2, *s1) X je L4 # if found, return X addw2 &1, %r0 # increment s1 XL2: movb 0(%r0), %r1 # get *s1 X jne L1 # loop if not at end of string X movw &0, %r0 # set s1 to NULL XL4: ret &2 # and return s1 X**************************************************************************/ X/* strpbrk.c ends here */ END_OF_strpbrk.c if test 1342 -ne `wc -c <strpbrk.c`; then echo shar: \"strpbrk.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strrchr.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strrchr.c\" else echo shar: Extracting \"strrchr.c\" \(381 characters\) sed "s/^X//" >strrchr.c <<'END_OF_strrchr.c' X/* X * Return ptr in sp at which the character c last appears, or X * NULL if not found X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ X Xchar *strrchr(sp, c) Xregister char *sp, c; X{ X register char *rp; X X rp = (char *)0; X do { X if (*sp == c) X rp = sp; X } while X (*sp++); X return(rp); X} END_OF_strrchr.c if test 381 -ne `wc -c <strrchr.c`; then echo shar: \"strrchr.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strspn.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strspn.c\" else echo shar: Extracting \"strspn.c\" \(526 characters\) sed "s/^X//" >strspn.c <<'END_OF_strspn.c' X/* X * strspn - find length of initial segment of s1 consisting entirely X * of characters from s2 X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X Xint Xstrspn(s1, s2) Xchar *s1; Xchar *s2; X{ X register char *scan1; X register char *scan2; X register int count; X X count = 0; X for (scan1 = s1; *scan1 != '\0'; scan1++) { X for (scan2 = s2; *scan2 != '\0'; scan2++) X if (*scan1 == *scan2) X break; X if (*scan2 == '\0') X return(count); X count++; X } X return(count); X} END_OF_strspn.c if test 526 -ne `wc -c <strspn.c`; then echo shar: \"strspn.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strtok.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strtok.c\" else echo shar: Extracting \"strtok.c\" \(1333 characters\) sed "s/^X//" >strtok.c <<'END_OF_strtok.c' X/* strtok.c -- return tokens from a string, NULL if no token left */ X/* LINTLIBRARY */ X X/* X * Get next token from string s1 (NULL on 2nd, 3rd, etc. calls), X * where tokens are nonempty strings separated by runs of X * chars from s2. Writes NULs into s1 to end tokens. s2 need not X * remain constant from call to call. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X X#define NULL 0 X Xchar * Xstrtok(s1, s2) Xchar *s1; Xregister char *s2; X{ X register char *scan; X char *tok; X register char *scan2; X static char *scanpoint = (char *)NULL; X X if (s1 == (char *)NULL && scanpoint == (char *)NULL) X return((char *)NULL); X if (s1 != (char *)NULL) X scan = s1; X else X scan = scanpoint; X X /* X * Scan leading delimiters. X */ X for (; *scan != '\0'; scan++) { X for (scan2 = s2; *scan2 != '\0'; scan2++) X if (*scan == *scan2) X break; X if (*scan2 == '\0') X break; X } X if (*scan == '\0') { X scanpoint = (char *)NULL; X return((char *)NULL); X } X X tok = scan; X X /* X * Scan token. X */ X for (; *scan != '\0'; scan++) { X for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ X if (*scan == *scan2++) { X scanpoint = scan+1; X *scan = '\0'; X return(tok); X } X } X X /* X * Reached end of string. X */ X scanpoint = (char *)NULL; X return(tok); X} X X/* strtok.c ends here */ END_OF_strtok.c if test 1333 -ne `wc -c <strtok.c`; then echo shar: \"strtok.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f sys.dirent.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"sys.dirent.h\" else echo shar: Extracting \"sys.dirent.h\" \(1311 characters\) sed "s/^X//" >sys.dirent.h <<'END_OF_sys.dirent.h' X/* X <sys/dirent.h> -- file system independent directory entry (SVR3) X X last edit: 13-Oct-1987 D A Gwyn X X prerequisite: <sys/types.h> X*/ X Xstruct dirent /* data from getdents()/readdir() */ X { X long d_ino; /* inode number of entry */ X off_t d_off; /* offset of disk directory entry */ X unsigned short d_reclen; /* length of this record */ X char d_name[1]; /* name of file */ /* non-POSIX */ X }; X X#ifdef BSD_SYSV /* (e.g., when compiling getdents.c) */ Xextern struct dirent __dirent; /* (not actually used) */ X/* The following is portable, although rather silly. */ X#define DIRENTBASESIZ (__dirent.d_name - (char *)&__dirent.d_ino) X X#else X/* The following nonportable ugliness could have been avoided by defining X DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments. X There shouldn't be any problem if you avoid using the DIRENTSIZ() macro. */ X X#define DIRENTBASESIZ (((struct dirent *)0)->d_name \ X - (char *)&((struct dirent *)0)->d_ino) X#endif X X#define DIRENTSIZ( namlen ) ((DIRENTBASESIZ + sizeof(long) + (namlen)) \ X / sizeof(long) * sizeof(long)) X X/* DAG -- the following was moved from <dirent.h>, which was the wrong place */ X#define MAXNAMLEN 512 /* maximum filename length */ X X#ifndef NAME_MAX X#define NAME_MAX (MAXNAMLEN - 1) /* DAG -- added for POSIX */ X#endif END_OF_sys.dirent.h if test 1311 -ne `wc -c <sys.dirent.h`; then echo shar: \"sys.dirent.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f telldir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"telldir.c\" else echo shar: Extracting \"telldir.c\" \(794 characters\) sed "s/^X//" >telldir.c <<'END_OF_telldir.c' X/* X telldir -- report directory stream position X X last edit: 25-Apr-1987 D A Gwyn X X NOTE: 4.nBSD directory compaction makes seekdir() & telldir() X practically impossible to do right. Avoid using them! X*/ X X#include <sys/errno.h> X#include <sys/types.h> X#include <dirent.h> X Xextern off_t lseek(); X Xextern int errno; X X#ifndef SEEK_CUR X#define SEEK_CUR 1 X#endif X Xoff_t Xtelldir( dirp ) /* return offset of next entry */ X DIR *dirp; /* stream from opendir() */ X { X if ( dirp == NULL || dirp->dd_buf == NULL ) X { X errno = EFAULT; X return -1; /* invalid pointer */ X } X X if ( dirp->dd_loc < dirp->dd_size ) /* valid index */ X return ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off; X else /* beginning of next directory block */ X return lseek( dirp->dd_fd, (off_t)0, SEEK_CUR ); X } END_OF_telldir.c if test 794 -ne `wc -c <telldir.c`; then echo shar: \"telldir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f testdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"testdir.c\" else echo shar: Extracting \"testdir.c\" \(837 characters\) sed "s/^X//" >testdir.c <<'END_OF_testdir.c' X/* X testdir -- basic test for C library directory access routines X X last edit: 25-Apr-1987 D A Gwyn X*/ X X#include <sys/types.h> X#include <stdio.h> X#include <dirent.h> X Xextern void exit(); Xextern int strcmp(); X Xmain( argc, argv ) X int argc; X register char **argv; X { X register DIR *dirp; X register struct dirent *dp; X int nerrs = 0; /* total not found */ X X if ( (dirp = opendir( "." )) == NULL ) X { X (void)fprintf( stderr, "Cannot open \".\" directory\n" ); X exit( 1 ); X } X X while ( --argc > 0 ) X { X ++argv; X X while ( (dp = readdir( dirp )) != NULL ) X if ( strcmp( dp->d_name, *argv ) == 0 ) X { X (void)printf( "\"%s\" found.\n", *argv ); X break; X } X X if ( dp == NULL ) X { X (void)printf( "\"%s\" not found.\n", *argv ); X ++nerrs; X } X X rewinddir( dirp ); X } X X (void)closedir( dirp ); X exit( nerrs ); X } END_OF_testdir.c if test 837 -ne `wc -c <testdir.c`; then echo shar: \"testdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f tfind.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"tfind.c\" else echo shar: Extracting \"tfind.c\" \(983 characters\) sed "s/^X//" >tfind.c <<'END_OF_tfind.c' X/* X * Tree search generalized from Knuth (6.2.2) Algorithm T just like X * the AT&T man page says. X * X * The node_t structure is for internal use only, lint doesn't grok it. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X#include <search.h> X Xtypedef struct node_t X{ X char *key; X struct node_t *llink, *rlink; X} node; X Xnode *tfind(key, rootp, compar) X/* find a node, or return 0 */ Xchar *key; /* key to be found */ Xregister node **rootp; /* address of the tree root */ Xint (*compar)(); /* ordering function */ X{ X if (rootp == (struct node_t **)0) X return ((struct node_t *)0); X while (*rootp != (struct node_t *)0) /* T1: */ X { X int r; X if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ X return (*rootp); /* key found */ X rootp = (r < 0) ? X &(*rootp)->llink : /* T3: follow left branch */ X &(*rootp)->rlink; /* T4: follow right branch */ X } X return (node *)0; X} END_OF_tfind.c if test 983 -ne `wc -c <tfind.c`; then echo shar: \"tfind.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f unistd.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"unistd.h\" else echo shar: Extracting \"unistd.h\" \(1088 characters\) sed "s/^X//" >unistd.h <<'END_OF_unistd.h' X/* unistd.h -- symbolic constands for POSIX conformance */ X X#ifndef R_OK /* 4.2BSD may have got these from /usr/include/sys/file.h */ X X/* Symbolic constants for the "access" routine: */ X#define R_OK 4 /* Test for Read permission */ X#define W_OK 2 /* Test for Write permission */ X#define X_OK 1 /* Test for eXecute permission */ X#define F_OK 0 /* Test for existence of File */ X X#endif /* R_OK */ X X#ifndef F_ULOCK X X#define F_ULOCK 0 /* Unlock a previously locked region */ X#define F_LOCK 1 /* Lock a region for exclusive use */ X#define F_TLOCK 2 /* Test and lock a region for exclusive use */ X#define F_TEST 3 /* Test a region for other processes locks */ X X#endif /* F_ULOCK */ X X/* Symbolic constants for the "lseek" routine: */ X#define SEEK_SET 0 /* Set file pointer to "offset" */ X#define SEEK_CUR 1 /* Set file pointer to current plus "offset" */ X#define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ X X/* Path names: */ X#define GF_PATH "/etc/group" /* Path name of the "group" file */ X#define PF_PATH "/etc/passwd" /* Path name of the "passwd" file */ X X/* unistd.h ends here */ END_OF_unistd.h if test 1088 -ne `wc -c <unistd.h`; then echo shar: \"unistd.h\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 1 \(of 5\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Lenny Tropiano ICUS Software Systems [w] +1 (516) 589-7930 lenny@icus.islp.ny.us Telex; 154232428 ICUS [h] +1 (516) 968-8576 {ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752
lenny@icus.islp.ny.us (Lenny Tropiano) (08/03/89)
#! /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 5)." # Contents: dirent.4 getdents.2 lsearch.3c memcpy.c memory.3c mkdir.3 # opendir.c rename.3 rmdir.3 seekdir.c ssignal.3c strtol.3c strtol.c # sys._dir.h # Wrapped by lenny@icus on Wed Aug 2 21:40:25 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f dirent.4 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"dirent.4\" else echo shar: Extracting \"dirent.4\" \(1593 characters\) sed "s/^X//" >dirent.4 <<'END_OF_dirent.4' X.TH DIRENT 4 "Standard Extension" X.SH NAME Xdirent \- file system independent directory entry X.SH SYNOPSIS X.B "#include <sys/types.h>" X.br X.B "#include <sys/dirent.h>" X.SH DESCRIPTION XDifferent file system types Xmay have different directory entries. XThe X.I dirent Xstructure defines a Xfile system independent directory entry, Xwhich contains information common to Xdirectory entries in different file system types. XA set of these structures is returned by the X.IR getdents (2) Xsystem call. X.P XThe X.I dirent Xstructure is defined below. X.br Xstruct dirent { X.br X long d_ino; X.br X off_t d_off; X.br X unsigned short d_reclen; X.br X char d_name[1]; X.br X }; X.P XThe field X.I d_ino Xis a number which is unique Xfor each file in the file system. XThe field X.I d_off\^ Xrepresents an offset of that directory entry Xin the actual file system directory. XThe field X.I d_name Xis the beginning of the character array Xgiving the name of the directory entry. XThis name is null terminated Xand may have at most X.SM NAME_MAX Xcharacters in addition to the null terminator. XThis results in file system independent directory entries Xbeing variable-length entities. XThe value of X.I d_reclen Xis the record length of this entry. XThis length is defined to be the number of bytes Xbetween the beginning of the current entry and the next one, Xadjusted so that the next entry Xwill start on a long boundary. X.SH FILES X/usr/include/sys/dirent.h X.SH "SEE ALSO" Xgetdents(2). X.SH WARNING XThe field X.I d_off\^ Xdoes not have a simple interpretation Xfor some file system types Xand should not be used directly by applications. END_OF_dirent.4 if test 1593 -ne `wc -c <dirent.4`; then echo shar: \"dirent.4\" unpacked with wrong size! fi # end of overwriting check fi if test -f getdents.2 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"getdents.2\" else echo shar: Extracting \"getdents.2\" \(1922 characters\) sed "s/^X//" >getdents.2 <<'END_OF_getdents.2' X.TH GETDENTS 2 "Standard Extension" X.SH NAME Xgetdents \- get directory entries in a file system independent format X.SH SYNOPSIS X.B "#include <sys/types.h>" X.br X.B "#include <sys/dirent.h>" X.P X.B "int getdents (fildes, buf, nbyte)" X.br X.B "int fildes;" X.br X.B "char \(**buf;" X.br X.B "unsigned nbyte;" X.SH DESCRIPTION X.I Fildes Xis a file descriptor obtained from an X.IR open (2) Xor X.IR dup (2) Xsystem call. X.P X.I Getdents Xattempts to read X.I nbyte Xbytes from the directory associated with X.I fildes Xand to format them as Xfile system independent entries Xin the buffer pointed to by X.IR buf . XSince the file system independent directory entries Xare of variable length, Xin most cases the actual number of bytes returned Xwill be less than X.IR nbyte . X.P XThe file system independent directory entry is specified by the X.I dirent Xstructure. XFor a description of this see X.IR dirent (4). X.P XOn devices capable of seeking, X.I getdents Xstarts at a position in the file given by Xthe file pointer associated with X.IR fildes . XUpon return from X.IR getdents , Xthe file pointer has been incremented Xto point to the next directory entry. X.P XThis system call was developed in order to implement the X.I readdir Xroutine X[for a description see X.IR directory (3C)] Xand should not be used for other purposes. X.SH "SEE ALSO" Xdirectory(3C), dirent(4). X.SH DIAGNOSTICS XUpon successful completion Xa non-negative integer is returned Xindicating the number of bytes of X.I buf\^ Xactually filled. X(This need not be the number actually used Xin the actual directory file.)\|\| XA value of zero Xindicates the end of the directory has been reached. XIf X.I getdents Xfails for any other reason, Xa value of \-1 is returned and Xthe external integer variable X.I errno Xis set to indicate the error. X.SH WARNINGS XEntries for "." and ".." Xmay not be reported for some file system types. X.P XThe exact set of X.I errno Xvalues and meanings may vary among implementations. END_OF_getdents.2 if test 1922 -ne `wc -c <getdents.2`; then echo shar: \"getdents.2\" unpacked with wrong size! fi # end of overwriting check fi if test -f lsearch.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"lsearch.3c\" else echo shar: Extracting \"lsearch.3c\" \(2671 characters\) sed "s/^X//" >lsearch.3c <<'END_OF_lsearch.3c' X.TH LSEARCH 3C "Standard extension" X.SH NAME Xlsearch, lfind \- linear search and update X.SH SYNOPSIS X.B #include <stdio.h> X.br X.B #include <search.h> X.PP X.B "char \(**lsearch ((char \(**)key, (char \(**)base, nelp, sizeof(\(**key), compar)" X.br X.B unsigned \(**nelp; X.br X.B int (\(**compar)( ); X.PP X.B "char \(**lfind ((char \(**)key, (char \(**)base, nelp, sizeof(\(**key), compar)" X.br X.B unsigned \(**nelp; X.br X.B int (\(**compar)( ); X.SH DESCRIPTION X.I Lsearch Xis a linear search routine generalized from Knuth (6.1) Algorithm S. XIt returns a pointer into a table indicating where Xa datum may be found. XIf the datum does not occur, it is added Xat the end of the table. X.B Key Xpoints to the datum to be sought in the table. X.B Base Xpoints to the first element in the table. X.B Nelp Xpoints to an integer containing the current number of Xelements in the table. XThe integer is incremented if the datum is added to the table. X.B Compar Xis the name of the comparison function which the user must supply X.RI ( strcmp , Xfor example). XIt is called with two arguments that point Xto the elements being compared. XThe function must return zero if the elements Xare equal and non-zero otherwise. X.PP X.I Lfind Xis the same as X.I lsearch Xexcept that if the datum is not found, it is not added Xto the table. XInstead, a X.SM NULL Xpointer is returned. X.SH NOTES XThe pointers to the key and the element Xat the base of the table should be Xof type pointer-to-element, Xand cast to type pointer-to-character. X.br XThe comparison function need not compare every byte, Xso arbitrary data may be contained in the elements Xin addition to the values being compared. X.br XAlthough declared as type pointer-to-character, Xthe value returned should be cast into type pointer-to-element. X.SH EXAMPLE XThis fragment will read in \(<= \s-1TABSIZE\s+1 Xstrings of length \(<= \s-1ELSIZE\s+1 Xand store them in a table, eliminating duplicates. X.PP X.RS X.nf X.ss 18 X#include <stdio.h> X#include <search.h> X X#define \s-1TABSIZE\s+1 50 X#define \s-1ELSIZE\s+1 120 X X char line[\s-1ELSIZE\s+1], tab[\s-1TABSIZE\s+1][\s-1ELSIZE\s+1], \(**lsearch( ); X unsigned nel = 0; X int strcmp( ); X . . . X while (fgets(line, \s-1ELSIZE\s+1, stdin) != \s-1NULL\s+1 && X nel < \s-1TABSIZE\s+1) X (void) lsearch(line, (char \(**)tab, &nel, X \s-1ELSIZE\s+1, strcmp); X . . . X.fi X.SH SEE ALSO Xbsearch(3C), hsearch(3C), tsearch(3C). X.SH DIAGNOSTICS XIf the searched for datum is found, both X.I lsearch Xand X.I lfind Xreturn a pointer Xto it. XOtherwise, X.I lfind Xreturns NULL and X.I lsearch Xreturns a pointer to the newly Xadded element. X.SH BUGS XUndefined results can occur if there is not enough room in the table to Xadd a new item. END_OF_lsearch.3c if test 2671 -ne `wc -c <lsearch.3c`; then echo shar: \"lsearch.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f memcpy.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memcpy.c\" else echo shar: Extracting \"memcpy.c\" \(2473 characters\) sed "s/^X//" >memcpy.c <<'END_OF_memcpy.c' X/* X * Copy first n bytes of s to t, return t X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X */ X/*LINTLIBRARY*/ Xchar *memcpy(t, s, n) Xregister char *t, *s; Xregister int n; X{ X register char *os = t; X X while (--n >= 0) X *t++ = *s++; X return(os); X} X X/************************************************************************** X XIf you happen to be using a PDP-11, you can use this assembler version... X X/ MEMCPY(TO, FROM, N) CHAR *TO, *FROM; X/ X/ Copy "n" bytes from "from" to "to". X/ X.globl _memcpy X.globl csav, cret X X.text X_memcpy: jsr r0, csav / save registers X mov r5, r4 / get arguments... X cmp (r4)+, (r4)+ / X mov (r4)+, r1 / to X mov (r4)+, r0 / from X mov (r4), r2 / byte count X beq ret / if zero then return X bit $1, r1 / is "to" odd X beq 1f / yes... X movb (r0)+, (r1)+ / copy one byte to make it even X dec r2 / and adjust byte count X1: mov r2, r3 / save (low bit of) count X asr r2 / convert from bytes to words X beq 3f / if any words to copy... X bit $1, r0 / is "from" even now? X beq 2f / if not ... X1: movb (r0)+, (r1)+ / copy bytes... X movb (r0)+, (r1)+ / ... X sob r2, 1b / ... X br 3f / else ... X2: mov (r0)+, (r1)+ / copy words... X sob r2, 2b / ... X3: ror r3 / is byte count odd? X bcc ret / if so... X movb (r0)+, (r1)+ / copy odd byte. Xret: jmp cret / return X XIf you happen to be a VAX, you can use this: X X# memcpy(to, from, count) char *to, *from; int count; X# X# Copy "count" bytes from "from" to "to"; not guaranteed to X# work if "from" and "to" overlap. X X .align 2 X .globl _memcpy X_memcpy: X .word 0 X movl 4(ap), r3 # r3 = to X movl 8(ap), r1 # r1 = from XL1: X movzwl $65535, r0 # while more than 65535 bytes to move X cmpl 12(ap), r0 X jleq L2 # if <= 65535, break X subl2 r0, 12(ap) # count-=65535 (bytes moved this time) X movc3 r0, (r1), (r3) # r1, r3 magically point to next 65K X brb L1 XL2: X movc3 12(ap), (r1), (r3) # move up to 65535 bytes X ret X XIf you happen to be a 3b2, 3b5, 3b10, or 3b15 (but not a 3b1!) you can use this X X .file "memcpy.s" # silly assembler wants this line X .globl memcpy X .align 4 Xmemcpy: save &0 # set up stack frame X movw 0(%ap), %r1 # get source X movw 4(%ap), %r0 # and destination X movw 8(%ap), %r2 # get count X movblb # this instruction does it all X ret &0 # return X X**************************************************************************/ END_OF_memcpy.c if test 2473 -ne `wc -c <memcpy.c`; then echo shar: \"memcpy.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f memory.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"memory.3c\" else echo shar: Extracting \"memory.3c\" \(2063 characters\) sed "s/^X//" >memory.3c <<'END_OF_memory.3c' X.TH MEMORY 3C "Standard Extension" X.SH NAME Xmemccpy, memchr, memcmp, memcpy, memset \- memory operations X.SH SYNOPSIS X.nf X.B #include <memory.h> X.PP X.B char \(**memccpy (s1, s2, c, n) X.B char \(**s1, \(**s2; X.B int c, n; X.PP X.B char \(**memchr (s, c, n) X.B char \(**s; X.B int c, n; X.PP X.B int memcmp (s1, s2, n) X.B char \(**s1, \(**s2; X.B int n; X.PP X.B char \(**memcpy (s1, s2, n) X.B char \(**s1, \(**s2; X.B int n; X.PP X.B char \(**memset (s, c, n) X.B char \(**s; X.B int c, n; X.fi X.SH DESCRIPTION XThese functions operate as efficiently as possible on memory areas (arrays of Xcharacters bounded by a count, not necessarily terminated by a null character). XThey do not check for overflow of any receiving memory area. X.PP X.I Memccpy Xcopies characters from memory area X.B s2 Xinto X.BR s1 , Xstopping after the first occurrence of character X.B c Xhas been copied, or after X.B n Xcharacters have been copied, whichever comes first. XIt returns a pointer to the character after Xthe copy of X.B c Xin X.BR s1 , Xor a X.SM NULL Xpointer if X.B c Xwas not found in the first X.B n Xcharacters of X.BR s2 . X.PP X.PP X.I Memchr Xreturns a pointer to the first Xoccurrence of character X.B c Xin the first X.B n Xcharacters of memory area X.BR s, Xor a X.SM NULL Xpointer if X.B c Xdoes not occur. X.PP X.I Memcmp Xcompares its arguments, looking at the first X.B n Xcharacters only, and returns an integer Xless than, equal to, or greater than 0, Xaccording as X.B s1 Xis lexicographically less than, equal to, or Xgreater than X.BR s2 . X.PP X.I Memcpy Xcopies X.B n Xcharacters from memory area X.B s2 Xto X.BR s1 . XIt returns X.BR s1 . X.PP X.I Memset Xsets the first X.B n Xcharacters in memory area X.B s Xto the value of character X.BR c . XIt returns X.BR s . X.SH NOTE XAll these functions are declared in the optional X.I <memory.h> Xheader file. X.SH BUGS X.I Memcmp Xuses native character comparison, which may be signed or unsigned. XThus the sign of the value returned when one of the characters has its Xhigh-order bit set is implementation-dependent. X.PP XOverlapping moves may scramble the data in both source and target areas. END_OF_memory.3c if test 2063 -ne `wc -c <memory.3c`; then echo shar: \"memory.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f mkdir.3 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"mkdir.3\" else echo shar: Extracting \"mkdir.3\" \(2107 characters\) sed "s/^X//" >mkdir.3 <<'END_OF_mkdir.3' X.TH MKDIR 3 "Standard Extension" X.SH NAME Xmkdir \- make a directory file X.SH SYNOPSIS X.nf X.ft B Xmkdir(path, mode) Xchar *path; Xint mode; X.fi X.ft R X.SH DESCRIPTION X.I Mkdir Xcreates a new directory file with name X.IR path . XThe mode of the new file Xis initialized from X.IR mode . X(The protection part of the mode Xis modified by the process's mode mask; see X.IR umask (2)). X.PP XThe directory's owner ID is set to the process's effective user ID. XThe directory's group ID is set to the process's effective group ID. X.PP XThe low-order 9 bits of mode are modified by the process's Xfile mode creation mask: all bits set in the process's file mode Xcreation mask are cleared. See X.IR umask (2). X.SH NOTES XThis function emulates the SVr3 behavior (group ID of the directory Xis the effective group ID of the calling process) rather than the BSD Xbehavior (group ID of the directory is the group ID of the parent directory). X.PP XOn USG it will succeed if the real or apparent uid of the calling process Xhas write privileges in the current directory (the latter case is implemented Xby a kluge that tries to set the parent directory's permissions to 0777, 'ware Xsecurity holes!). The new directory will be owned by the effective uid. X.PP XOn V7 (because it restricts the chown(2) call and mkdir(1) makes Xdirectories owned by the real ID of its caller) the call will only succeed Xif the real ID matches, and the new directory will be owned by the real Xuid. X.PP XThe overhead of this emulation is fairly high, requiring a fork/exec (on AT&T Xversions, two fork-execs). X.SH "RETURN VALUE XA 0 return value indicates success. A \-1 return value Xindicates an error, and an error code is stored in X.I errno. X.SH "ERRORS X.I Mkdir Xwill fail and no directory will be created if: X[ENOTDIR] XA component of the path prefix is not a directory. X.TP 15 X[ENOENT] XA component of the path prefix does not exist. X.TP 15 X[EEXIST] XThe named file exists. X.TP 15 X[EACCES] XA component of the path prefix denies search permission, or write permission Xis denied on the parent of the directory to be created. X.SH "SEE ALSO" Xchmod(2), stat(2), umask(2) END_OF_mkdir.3 if test 2107 -ne `wc -c <mkdir.3`; then echo shar: \"mkdir.3\" unpacked with wrong size! fi # end of overwriting check fi if test -f opendir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"opendir.c\" else echo shar: Extracting \"opendir.c\" \(1473 characters\) sed "s/^X//" >opendir.c <<'END_OF_opendir.c' X/* X opendir -- open a directory stream X X last edit: 16-Jun-1987 D A Gwyn X*/ X X#include <sys/errno.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <dirent.h> X X#ifdef BSD_SYSV X#define open _open /* avoid emulation overhead */ X#endif X Xtypedef char *pointer; /* (void *) if you have it */ X Xextern void free(); Xextern pointer malloc(); Xextern int open(), close(), fstat(); X Xextern int errno; X X#ifndef NULL X#define NULL 0 X#endif X X#ifndef O_RDONLY X#define O_RDONLY 0 X#endif X X#ifndef S_ISDIR /* macro to test for directory file */ X#define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR) X#endif X XDIR * Xopendir( dirname ) X char *dirname; /* name of directory */ X { X register DIR *dirp; /* -> malloc'ed storage */ X register int fd; /* file descriptor for read */ X struct stat sbuf; /* result of fstat() */ X X if ( (fd = open( dirname, O_RDONLY )) < 0 ) X return NULL; /* errno set by open() */ X X if ( fstat( fd, &sbuf ) != 0 || !S_ISDIR( sbuf.st_mode ) ) X { X (void)close( fd ); X errno = ENOTDIR; X return NULL; /* not a directory */ X } X X if ( (dirp = (DIR *)malloc( sizeof(DIR) )) == NULL X || (dirp->dd_buf = (char *)malloc( (unsigned)DIRBUF )) == NULL X ) { X register int serrno = errno; X /* errno set to ENOMEM by sbrk() */ X X if ( dirp != NULL ) X free( (pointer)dirp ); X X (void)close( fd ); X errno = serrno; X return NULL; /* not enough memory */ X } X X dirp->dd_fd = fd; X dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ X X return dirp; X } END_OF_opendir.c if test 1473 -ne `wc -c <opendir.c`; then echo shar: \"opendir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f rename.3 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rename.3\" else echo shar: Extracting \"rename.3\" \(2283 characters\) sed "s/^X//" >rename.3 <<'END_OF_rename.3' X.TH RENAME 3 "Standard Extension" X.SH NAME Xrename \- change the name of a file X.SH SYNOPSIS X.ft B X.nf Xrename(from, to) Xchar *from, *to; X.fi X.ft R X.SH DESCRIPTION X.I Rename Xcauses the link named X.I from Xto be renamed as X.IR to . XIf X.I to Xexists, then it is first removed. XBoth X.I from Xand X.I to Xmust be of the same type (i.e., both directories or both Xnon-directories), and must reside on the same file system. X.PP X.I Rename Xguarantees that an instance of X.I to Xwill always exist, even if the system should crash in Xthe middle of the operation. X.SH CAVEAT XThe system can deadlock if a loop in the file system graph is present. XThis loop takes the form of an entry in directory \*(lqa\*(rq, Xsay \*(lqa/foo\*(rq, Xbeing a hard link to directory \*(lqb\*(rq, and an entry in Xdirectory \*(lqb\*(rq, say \*(lqb/bar\*(rq, being a hard link Xto directory \*(lqa\*(rq. XWhen such a loop exists and two separate processes attempt to Xperform \*(lqrename a/foo b/bar\*(rq and \*(lqrename b/bar a/foo\*(rq, Xrespectively, Xthe system may deadlock attempting to lock Xboth directories for modification. XOn systems with a symbolic link capability, hard links to directories should be Xreplaced by symbolic links by the system administrator. X.SH "RETURN VALUE" XA 0 value is returned if the operation succeeds, otherwise X.I rename Xreturns \-1 and the global variable X.I errno Xindicates the reason for the failure. X.SH "ERRORS X.I Rename Xwill fail and nothing will change if any of the following are true: X.TP 15 X[ENOTDIR] XA component of either path prefix is not a directory. X.TP 15 X[ENOENT] XA component of either path prefix does not exist. X.TP 15 X[EACCES] XA component of either path prefix denies search permission. X.TP 15 X[ENOENT] XThe file named by \fIfrom\fP does not exist. X.TP 15 X[EXDEV] XThe link named by \fIto\fP and the file named by \fIfrom\fP Xare on different logical devices (file systems). Note that this error Xcode will not be returned if the implementation permits cross-device Xlinks. X.TP 15 X[EACCES] XThe requested link requires writing in a directory with a mode Xthat denies write permission. X.TP 15 X[EROFS] XThe requested link requires writing in a directory on a read-only file Xsystem. X.TP 15 X[EFAULT] X.I Path Xpoints outside the process's allocated address space. X.SH "SEE ALSO" Xopen(2) END_OF_rename.3 if test 2283 -ne `wc -c <rename.3`; then echo shar: \"rename.3\" unpacked with wrong size! fi # end of overwriting check fi if test -f rmdir.3 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rmdir.3\" else echo shar: Extracting \"rmdir.3\" \(1443 characters\) sed "s/^X//" >rmdir.3 <<'END_OF_rmdir.3' X.TH RMDIR 3 "Standard Extension" X.SH NAME Xrmdir \- remove a directory file X.SH SYNOPSIS X.nf X.ft B Xrmdir(path) Xchar *path; X.fi X.ft R X.SH DESCRIPTION X.I Rmdir Xremoves a directory file Xwhose name is given by X.I path. XThe directory must not have any entries other Xthan \*(lq.\*(rq and \*(lq..\*(rq. X.SH "RETURN VALUE XA 0 is returned if the remove succeeds; otherwise a \-1 is Xreturned. X.SH ERRORS XThe named file is removed unless one or more of the Xfollowing are true: X.TP 15 X[ENOTEMPTY] XThe named directory contains files other than ``.'' and ``..'' in it. X.TP 15 X[EPERM] XThe pathname contained a non-ASCII character. X.TP 15 X[ENOENT] XThe pathname was too long. X.TP 15 X[ENOTDIR] XA component of the path prefix is not a directory. X.TP 15 X[ENOENT] XThe named file does not exist. X.TP 15 X[EACCES] XA component of the path prefix denies search permission. X.TP 15 X[EACCES] XWrite permission is denied on the directory containing the link Xto be removed. X.TP 15 X[EBUSY] XThe directory to be removed is the mount point Xfor a mounted file system. X.TP 15 X[EROFS] XThe directory entry to be removed resides on a read-only file system. X.TP 15 X[EFAULT] X.I Path Xpoints outside the process's allocated address space. X.SH WARNING XThis call is implemented via a spawn of /bin/rmdir. Its error return status Xis therefore unreliable, and the value of errno after the call will not Xtypically reflect the above error conditions properly. X.SH "SEE ALSO" Xmkdir(3), unlink(2) END_OF_rmdir.3 if test 1443 -ne `wc -c <rmdir.3`; then echo shar: \"rmdir.3\" unpacked with wrong size! fi # end of overwriting check fi if test -f seekdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"seekdir.c\" else echo shar: Extracting \"seekdir.c\" \(2965 characters\) sed "s/^X//" >seekdir.c <<'END_OF_seekdir.c' X/* X seekdir -- reposition a directory stream X X last edit: 24-May-1987 D A Gwyn X X An unsuccessful seekdir() will in general alter the current X directory position; beware. X X NOTE: 4.nBSD directory compaction makes seekdir() & telldir() X practically impossible to do right. Avoid using them! X*/ X X#include <sys/errno.h> X#include <sys/types.h> X#include <dirent.h> X Xextern off_t lseek(); X Xextern int errno; X X#ifndef NULL X#define NULL 0 X#endif X X#ifndef SEEK_SET X#define SEEK_SET 0 X#endif X Xtypedef int bool; /* Boolean data type */ X#define false 0 X#define true 1 X Xvoid Xseekdir( dirp, loc ) X register DIR *dirp; /* stream from opendir() */ X register off_t loc; /* position from telldir() */ X { X register bool rewind; /* "start over when stymied" flag */ X X if ( dirp == NULL || dirp->dd_buf == NULL ) X { X errno = EFAULT; X return; /* invalid pointer */ X } X X /* A (struct dirent)'s d_off is an invented quantity on 4.nBSD X NFS-supporting systems, so it is not safe to lseek() to it. */ X X /* Monotonicity of d_off is heavily exploited in the following. */ X X /* This algorithm is tuned for modest directory sizes. For X huge directories, it might be more efficient to read blocks X until the first d_off is too large, then back up one block, X or even to use binary search on the directory blocks. I X doubt that the extra code for that would be worthwhile. */ X X if ( dirp->dd_loc >= dirp->dd_size /* invalid index */ X || ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off > loc X /* too far along in buffer */ X ) X dirp->dd_loc = 0; /* reset to beginning of buffer */ X /* else save time by starting at current dirp->dd_loc */ X X for ( rewind = true; ; ) X { X register struct dirent *dp; X X /* See whether the matching entry is in the current buffer. */ X X if ( (dirp->dd_loc < dirp->dd_size /* valid index */ X || readdir( dirp ) != NULL /* next buffer read */ X && (dirp->dd_loc = 0, true) /* beginning of buffer set */ X ) X && (dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off X <= loc /* match possible in this buffer */ X ) { X for ( /* dp initialized above */ ; X (char *)dp < &dirp->dd_buf[dirp->dd_size]; X dp = (struct dirent *)((char *)dp + dp->d_reclen) X ) X if ( dp->d_off == loc ) X { /* found it! */ X dirp->dd_loc = X (char *)dp - dirp->dd_buf; X return; X } X X rewind = false; /* no point in backing up later */ X dirp->dd_loc = dirp->dd_size; /* set end of buffer */ X } X else /* whole buffer past matching entry */ X if ( !rewind ) X { /* no point in searching further */ X errno = EINVAL; X return; /* no entry at specified loc */ X } X else { /* rewind directory and start over */ X rewind = false; /* but only once! */ X X dirp->dd_loc = dirp->dd_size = 0; X X if ( lseek( dirp->dd_fd, (off_t)0, SEEK_SET ) X != 0 X ) X return; /* errno already set (EBADF) */ X X if ( loc == 0 ) X return; /* save time */ X } X } X } END_OF_seekdir.c if test 2965 -ne `wc -c <seekdir.c`; then echo shar: \"seekdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ssignal.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"ssignal.3c\" else echo shar: Extracting \"ssignal.3c\" \(2129 characters\) sed "s/^X//" >ssignal.3c <<'END_OF_ssignal.3c' X.TH SSIGNAL 3C "Standard Extension" X.SH NAME Xssignal, gsignal \- software signals X.SH SYNOPSIS X.B #include <signal.h> X.PP X.B int (\(**ssignal (sig, action))( ) X.br X.B int sig, (\(**action)( ); X.PP X.B int gsignal (sig) X.br X.B int sig; X.SH DESCRIPTION X.I Ssignal Xand X.I gsignal Ximplement a software facility similar to X.IR signal (2). XOn some AT&T UNIX versions, an implementation of X.IR ssignal (3) Xis used by the Standard C Library to enable users to indicate the disposition Xof error conditions, and is also available to users for other purposes. This Xlibrary emulates that facility. X.PP XSoftware signals made available to users are associated Xwith integers in the inclusive range 1 through 15. A Xcall to X.I ssignal Xassociates a procedure, X.IR action , Xwith the software signal X.IR sig ; Xthe software signal, X.IR sig , Xis raised Xby a call to X.IR gsignal . XRaising a software signal causes the action established for that signal Xto be X.IR taken . X.PP XThe first argument to X.I ssignal Xis a number identifying the type of signal for which an action is to be Xestablished. The second argument defines the action; it is either the Xname of a (user-defined) X.I action function Xor one of the manifest constants X.SM X.B SIG_DFL X(default) or X.SM X.B SIG_IGN X(ignore). X.I Ssignal Xreturns the action previously established for that signal type; if no Xaction has been established or the signal number is illegal, X.I ssignal Xreturns X.SM X.BR SIG_DFL . X.PP X.I Gsignal Xraises the signal identified by its argument, X.IR sig : X.RS 5 X.PP XIf an action function has been established for X.IR sig , Xthen that action is reset to X.SM X.B SIG_DFL Xand the action function is entered with argument X.IR sig . X.I Gsignal Xreturns the value returned to it by the action function. X.PP XIf the action for X.I sig Xis X.SM X.BR SIG_IGN , X.I gsignal Xreturns the value 1 and takes no other action. X.PP XIf the action for X.I sig Xis X.SM X.BR SIG_DFL , X.I gsignal Xreturns the value 0 and takes no other action. X.PP XIf X.I sig Xhas an illegal value or no action was ever specified for X.IR sig , X.I gsignal Xreturns the value 0 and takes no other action. X.RE X.SH "SEE ALSO" Xsignal(2). END_OF_ssignal.3c if test 2129 -ne `wc -c <ssignal.3c`; then echo shar: \"ssignal.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strtol.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strtol.3c\" else echo shar: Extracting \"strtol.3c\" \(1522 characters\) sed "s/^X//" >strtol.3c <<'END_OF_strtol.3c' X.TH STRTOL 3C X.SH NAME Xstrtol, atol, atoi \- convert string to integer X.SH SYNOPSIS X.nf X.B long strtol (str, ptr, base) X.B char \(**str, \(**\(**ptr; X.B int base; X.SH DESCRIPTION X.I Strtol Xreturns as a long integer the value represented by the character string pointed Xto by X.IR str . XThe string is scanned up to the first character inconsistent with the base. XLeading ``white-space'' characters (as defined by X.I isspace Xin X.IR ctype (3C)) Xare ignored. X.PP XIf the value of X.I ptr Xis not (char \(**\(**)\s-1NULL\s+1, a pointer to the character terminating the Xscan is returned in the location pointed to by X.IR ptr . XIf no integer can be formed, that location is set to X.IR str , Xand zero is returned. X.PP XIf X.I base Xis positive (and not greater than 36), it is used as the base for conversion. XAfter an optional leading sign, leading zeros are ignored, and ``0x'' or ``0X'' Xis ignored if X.I base Xis 16. X.PP XIf X.I base Xis zero, the string itself determines the base thusly: After an optional leading Xsign a leading zero indicates octal conversion, and a leading ``0x'' or ``0X'' Xhexadecimal conversion. Otherwise, decimal conversion is used. X.PP XTruncation from long to int can, of course, take place upon assignment or by Xan explicit cast. X.PP X.I Atol(str) Xis equivalent to X.IR "strtol(str, (char \(**\(**)\s-1NULL\s+1, 10)" . X.PP X.I Atoi(str) Xis equivalent to X.IR "(int) strtol(str, (char \(**\(**)\s-1NULL\s+1, 10)" . X.SH SEE ALSO Xctype(3C), scanf(3S), strtod(3C), atoi(3S). X.SH BUGS XOverflow conditions are ignored. END_OF_strtol.3c if test 1522 -ne `wc -c <strtol.3c`; then echo shar: \"strtol.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strtol.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strtol.c\" else echo shar: Extracting \"strtol.c\" \(1737 characters\) sed "s/^X//" >strtol.c <<'END_OF_strtol.c' X/* X * strtol - convert string to long integer. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X * X * Compile with -DTEST to get short interactive main() for testing. X */ X X#include <stdio.h> X#include <ctype.h> X Xlong Xstrtol(s, p, b) Xchar *s, **p; Xint b; X{ X int base = 10, n = 0, sign = 1, valid = 1; X X /* X * leading sign? X */ X if (*s=='-') X sign=(-1); X else X sign=1; X if (*s=='+' || *s=='-') X ++s; /* skip sign */ X X /* X * what base are we really using? X */ X if (b == 0) { X if (strncmp(s, "0x", 2) == 0 || X strncmp(s, "0X", 2) == 0) { X s += 2; X base = 16; X } else X if (*s == '0') X base = 8; X } X X /* X * convert the string to a number. X */ X while (isascii(*s) && valid) { X switch(*s) { X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X n = base*n + *s-'0'; X break; X case '8': X case '9': X if (base >8) X n = base*n + *s-'0'; X else X valid = 0; X break; X case 'a': X case 'b': X case 'c': X case 'd': X case 'e': X case 'f': X if (base == 16) X n = base*n + *s-'a'+10; X else X valid = 0; X break; X case 'A': X case 'B': X case 'C': X case 'D': X case 'E': X case 'F': X if (base == 16) X n = base*n + *s-'A'+10; X else X valid = 0; X break; X default: X valid = 0; X break; X } X ++s; X } X X /* X * if arg `p' is not NULL, a ptr to the character X * terminating the scan will be returned in `p' X */ X if (*p != (char *)NULL) X *p = s; X X return sign * n; X} X X#ifdef TEST Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int i; X long j, strtol(); X X for (i=1; i<argc; i++) { X j = strtol(argv[i], 0, 0); X (void) printf("%s -> %ld(%lx)\n", argv[i], j, j); X } X exit(0); X} X#endif /* TEST */ END_OF_strtol.c if test 1737 -ne `wc -c <strtol.c`; then echo shar: \"strtol.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f sys._dir.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"sys._dir.h\" else echo shar: Extracting \"sys._dir.h\" \(2977 characters\) sed "s/^X//" >sys._dir.h <<'END_OF_sys._dir.h' X/* X <sys/_dir.h> -- definitions for 4.2,4.3BSD directories X X last edit: 25-Apr-1987 D A Gwyn X X A directory consists of some number of blocks of DIRBLKSIZ bytes each, X where DIRBLKSIZ is chosen such that it can be transferred to disk in a X single atomic operation (e.g., 512 bytes on most machines). X X Each DIRBLKSIZ-byte block contains some number of directory entry X structures, which are of variable length. Each directory entry has the X beginning of a (struct direct) at the front of it, containing its X filesystem-unique ident number, the length of the entry, and the length X of the name contained in the entry. These are followed by the NUL- X terminated name padded to a (long) boundary with 0 bytes. The maximum X length of a name in a directory is MAXNAMELEN. X X The macro DIRSIZ(dp) gives the amount of space required to represent a X directory entry. Free space in a directory is represented by entries X that have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes in a X directory block are claimed by the directory entries; this usually X results in the last entry in a directory having a large dp->d_reclen. X When entries are deleted from a directory, the space is returned to the X previous entry in the same directory block by increasing its X dp->d_reclen. If the first entry of a directory block is free, then X its dp->d_fileno is set to 0; entries other than the first in a X directory do not normally have dp->d_fileno set to 0. X X prerequisite: <sys/types.h> X*/ X X#if defined(accel) || defined(sun) || defined(vax) X#define DIRBLKSIZ 512 /* size of directory block */ X#else X#ifdef alliant X#define DIRBLKSIZ 4096 /* size of directory block */ X#else X#ifdef gould X#define DIRBLKSIZ 1024 /* size of directory block */ X#else X#ifdef ns32000 /* Dynix System V */ X#define DIRBLKSIZ 2600 /* size of directory block */ X#else /* be conservative; multiple blocks are okay but fractions are not */ X#define DIRBLKSIZ 4096 /* size of directory block */ X#endif X#endif X#endif X#endif X X#define MAXNAMELEN 255 /* maximum filename length */ X/* NOTE: not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */ X Xstruct direct /* data from read()/_getdirentries() */ X { X unsigned long d_fileno; /* unique ident of entry */ X unsigned short d_reclen; /* length of this record */ X unsigned short d_namlen; /* length of string in d_name */ X char d_name[MAXNAMELEN+1]; /* NUL-terminated filename */ X /* typically shorter */ X }; X X/* X The DIRSIZ macro gives the minimum record length which will hold the X directory entry. This requires the amount of space in a (struct X direct) without the d_name field, plus enough space for the name with a X terminating NUL character, rounded up to a (long) boundary. X X (Note that Berkeley didn't properly compensate for struct padding, X but we nevertheless have to use the same size as the actual system.) X*/ X X#define DIRSIZ( dp ) ((sizeof(struct direct) - (MAXNAMELEN+1) \ X + sizeof(long) + (dp)->d_namlen) \ X / sizeof(long) * sizeof(long)) END_OF_sys._dir.h if test 2977 -ne `wc -c <sys._dir.h`; then echo shar: \"sys._dir.h\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 2 \(of 5\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Lenny Tropiano ICUS Software Systems [w] +1 (516) 589-7930 lenny@icus.islp.ny.us Telex; 154232428 ICUS [h] +1 (516) 968-8576 {ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752
lenny@icus.islp.ny.us (Lenny Tropiano) (08/03/89)
#! /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 3 (of 5)." # Contents: DIRENT.INSTALL DIRENT.NOTES bsearch.3c directory.3c # getcwd.c mkdir.c tsearch.c # Wrapped by lenny@icus on Wed Aug 2 21:40:29 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f DIRENT.INSTALL -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"DIRENT.INSTALL\" else echo shar: Extracting \"DIRENT.INSTALL\" \(5490 characters\) sed "s/^X//" >DIRENT.INSTALL <<'END_OF_DIRENT.INSTALL' X X X INSTALLATION INSTRUCTIONS X X XThe following instructions are for systems resembling Ninth Edition UNIX, with Xhints about dealing with variations you may encounter for your specific system. XInstallation should be done only by someone who is comfortable with modifying Xthe standard C library and header files. X XIf your system already includes directory access routines, you should replace Xthem with this package. We're trying to get this standardized; see the Xdiscussion in the NOTES file. X XI have tried to make the source code as generic as possible, but if your system Xpredates Seventh Edition UNIX you will have problems. X XDISCLAIMER: Although I believe the code and procedures described here to be Xcorrect, I make no warranty of any kind, and you are advised to perform your Xown careful testing before making any substantial change like this to your Xprogramming environment. X X X0) For antique systems that do not support C's "void" data type, edit the file X sys.dirent.h to add the following: X X typedef int void; /* good enough for govt work */ X X If for some reason your <sys/types.h> doesn't define them, add the X following to sys.dirent.h: X X typedef unsigned short ino_t; /* (assuming original UFS) */ X typedef long off_t; /* long is forced by lseek() */ X X None of this should be necessary for any modern UNIX system. X X1) Copy the file dirent.h to /usr/include/dirent.h and copy the file X sys.dirent.h to /usr/include/sys/dirent.h. (The file sys._dir.h is also X provided for the BRL UNIX System V emulation for 4.nBSD. That environment X uses different directory names for everything.) X X2) Copy the file directory.3c to /usr/man/man3/directory.3 and copy the file X dirent.4 to /usr/man/man5/dirent.5; edit the new file X /usr/man/man3/directory.3 to change the "SEE ALSO" reference from dirent(4) X to dirent(5) and to change the 3C on the first line to 3; edit the new file X /usr/man/man5/dirent.5 to change the 4 on the first line to 5; then print X the manual pages via the command X X man directory dirent X X to see what the new routines are like. (If you have a "catman" style of X on-line manual, adapt these instructions accordingly. Manual entries are X kept in directories with other names on some systems such as UNIX System V. X On systems that already had a directory library documented in some other X manual entry, remove the superseded manual entry; if the description of the X native filesystem directory format found by "man dir" refers to a directory X library, modify it to simply refer to the entry for "dirent".) X X3) Copy the files closedir.c, opendir.c, readdir.c, rewinddir.c, seekdir.c, X and telldir.c to the "gen" or "port/gen" subdirectory of your C library X source directory. If you do not have a getdents() system call, copy the X file getdents.c to the "sys" or "port/sys" subdirectory and copy the file X getdents.2 to /usr/man/man2/getdents.2 (actually you may prefer to put this X file in section 3 and adjust the references in the other manual entries X accordingly; also adjust the references to dirent(4) to be to dirent(5) if X that's where the entry is). Edit the C library makefile(s) to include the X new object modules in the C library. (See the comments at the beginning of X getdents.c for symbols that must be defined to configure getdents.c.) Then X remake and reinstall the C library. Alternatively, you can just compile X the new sources and insert their objects near the front of the C library X /lib/libc.a using the "ar" utility (seekdir.o should precede readdir.o, X which in turn should precede getdents.o). On some systems you then need to X use the "ranlib" utility to update the archive symbol table. X X4) After the C library has been updated, delete /usr/include/ndir.h or any X other header used with a previous directory library to prevent inadvertent X use of the superseded directory access interface. Also delete any X corresponding library such as /usr/lib/libndir.a. X X5) To verify installation, try compiling, linking, and running the program X testdir.c. This program searches the current directory "." for each file X named as a program argument and prints `"FOO" found.' or `"FOO" not found.' X where FOO is of course replaced by the name being sought in the directory. X Try something like X X cd /usr/bin # a multi-block directory X WHEREVER/testdir FOO lint BAR f77 XYZZY X X which should produce the output X X "FOO" not found. X "lint" found. X "BAR" not found. X "f77" found. X "XYZZY" not found. X X A more thorough test would be X X cd /usr/bin # a multi-block directory X WHEREVER/testdir `ls -a` | grep 'not found' X X This program does not test the seekdir() and telldir() functions. X X6) Notify your programmers that all directory access must be made through the X new interface, and that documentation is available via X X man directory dirent X X Make the NOTES file available to those programmers who might want to X understand what this is all about. X X7) Change all system sources that were accessing directories to use the new X routines. Nearly all such sources contain the line X X #include <sys/dir.h> X or X #include <ndir.h> X X so they should be easy to find. (If you earlier removed some other header X file, that is, if this package superseded an earlier version of the X directory access library, look for its name too. See the conversion X instructions in the NOTES file.) END_OF_DIRENT.INSTALL if test 5490 -ne `wc -c <DIRENT.INSTALL`; then echo shar: \"DIRENT.INSTALL\" unpacked with wrong size! fi # end of overwriting check fi if test -f DIRENT.NOTES -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"DIRENT.NOTES\" else echo shar: Extracting \"DIRENT.NOTES\" \(5314 characters\) sed "s/^X//" >DIRENT.NOTES <<'END_OF_DIRENT.NOTES' X X XNOTES FOR NEARLY-POSIX-COMPATIBLE C LIBRARY DIRECTORY-ACCESS ROUTINES X X XOlder UNIX C libraries lacked support for reading directories, so historically Xprograms had knowledge of UNIX directory structure hard-coded into them. When XBerkeley changed the format of directories for 4.2BSD, it became necessary to Xchange programs to work with the new structure. Fortunately, Berkeley designed Xa small set of directory access routines to encapsulate knowledge of the new Xdirectory format so that user programs could deal with directory entries as an Xabstract data type. (Unfortunately, they didn't get it quite right.) The Xinterface to these routines was nearly independent of the particular Ximplementation of directories on any given UNIX system; this has become a Xparticularly important requirement with the advent of heterogeneous network Xfilesystems such as NFS. X XIt has consequently become possible to write portable applications that search Xdirectories by restricting all directory access to use these new interface Xroutines. The sources supplied here are a total rewrite of Berkeley's code, Xincorporating ideas from a variety of sources and conforming as closely to Xpublished standards as possible, and are in the PUBLIC DOMAIN to encourage Xtheir widespread adoption. They support four methods of access to system Xdirectories: the original UNIX filesystem via read(), the 4.2BSD filesystem via Xread(), NFS and native filesystems via getdirentries(), and SVR3 getdents(). XThe other three types are accomplished by appropriate emulation of the SVR3 Xgetdents() system call, which attains portability at the cost of slightly more Xdata movement than absolutely necessary for some systems. These routines Xshould be added to the standard C library on all UNIX systems, and all existing Xand future applications should be changed to use this interface. Once this is Xdone, there should be no portability problems due to differences in underlying Xdirectory structures among UNIX systems. (When porting your applications to Xother UNIX systems, you can always carry this package around with you.) X XAn additional benefit of these routines is that they buffer directory input, Xwhich provides improved access speed over raw read()s of one entry at a time. X XOne annoying compatibility problem has arisen along the way, namely that the Xoriginal Berkeley interface used the same name, struct direct, for the new data Xstructure as had been used for the original UNIX filesystem directory record Xstructure. This name was changed by the IEEE 1003.1 (POSIX) Working Group to X"struct dirent" and was picked up for SVR3 under the new name; it is also the Xname used in this portable package. I believe it is necessary to bite the Xbullet and adopt the new non-conflicting name. Code using a 4.2BSD-compatible Xpackage needs to be slightly revised to work with this new package, as follows: X Change X #include <ndir.h> /* Ninth Edition UNIX */ X or X #include <sys/dir.h> /* 4.2BSD */ X or X #include <dir.h> /* BRL System V emulation */ X to X #include <sys/types.h> /* if not already #included */ X #include <dirent.h> X X Change X struct direct X to X struct dirent X X Change X (anything)->d_namlen X to X strlen( (anything)->d_name ) X XThere is a minor compatibility problem in that the closedir() function was Xoriginally defined to have type void, but IEEE 1003.1 changed this to type int, Xwhich is what this implementation supports (even though I disagree with the Xchange). However, the difference does not affect most applications. X XAnother minor problem is that IEEE 1003.1 defined the d_name member of a struct Xdirent to be an array of maximum length; this does not permit use of compact Xvariable-length entries directly from a directory block buffer. This part of Xthe specification is incompatible with efficient use of the getdents() system Xcall, and I have therefore chosen to follow the SVID specification instead of XIEEE 1003.1 (which I hope is changed for the final-use standard). This Xdeviation should have little or no impact on sensibly-coded applications, since Xthe relevant d_name length is that given by strlen(), not the declared array Xsize. X XError handling is not completely satisfactory, due to the variety of possible Xfailure modes in a general setting. For example, the rewinddir() function Xmight fail, but there is no good way to indicate this. I have tried to Xfollow the specifications in IEEE 1003.1 and the SVID as closely as possible, Xbut there are minor deviations in this regard. Applications should not rely Xtoo heavily on exact failure mode semantics. X XPlease do not change the new standard interface in any way, as that would Xdefeat the major purpose of this package! (It's okay to alter the internal Ximplementation if you really have to, although I tried to make this unnecessary Xfor the vast majority of UNIX variants.) X XInstallation instructions can be found in the file named INSTALL. X XThis implementation is provided by: X X Douglas A. Gwyn X U.S. Army Ballistic Research Laboratory X SLCBR-VL-V X Aberdeen Proving Ground, MD 21005-5066 X X (301)278-6647 X X Gwyn@BRL.MIL or seismo!brl!gwyn X XThis is UNSUPPORTED, use-at-your-own-risk, free software in the public domain. XHowever, I would appreciate hearing of any actual bugs you find in this Ximplementation and/or any improvements you come up with. END_OF_DIRENT.NOTES if test 5314 -ne `wc -c <DIRENT.NOTES`; then echo shar: \"DIRENT.NOTES\" unpacked with wrong size! fi # end of overwriting check fi if test -f bsearch.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bsearch.3c\" else echo shar: Extracting \"bsearch.3c\" \(3005 characters\) sed "s/^X//" >bsearch.3c <<'END_OF_bsearch.3c' X.TH BSEARCH 3C "Standard Extension" X.SH NAME Xbsearch \- binary search a sorted table X.SH SYNOPSIS X.B #include <search.h> X.PP X.B "char \(**bsearch ((char \(**) key, (char \(**) base, nel, sizeof (\(**key), compar)" X.br X.B unsigned nel; X.br X.B int (\(**compar)( ); X.SH DESCRIPTION X.I Bsearch Xis a binary search routine generalized from Knuth (6.2.1) Algorithm B. XIt returns a pointer into a table indicating where a datum may be found. XThe table must be previously sorted in increasing order according to a Xprovided comparison function. X.I Key Xpoints to a datum instance to be sought in the table. X.I Base Xpoints to the element at the base of the table. X.I Nel Xis the number of elements in the table. X.I Compar Xis the name of the comparison function, which is called with two arguments Xthat point to the elements being compared. The function must return Xan integer less than, equal to, or greater than zero as accordinly the first Xargument is to be considered less than, equal to, or greater than the second. X.SH EXAMPLE XThe example below searches a table containing pointers to nodes consisting of Xa string and its length. The table is ordered alphabetically on the string in Xthe node pointed to by each entry. X.PP XThis code fragment reads in strings and either finds the corresponding node Xand prints out the string and its length, or prints an error message. X.PP X.RS X.nf X.ss 18 X#include <stdio.h> X#include <search.h> X X#define \s-1TABSIZE\s+1 1000 X Xstruct node { /\(** these are stored in the table \(**/ X char \(**string; X int length; X}; Xstruct node table[\s-1TABSIZE\s+1]; /\(** table to be searched \(**/ X . X . X . X{ X struct node \(**node_ptr, node; X int node_compare( ); /\(** routine to compare 2 nodes \(**/ X char str_space[20]; /\(** space to read string into \(**/ X . X . X . X node.string = str_space; X while (scanf("%s", node.string) != \s-1EOF\s+1) { X node_ptr = (struct node \(**)bsearch((char \(**)(&node), X (char \(**)table, \s-1TABSIZE\s+1, X sizeof(struct node), node_compare); X if (node_ptr != \s-1NULL\s+1) { X (void)printf("string = %20s, length = %d\en", X node_ptr\(mi>string, node_ptr\(mi>length); X } else { X (void)printf("not found: %s\en", node.string); X } X } X} X/\(** X This routine compares two nodes based on an X alphabetical ordering of the string field. X\(**/ Xint Xnode_compare(node1, node2) Xstruct node \(**node1, \(**node2; X{ X return strcmp(node1\(mi>string, node2\(mi>string); X} X.fe X.SH NOTES XThe pointers to the key and the element at the base of Xthe table should be of type pointer-to-element, Xand cast to type pointer-to-character. X.br XThe comparison function need not compare every byte, Xso arbitrary data may be contained in the elements in addition to the values Xbeing compared. X.br XAlthough declared as type pointer-to-character, Xthe value returned should be cast into type pointer-to-element. X.SH SEE ALSO Xhsearch(3C), lsearch(3C), qsort(3C), tsearch(3C). X.SH DIAGNOSTICS XA X\s-1NULL\s+1 Xpointer is returned if the key cannot be found in the table. END_OF_bsearch.3c if test 3005 -ne `wc -c <bsearch.3c`; then echo shar: \"bsearch.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f directory.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"directory.3c\" else echo shar: Extracting \"directory.3c\" \(4136 characters\) sed "s/^X//" >directory.3c <<'END_OF_directory.3c' X.TH DIRECTORY 3C "Standard Extension" X.SH NAME Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- directory operations X.SH SYNOPSIS X.B "#include <sys/types.h>" X.br X.B "#include <dirent.h>" X.P X.B "DIR \(**opendir (dirname)" X.br X.B "char \(**dirname;" X.P X.B "struct dirent \(**readdir (dirp)" X.br X.B "DIR \(**dirp;" X.P X.B "off_t telldir (dirp)" X.br X.B "DIR \(**dirp;" X.P X.B "void seekdir (dirp, loc)" X.br X.B "DIR \(**dirp;" X.br X.B "off_t loc;" X.P X.B "void rewinddir (dirp)" X.br X.B "DIR \(**dirp;" X.P X.B "int closedir (dirp)" X.br X.B "DIR \(**dirp;" X.SH DESCRIPTION X.I Opendir Xestablishes a connection between Xthe directory named by X.I dirname Xand a unique object of type X.SM DIR Xknown as a X.I "directory stream" Xthat it creates. X.I Opendir Xreturns a pointer to be used to identify the Xdirectory stream Xin subsequent operations. XA X.SM NULL Xpointer is returned if X.I dirname Xcannot be accessed or is not a directory, Xor if X.I opendir Xis unable to create the X.SM DIR Xobject X(perhaps due to insufficient memory). X.P X.I Readdir Xreturns a pointer to an internal structure Xcontaining information about the next active directory entry. XNo inactive entries are reported. XThe internal structure may be overwritten by Xanother operation on the same Xdirectory stream; Xthe amount of storage needed to hold a copy Xof the internal structure is given by the value of a macro, X.IR DIRENTSIZ(strlen(direntp\->d_name)) , Xnot by X.I "sizeof(struct\ dirent)" Xas one might expect. XA X.SM NULL Xpointer is returned Xupon reaching the end of the directory, Xupon detecting an invalid location in the directory, Xor upon occurrence of an error while reading the directory. X.P X.I Telldir Xreturns the current position associated with the named Xdirectory stream Xfor later use as an argument to X.IR seekdir . X.P X.I Seekdir Xsets the position of the next X.I readdir Xoperation on the named Xdirectory stream. XThe new position reverts to the one associated with the Xdirectory stream Xwhen the X.I telldir Xoperation from which X.I loc Xwas obtained was performed. X.P X.I Rewinddir Xresets the position of the named Xdirectory stream Xto the beginning of the directory. XAll buffered data for the directory stream is discarded, Xthereby guaranteeing that the actual Xfile system directory will be referred to for the next X.I readdir Xon the Xdirectory stream. X.P X.I Closedir Xcloses the named Xdirectory stream; Xinternal resources used for the Xdirectory stream are liberated, Xand subsequent use of the associated X.SM DIR Xobject is no longer valid. X.I Closedir Xreturns a value of zero if no error occurs, X\-1 otherwise. X.P XThere are several possible errors that can occur Xas a result of these operations; Xthe external integer variable X.I errno Xis set to indicate the specific error. X.RI ( Readdir 's Xdetection of the normal end of a directory Xis not considered to be an error.) X.SH EXAMPLE XSample code which searches the current working directory for entry X.IR name : X.P X.ft B X dirp = opendir( "." ); X.br X while ( (dp = readdir( dirp )) != NULL ) X.br X if ( strcmp( dp\->d_name, name ) == 0 ) X.br X { X.br X (void) closedir( dirp ); X.br X return FOUND; X.br X } X.br X (void) closedir( dirp ); X.br X return NOT_FOUND; X.ft P X.SH "SEE ALSO" Xgetdents(2), dirent(4). X.SH WARNINGS XEntries for "." and ".." Xmay not be reported for some file system types. X.P XThe value returned by X.I telldir Xneed not have any simple interpretation Xand should only be used as an argument to X.IR seekdir . XSimilarly, Xthe X.I loc Xargument to X.I seekdir Xmust be obtained from a previous X.I telldir Xoperation on the same Xdirectory stream. X.P X.I Telldir Xand X.I seekdir Xare unreliable when used in conjunction with Xfile systems that perform directory compaction or expansion Xor when the directory stream has been closed and reopened. XIt is best to avoid using X.I telldir Xand X.I seekdir Xaltogether. X.P XThe exact set of X.I errno Xvalues and meanings may vary among implementations. X.P XBecause directory entries can dynamically Xappear and disappear, Xand because directory contents are buffered Xby these routines, Xan application may need to continually rescan Xa directory to maintain an accurate picture Xof its active entries. END_OF_directory.3c if test 4136 -ne `wc -c <directory.3c`; then echo shar: \"directory.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f getcwd.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"getcwd.c\" else echo shar: Extracting \"getcwd.c\" \(5249 characters\) sed "s/^X//" >getcwd.c <<'END_OF_getcwd.c' X/* X getcwd -- get current working directory name (POSIX and SVID compatible) X X last edit: 21-Sep-1987 D A Gwyn X X This public-domain getcwd() routine can be used to replace the UNIX X System V library routine (which uses popen() to capture the output of X the "pwd" command). Once that is done, "pwd" can be reimplemented as X just puts(getcwd()). X X This implementation depends on every directory having entries for X "." and "..". It also depends on the internals of the <dirent.h> X data structures to some degree. X X I considered using chdir() to ascend the hierarchy, followed by a X final chdir() to the path being returned by getcwd() to restore the X location, but decided that error recovery was too difficult that way. X The algorithm I settled on was inspired by my rewrite of the "pwd" X utility, combined with the dotdots[] array trick from the SVR2 shell. X*/ X X#include <sys/types.h> X#include <sys/stat.h> X#include <dirent.h> X#include <errno.h> X#include <string.h> X Xtypedef char *pointer; /* (void *) if you have it */ X Xextern void free(); Xextern pointer malloc(); Xextern int fstat(), stat(); X Xextern int errno; /* normally done by <errno.h> */ X X#ifndef NULL X#define NULL 0 /* amorphous null pointer constant */ X#endif X X#ifndef NAME_MAX X#define NAME_MAX 255 /* maximum directory entry size */ X#endif X Xchar * Xgetcwd( buf, size ) /* returns pointer to CWD pathname */ X char *buf; /* where to put name (NULL to malloc) */ X int size; /* size of buf[] or malloc()ed memory */ X { X static char dotdots[] = X"../../../../../../../../../../../../../../../../../../../../../../../../../.."; X char *dotdot; /* -> dotdots[.], right to left */ X DIR *dirp; /* -> parent directory stream */ X struct dirent *dir; /* -> directory entry */ X struct stat stat1, stat2; /* info from stat() */ X struct stat *d = &stat1; /* -> info about "." */ X struct stat *dd = &stat2; /* -> info about ".." */ X register char *buffer; /* local copy of buf, or malloc()ed */ X char *bufend; /* -> buffer[size] */ X register char *endp; /* -> end of reversed string */ X register char *dname; /* entry name ("" for root) */ X int serrno = errno; /* save entry errno */ X X if ( size == 0 ) X { X errno = EINVAL; /* invalid argument */ X return NULL; X } X X if ( (buffer = buf) == NULL /* wants us to malloc() the string */ X && (buffer = (char *)malloc( (unsigned)size )) == NULL X ) { X errno = ENOMEM; /* cannot malloc() specified size */ X return NULL; X } X X if ( stat( ".", dd ) != 0 ) /* prime the pump */ X goto error; /* errno already set */ X X endp = buffer; /* initially, empty string */ X bufend = &buffer[size]; X X for ( dotdot = &dotdots[sizeof(dotdots)]; dotdot != dotdots; ) X { X dotdot -= 3; /* include one more "/.." section */ X /* (first time is actually "..") */ X X /* swap stat() info buffers */ X { X register struct stat *temp = d; X X d = dd; /* new current dir is old parent dir */ X dd = temp; X } X X if ( (dirp = opendir( dotdot )) == NULL ) /* new parent */ X goto error; /* errno already set */ X X if ( fstat( dirp->dd_fd, dd ) != 0 ) X { X serrno = errno; /* set by fstat() */ X (void)closedir( dirp ); X errno = serrno; /* in case closedir() clobbered it */ X goto error; X } X X if ( d->st_dev == dd->st_dev ) X { /* not crossing a mount point */ X if ( d->st_ino == dd->st_ino ) X { /* root directory */ X dname = ""; X goto append; X } X X do X if ( (dir = readdir( dirp )) == NULL ) X { X (void)closedir( dirp ); X errno = ENOENT; /* missing entry */ X goto error; X } X while ( dir->d_ino != d->st_ino ); X } X else { /* crossing a mount point */ X struct stat t; /* info re. test entry */ X char name[sizeof(dotdots) + 1 + NAME_MAX]; X X (void)strcpy( name, dotdot ); X dname = &name[strlen( name )]; X *dname++ = '/'; X X do { X if ( (dir = readdir( dirp )) == NULL ) X { X (void)closedir( dirp ); X errno = ENOENT; /* missing entry */ X goto error; X } X X (void)strcpy( dname, dir->d_name ); X /* must fit if NAME_MAX is not a lie */ X } X while ( stat( name, &t ) != 0 X || t.st_ino != d->st_ino X || t.st_dev != d->st_dev X ); X } X X dname = dir->d_name; X X /* append "/" and reversed dname string onto buffer */ X append: X if ( endp != buffer /* avoid trailing / in final name */ X || dname[0] == '\0' /* but allow "/" when CWD is root */ X ) X *endp++ = '/'; X X { X register char *app; /* traverses dname string */ X X for ( app = dname; *app != '\0'; ++app ) X ; X X if ( app - dname >= bufend - endp ) X { X (void)closedir( dirp ); X errno = ERANGE; /* won't fit allotted space */ X goto error; X } X X while ( app != dname ) X *endp++ = *--app; X } X X (void)closedir( dirp ); X X if ( dname[0] == '\0' ) /* reached root; wrap it up */ X { X register char *startp; /* -> buffer[.] */ X X *endp = '\0'; /* plant null terminator */ X X /* straighten out reversed pathname string */ X for ( startp = buffer; --endp > startp; ++startp ) X { X char temp = *endp; X X *endp = *startp; X *startp = temp; X } X X errno = serrno; /* restore entry errno */ X return buffer; X } X } X X errno = ENOMEM; /* actually, algorithm failure */ X X error: X if ( buf == NULL ) X free( (pointer)buffer ); X X return NULL; X } X X END_OF_getcwd.c if test 5249 -ne `wc -c <getcwd.c`; then echo shar: \"getcwd.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f mkdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"mkdir.c\" else echo shar: Extracting \"mkdir.c\" \(4832 characters\) sed "s/^X//" >mkdir.c <<'END_OF_mkdir.c' X/**************************************************************************** X XNAME X mkdir.c -- emulation of BSD/SVr3-style mkdir(2) system call X XSYNOPSIS X int mkdir(path, perm) -- make a directory with given permissions X char *path; int perm; X XDESCRIPTION X The mkdir() function is used for making directories on systems that Xdon't have a mkdir(2) call (that is, V7 and USG systems before V.3). It tries Xto act as much like mkdir(2) as possible. Due to various bogosities (why, oh Xwhy wasn't mknod(2) for a directory made a non-privileged call?) it cannot Xcompletely succeed. It returns 0 on success and -1 on failure but Xonly detect the following ERRNO conditions; ENOENT, EEXIST, EACCESS, ENOTDIR. X X Note: this function emulates the SVr3 behavior (group ID of the directory Xis the effective group ID of the calling process) rather than the BSD Xbehavior (group ID of the directory is the group ID of the parent directory). X X On USG it will succeed if the real or apparent uid of the calling process Xhas write privileges in the current directory (the latter case is implemented Xby a kluge that tries to set the parent directory's permissions to 0777, 'ware Xsecurity holes!). The new directory will be owned by the effective uid. X X On V7 (because it restricts the chown(2) call and mkdir(1) makes Xdirectories owned by the real ID of its caller) the call will only succeed Xif the real ID matches, and the new directory will be owned by the real Xuid. X XREVISED BY X Eric S. Raymond X X****************************************************************************/ X/* LINTLIBRARY */ X#include <sys/types.h> X#include <sys/stat.h> X#include <errno.h> X#include <signal.h> X Xextern int errno; X Xstatic int fwait(pid) X/* wait on a child process, shielding it from SIGINT and SIGHUP */ Xregister int pid; X{ X register int w; X int status; X X while ((w = wait(&status)) != pid && w != -1) X continue; X if (w == -1) X status = -1; X X return(status); X} X Xint mkdir(path, perm) Xchar *path; Xint perm; X{ X int status, pid; X int uid = getuid(), gid = getgid(); X#ifndef lint X int euid = geteuid(); X int egid = getegid(); X#endif /* lint */ X struct stat pstat, sbuf; X register char *p; X char parent[200]; X extern char *strrchr(); X X#ifdef MAIN X (void) fprintf(stderr, "Attempting to mkdir %s\n", path); X#endif /* MAIN */ X X errno = 0; X X /* X * check that the directory doesn't already exist, so that the X * do loop below must run at least once X */ X if (stat(path, &sbuf) == 0) X { X errno = EEXIST; X#ifdef MAIN X (void) fprintf(stderr, "Directory %s exists\n", path); X#endif /* MAIN */ X return(-1); X } X X /* construct the parent's name */ X if (p = strrchr(path, '/')) X { X *p = '\0'; X (void) strcpy(parent, path); X *p = '/'; X } X else X (void) strcpy(parent, "."); X X if (stat(parent, &pstat) == -1) /* check that the parent exists */ X { X errno = ENOENT; X return(-1); X } X else if (!(pstat.st_mode & S_IFDIR)) /* and that it's a directory */ X { X errno = ENOTDIR; X return(-1); X } X X#ifdef USG X /* X * If the parent directory is 755 (rwxr-xr-x) the mkdir(1) below X * will probably fail because it will get suid'd to our real uid, which X * is random (and thus probably won't match the parent owner's). X * So we have to temporarily chmod the parent to 777 (rwxrwxrwx). X */ X if (sbuf.st_uid != uid) X { X if (chmod(parent, 0777) == -1) X { X errno = EACCES; X return(-1); X } X } X#endif /* USG */ X X /* now we can make the new directory */ X if (pid = fork()) /* parent side */ X { X if (pid == -1) X return(-1); X X status = fwait(pid); /* wait till mkdir child is done */ X X#ifdef USG X /* X * Spawn another child to set ownership correctly -- we do this so X * that it gets set to effective ID even if we're running su. This X * only works where chown(2) can be called to give files away by a X * non-superuser. X */ X if (pid = fork()) X (void) fwait(pid); X else { X#ifndef lint X int oldumask = umask(0777); X#endif /* lint */ X X (void) stat(".", &pstat); X (void) setuid(uid); X (void) setgid(gid); X#ifndef lint /* USG lints disagree about 2nd argument types */ X (void) chmod(path, (unsigned)(perm & ~oldumask)); X (void) chown(path, euid, egid); X (void) umask(oldumask); X#endif /* lint */ X _exit(0); X } X#endif /* USG */ X } else { /* child side */ X (void) close(1); /* stdout */ X (void) close(2); /* stderr */ X (void) execlp("mkdir", "mkdir", path, (char *)0); X perror(path); X _exit(1); X } X X#ifndef lint /* USG lints disagree about the type of arg 2 */ X#ifdef USG X if (sbuf.st_uid != uid) X (void) chmod(parent, (unsigned) pstat.st_mode); /* put it back */ X#endif /* USG */ X#endif /* lint */ X X return(status); X} X X/* mkdir.c ends here */ END_OF_mkdir.c if test 4832 -ne `wc -c <mkdir.c`; then echo shar: \"mkdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f tsearch.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"tsearch.c\" else echo shar: Extracting \"tsearch.c\" \(3509 characters\) sed "s/^X//" >tsearch.c <<'END_OF_tsearch.c' X/* X * Tree search generalized from Knuth (6.2.2) Algorithm T just like X * the AT&T man page says. X * X * The node_t structure is for internal use only, lint doesn't grok it. X * X * Written by reading the System V Interface Definition, not the code. X * X * Totally public domain. X */ X/*LINTLIBRARY*/ X X#include <search.h> X Xtypedef struct node_t X{ X char *key; X struct node_t *left, *right; X} Xnode; X Xnode *tsearch(key, rootp, compar) X/* find or insert datum into search tree */ Xchar *key; /* key to be located */ Xregister node **rootp; /* address of tree root */ Xint (*compar)(); /* ordering function */ X{ X register node *q; X X if (rootp == (struct node_t **)0) X return ((struct node_t *)0); X while (*rootp != (struct node_t *)0) /* Knuth's T1: */ X { X int r; X X if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ X return (*rootp); /* we found it! */ X rootp = (r < 0) ? X &(*rootp)->left : /* T3: follow left branch */ X &(*rootp)->right; /* T4: follow right branch */ X } X q = (node *) malloc(sizeof(node)); /* T5: key not found */ X if (q != (struct node_t *)0) /* make new node */ X { X *rootp = q; /* link new node to old */ X q->key = key; /* initialize new node */ X q->left = q->right = (struct node_t *)0; X } X return (q); X} X Xnode *tdelete(key, rootp, compar) X/* delete node with given key */ Xchar *key; /* key to be deleted */ Xregister node **rootp; /* address of the root of tree */ Xint (*compar)(); /* comparison function */ X{ X node *p; X register node *q; X register node *r; X int cmp; X X if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0) X return ((struct node_t *)0); X while ((cmp = (*compar)(key, (*rootp)->key)) != 0) X { X p = *rootp; X rootp = (cmp < 0) ? X &(*rootp)->left : /* follow left branch */ X &(*rootp)->right; /* follow right branch */ X if (*rootp == (struct node_t *)0) X return ((struct node_t *)0); /* key not found */ X } X r = (*rootp)->right; /* D1: */ X if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */ X q = r; X else if (r != (struct node_t *)0) /* Right link is null? */ X { X if (r->left == (struct node_t *)0) /* D2: Find successor */ X { X r->left = q; X q = r; X } X else X { /* D3: Find (struct node_t *)0 link */ X for (q = r->left; q->left != (struct node_t *)0; q = r->left) X r = q; X r->left = q->right; X q->left = (*rootp)->left; X q->right = (*rootp)->right; X } X } X free((struct node_t *) *rootp); /* D4: Free node */ X *rootp = q; /* link parent to new node */ X return(p); X} X Xstatic void trecurse(root, action, level) X/* Walk the nodes of a tree */ Xregister node *root; /* Root of the tree to be walked */ Xregister void (*action)(); /* Function to be called at each node */ Xregister int level; X{ X if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0) X (*action)(root, leaf, level); X else X { X (*action)(root, preorder, level); X if (root->left != (struct node_t *)0) X trecurse(root->left, action, level + 1); X (*action)(root, postorder, level); X if (root->right != (struct node_t *)0) X trecurse(root->right, action, level + 1); X (*action)(root, endorder, level); X } X} X Xvoid twalk(root, action) /* Walk the nodes of a tree */ Xnode *root; /* Root of the tree to be walked */ Xvoid (*action)(); /* Function to be called at each node */ X{ X if (root != (node *)0 && action != (void(*)())0) X trecurse(root, action, 0); X} X X/* tsearch.c ends here */ END_OF_tsearch.c if test 3509 -ne `wc -c <tsearch.c`; then echo shar: \"tsearch.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 3 \(of 5\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Lenny Tropiano ICUS Software Systems [w] +1 (516) 589-7930 lenny@icus.islp.ny.us Telex; 154232428 ICUS [h] +1 (516) 968-8576 {ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752
lenny@icus.islp.ny.us (Lenny Tropiano) (08/03/89)
#! /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 4 (of 5)." # Contents: getdents.c string.3 tsearch.3c # Wrapped by lenny@icus on Wed Aug 2 21:40:33 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f getdents.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"getdents.c\" else echo shar: Extracting \"getdents.c\" \(8062 characters\) sed "s/^X//" >getdents.c <<'END_OF_getdents.c' X/* X getdents -- get directory entries in a file system independent format X (SVR3 system call emulation) X X last edit: 15-Feb-1988 D A Gwyn X X This single source file supports several different methods of X getting directory entries from the operating system. Define X whichever one of the following describes your system: X X UFS original UNIX filesystem (14-character name limit) X BFS 4.2BSD (also 4.3BSD) native filesystem (long names) X NFS getdirentries() system call X X Also define any of the following that are pertinent: X X ATT_SPEC check user buffer address for longword alignment X BSD_SYSV BRL UNIX System V emulation environment on 4.nBSD X UNK have _getdents() system call, but kernel may not X support it X UW_NFS You are running an NFS filesystem with an X underlying 4.2 BSD filesystem. This is true X in particular if you running the NFS port from X the University of Wisconsin. X X If your C library has a getdents() system call interface, but you X can't count on all kernels on which your application binaries may X run to support it, change the system call interface name to X _getdents() and define "UNK" to enable the system-call validity X test in this "wrapper" around _getdents(). X X If your system has a getdents() system call that is guaranteed X to always work, you shouldn't be using this source file at all. X*/ X X#define UFS X#define ATT_SPEC X X#include <sys/errno.h> X#include <sys/types.h> X#ifdef BSD_SYSV X#include <sys/_dir.h> /* BSD flavor, not System V */ X#else X#include <sys/dir.h> X#undef MAXNAMLEN /* avoid conflict with SVR3 */ X /* Good thing we don't need to use the DIRSIZ() macro! */ X#ifdef d_ino /* 4.3BSD/NFS using d_fileno */ X#undef d_ino /* (not absolutely necessary) */ X#else X#define d_fileno d_ino /* (struct direct) member */ X#endif X#endif X#include <sys/dirent.h> X#include <sys/stat.h> X#ifdef UNK X#ifndef UFS X#include "***** ERROR ***** UNK applies only to UFS" X/* One could do something similar for getdirentries(), but I didn't bother. */ X#endif X#include <signal.h> X#endif X X#if defined(UFS) + defined(BFS) + defined(NFS) != 1 /* sanity check */ X#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined" X#endif X X#ifdef BSD_SYSV Xstruct dirent __dirent; /* (just for the DIRENTBASESIZ macro) */ X#endif X X#ifdef UFS X#define RecLen( dp ) (sizeof(struct direct)) /* fixed-length entries */ X#else /* BFS || NFS */ X#define RecLen( dp ) ((dp)->d_reclen) /* variable-length entries */ X#endif X X#ifdef NFS X#ifdef BSD_SYSV X#define getdirentries _getdirentries /* package hides this system call */ X#endif Xextern int getdirentries(); Xstatic long dummy; /* getdirentries() needs basep */ X#define GetBlock( fd, buf, n ) getdirentries( fd, buf, (unsigned)n, &dummy ) X#else /* UFS || BFS */ X#ifdef BSD_SYSV X#define read _read /* avoid emulation overhead */ X#endif Xextern int read(); X#define GetBlock( fd, buf, n ) read( fd, buf, (unsigned)n ) X#endif X X#ifdef UNK Xextern int _getdents(); /* actual system call */ X#endif X Xextern char *strncpy(); Xextern int fstat(); Xextern off_t lseek(); X Xextern int errno; X X#ifndef DIRBLKSIZ X#define DIRBLKSIZ 4096 /* directory file read buffer size */ X#endif X X#ifndef NULL X#define NULL 0 X#endif X X#ifndef SEEK_CUR X#define SEEK_CUR 1 X#endif X X#ifndef S_ISDIR /* macro to test for directory file */ X#define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR) X#endif X X#ifdef UFS X X/* X The following routine is necessary to handle DIRSIZ-long entry names. X Thanks to Richard Todd for pointing this out. X*/ X Xstatic int XNameLen( name ) /* return # chars in embedded name */ X char name[]; /* -> name embedded in struct direct */ X { X register char *s; /* -> name[.] */ X register char *stop = &name[DIRSIZ]; /* -> past end of name field */ X X for ( s = &name[1]; /* (empty names are impossible) */ X *s != '\0' /* not NUL terminator */ X && ++s < stop; /* < DIRSIZ characters scanned */ X ) X ; X X return s - name; /* # valid characters in name */ X } X X#else /* BFS || NFS */ X Xextern int strlen(); X X#define NameLen( name ) strlen( name ) /* names are always NUL-terminated */ X X#endif X X#ifdef UNK Xstatic enum { maybe, no, yes } state = maybe; X /* does _getdents() work? */ X X/*ARGSUSED*/ Xstatic void Xsig_catch( sig ) X int sig; /* must be SIGSYS */ X { X state = no; /* attempted _getdents() faulted */ X } X#endif X Xint Xgetdents( fildes, buf, nbyte ) /* returns # bytes read; X 0 on EOF, -1 on error */ X int fildes; /* directory file descriptor */ X char *buf; /* where to put the (struct dirent)s */ X unsigned nbyte; /* size of buf[] */ X { X int serrno; /* entry errno */ X off_t offset; /* initial directory file offset */ X struct stat statb; /* fstat() info */ X union { X char dblk[DIRBLKSIZ X#ifdef UFS X +1 /* for last entry name terminator */ X#endif X ]; X /* directory file block buffer */ X struct direct dummy; /* just for alignment */ X } u; /* (avoids having to malloc()) */ X register struct direct *dp; /* -> u.dblk[.] */ X register struct dirent *bp; /* -> buf[.] */ X X#ifdef UNK X switch ( state ) X { X void (*shdlr)(); /* entry SIGSYS handler */ X register int retval; /* return from _getdents() if any */ X X case yes: /* _getdents() is known to work */ X return _getdents( fildes, buf, nbyte ); X X case maybe: /* first time only */ X shdlr = signal( SIGSYS, sig_catch ); X retval = _getdents( fildes, buf, nbyte ); /* try it */ X (void)signal( SIGSYS, shdlr ); X X if ( state == maybe ) /* SIGSYS did not occur */ X { X state = yes; /* so _getdents() must have worked */ X return retval; X } X /* else fall through into emulation */ X X/* case no: /* fall through into emulation */ X } X#endif X X if ( buf == NULL X#ifdef ATT_SPEC X || (unsigned long)buf % sizeof(long) != 0 /* ugh */ X#endif X ) { X errno = EFAULT; /* invalid pointer */ X return -1; X } X X if ( fstat( fildes, &statb ) != 0 ) X return -1; /* errno set by fstat() */ X X if ( !S_ISDIR( statb.st_mode ) ) X { X errno = ENOTDIR; /* not a directory */ X return -1; X } X X if ( (offset = lseek( fildes, (off_t)0, SEEK_CUR )) < 0 ) X return -1; /* errno set by lseek() */ X X#ifdef BFS /* no telling what remote hosts do */ X if ( (unsigned long)offset % DIRBLKSIZ != 0 ) X { X errno = ENOENT; /* file pointer probably misaligned */ X return -1; X } X#endif X X serrno = errno; /* save entry errno */ X X for ( bp = (struct dirent *)buf; bp == (struct dirent *)buf; ) X { /* convert next directory block */ X int size; X X do size = GetBlock( fildes, u.dblk, DIRBLKSIZ ); X while ( size == -1 && errno == EINTR ); X X if ( size <= 0 ) X return size; /* EOF or error (EBADF) */ X X for ( dp = (struct direct *)u.dblk; X (char *)dp < &u.dblk[size]; X dp = (struct direct *)((char *)dp + RecLen( dp )) X ) { X#ifndef UFS X if ( dp->d_reclen <= 0 ) X { X errno = EIO; /* corrupted directory */ X return -1; X } X#endif X X if ( dp->d_fileno != 0 ) X { /* non-empty; copy to user buffer */ X register int reclen = X DIRENTSIZ( NameLen( dp->d_name ) ); X X if ( (char *)bp + reclen > &buf[nbyte] ) X { X errno = EINVAL; X return -1; /* buf too small */ X } X X bp->d_ino = dp->d_fileno; X bp->d_off = offset + ((char *)dp - u.dblk); X bp->d_reclen = reclen; X X { X#ifdef UFS X /* Is the following kludge ugly? You bet. */ X X register char save = dp->d_name[DIRSIZ]; X /* save original data */ X X dp->d_name[DIRSIZ] = '\0'; X /* ensure NUL termination */ X#endif X (void)strncpy( bp->d_name, dp->d_name, X reclen - DIRENTBASESIZ X ); /* adds NUL padding */ X#ifdef UFS X dp->d_name[DIRSIZ] = save; X /* restore original data */ X#endif X } X X bp = (struct dirent *)((char *)bp + reclen); X } X } X X#ifndef UW_NFS X#if !(defined(BFS) || defined(sun)) /* 4.2BSD screwed up; fixed in 4.3BSD */ X if ( (char *)dp > &u.dblk[size] ) X { X errno = EIO; /* corrupted directory */ X return -1; X } X#endif X#endif X } X X errno = serrno; /* restore entry errno */ X return (char *)bp - buf; /* return # bytes read */ X } END_OF_getdents.c if test 8062 -ne `wc -c <getdents.c`; then echo shar: \"getdents.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f string.3 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"string.3\" else echo shar: Extracting \"string.3\" \(6925 characters\) sed "s/^X//" >string.3 <<'END_OF_string.3' X.TH STRING 3 "ANSI/POSIX Standard" X.SH NAME Xstrcat, strdup, strncat, strcmp, strncmp, strcpy, Xstrncpy, strlen, strchr, strrchr, strpbrk, strspn, strcspn, Xstrtok \- string operations X.SH SYNOPSIS X.B #include <string.h> X.br X.B #include <sys/types.h> X.P X.B "char \(**strcat(s1, s2)" X.br X.B "char \(**s1, \(**s2;" X.P X.B "char \(**strdup(s1)" X.br X.B "char \(**s1;" X.P X.B "char \(**strncat(s1, s2, n)" X.br X.B "char \(**s1, \(**s2;" X.br X.B "size_t n;" X.P X.B "int strcmp(s1, s2)" X.br X.B "char \(**s1, \(**s2;" X.P X.B "strncmp(s1, s2, n)" X.br X.B "char \(**s1, \(**s2;" X.br X.B "size_t n;" X.P X.B "char \(**strcpy(s1, s2)" X.br X.B "char \(**s1, \(**s2;" X.P X.B "char \(**strncpy(s1, s2, n)" X.br X.B "char \(**s1, \(**s2;" X.br X.B "size_t n;" X.P X.B "int strlen(s)" X.br X.B "char \(**s;" X.P X.B "char \(**strchr(s, c)" X.br X.B "char \(**s;" X.br X.B "int c;" X.P X.B "char \(**strrchr(s, c)" X.br X.B "char \(**s;" X.br X.B "int c;" X.P X.B "char \(**strpbrk(s1, s2)" X.br X.B "char \(**s1, s2;" X.P X.B "int strspn(s1, s2)" X.br X.B "char \(**s1, \(**s2;" X.P X.B "int strcspn(s1, s2)" X.br X.B "char \(**s1, \(**s2;" X.P X.B "char \(**strtok(s1, s2)" X.br X.B "char \(**s1, s2;" X.br X.SH DESCRIPTION XThe arguments \fBs1\fR, \fBs2\fR, and s point to strings (arrays of Xcharacters terminated by a null character). The functions Xstrcat, strncat, strcpy, and strncpy all alter \fBs1\fR. These Xfunctions do not check for overflow of the array pointed to Xby \fBs1\fR. X.P X\fBStrcat\fR appends a copy of string \fBs2\fR to the end of string \fBs1\fR. X.P X\fBStrdup\fR returns a pointer to a new string that is a duplicate Xof the string pointed to by \fBs1\fR. The space for the new Xstring is obtained using malloc(3C). If the new string Xcannot be created, a null pointer is returned. X.P X\fBStrncat\fR appends at most n characters. Each returns a Xpointer to the null-terminated result. X.P X\fBStrcmp\fR compares its arguments and returns an integer less Xthan, equal to, or greater than 0, according as \fBs1\fR is Xlexicographically less than, equal to, or greater than \fBs2\fR. X\fBStrncmp\fR makes the same comparison but looks at, at most, n Xcharacters. X.P X\fBStrcpy\fR copies string \fBs2\fR to \fBs1\fR, stopping after the null Xcharacter has been copied. \fBStrncpy\fR copies exactly n Xcharacters, truncating \fBs2\fR or adding null characters to \fBs1\fR if Xnecessary. The result will not be null-terminated if the Xlength of \fBs2\fR is n or more. Each function returns \fBs1\fR. X.P X\fBStrlen\fR returns the number of characters in s, not including Xthe terminating null character. X.P X\fBStrchr\fR (\fBstrrchr\fR) returns a pointer to the first (last) Xoccurrence of character c in string s, or a NULL pointer if Xc does not occur in the string. The null character Xterminating a string is considered to be part of the string. X.P X\fBStrpbrk\fR returns a pointer to the first occurrence in string X\fBS1\fR of any character from string \fBs2\fR, or a NULL pointer if no Xcharacter from \fBs2\fR exists in \fBs1\fR. X.P X\fBStrspn\fR (\fBstrcspn\fR) returns the length of the initial segment Xof string \fBs1\fR, which consists entirely of characters from X(not from) string \fBs2\fR. X.P X\fBStrtok\fR considers the string \fBs1\fR to consist of a sequence of Xzero or more text tokens separated by spans of one or more Xcharacters from the separator string \fBs2\fR. The first call X(with pointer \fBs1\fR specified) returns a pointer to the first Xcharacter of the first token, and will have written a null Xcharacter into \fBs1\fR immediately following the returned token. XThe function keeps track of its position in the string Xbetween separate calls, so that subsequent calls (which must Xbe made with the first argument a NULL pointer) will work Xthrough the string \fBs1\fR immediately following that token. In Xthis way, subsequent calls will work through the string \fBs1\fR Xuntil no tokens remain. The separator string \fBs2\fR may be Xdifferent from call to call. When no token remains in \fBs1\fR, a XNULL pointer is returned. X.P XFor user convenience, all these functions are declared in Xthe optional <string.h> header file. X.SH SEE ALSO Xmalloc(3C), malloc(3X). X.SH CAVEATS X\fBStrcmp\fR and \fBstrncmp\fR are implemented by using the most natural Xcharacter comparison on the machine. Thus, the sign of the Xvalue returned when one of the characters has its high-order Xbit set is not the same in all implementations and should Xnot be relied upon. X.P XCharacter movement is performed differently in different Ximplementations. Thus, overlapping moves may yield Xsurprises.!STUFFY!FUNK! Xchmod 644 src/D.posix/string.3 Xecho Extracting src/D.posix/getopt.3c Xsed >src/D.posix/getopt.3c <<'!STUFFY!FUNK!' -e 's///' X.TH GETOPT 3C "Standard Extensions" X.SH NAME Xgetopt \- parse arguments from an argument token vector X.SH SYNOPSIS X.B int getopt (argc, argv, optstring) X.br X.B int argc; X.br X.B char \(**\(**argv, \(**opstring; X.PP X.B extern char \(**optarg; X.br X.B extern int optind, opterr; X.SH DESCRIPTION X.I Getopt Xreturns the next option letter in X.I argv Xthat matches Xa letter in X.IR optstring . X.I Optstring Xis a string of recognized option letters. If a letter is followed by a colon, Xthe option is expected to have an argument that may or may not be separated Xfrom it by white space. X.I Optarg Xis set to point to the start of the option argument on return from X.IR getopt . X.PP X.I Getopt Xplaces in X.I optind Xthe X.I argv Xindex of the next argument to be processed. Because X.I optind Xis external, it is normally initialized to zero automatically before the first Xcall to X.IR getopt . X.PP XWhen all options have been processed (i.e., up to the first non-option Xargument), X.I getopt Xreturns X.SM X.BR EOF . XThe special option X.B \-\- Xmay be used to delimit the end of the options; X.SM X.B EOF Xwill be returned, and X.B \-\- Xwill be skipped. X.SH DIAGNOSTICS X.I Getopt Xprints an error message on X.I stderr Xand returns a Xquestion mark X.RB ( ? ) Xwhen it encounters an option letter not included in X.IR optstring . XThis error message may be disabled by setting X.I opterr Xto a non-zero value. X.SH EXAMPLE XThe following code fragment shows how one might process the arguments for a Xcommand that can take the mutually exclusive options X.B a Xand X.BR b , Xand the options X.B f Xand X.BR o , Xboth of which require arguments: X.PP X.RS X.nf X.ss 18 Xmain (argc, argv) Xint argc; Xchar \(**\(**argv; X{ X int c; X extern char \(**optarg; X extern int optind; X \&\f3.\fP X \&\f3.\fP X \&\f3.\fP X while ((c = getopt(argc, argv, "abf:o:")) != \s-1EOF\s+1) X switch (c) { X case \(fma\(fm: X if (bflg) X errflg++; X else X aflg++; X break; X case \(fmb\(fm: X if (aflg) X errflg++; X else X bproc( ); X break; X case \(fmf\(fm: X ifile = optarg; X break; X case \(fmo\(fm: X ofile = optarg; X break; X case \(fm?\(fm: X errflg++; X } X if (errflg) { X fprintf(stderr, "usage: . . . "); X exit (2); X } X for ( ; optind < argc; optind++) { X if (access(argv[optind], 4)) { X \&\f3.\fP X \&\f3.\fP X \&\f3.\fP X} X.ss 12 X.fi END_OF_string.3 if test 6925 -ne `wc -c <string.3`; then echo shar: \"string.3\" unpacked with wrong size! fi # end of overwriting check fi if test -f tsearch.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"tsearch.3c\" else echo shar: Extracting \"tsearch.3c\" \(6251 characters\) sed "s/^X//" >tsearch.3c <<'END_OF_tsearch.3c' X.TH TSEARCH 3C "Standard Extension" X.SH NAME Xtsearch, tfind, tdelete, twalk \- manipulate binary search trees X.SH SYNOPSIS X.B #include <search.h> X.PP X.B "char \(**tsearch ((char \(**) key, (char \(**\(**) rootp, compar)" X.br X.B int (\(**compar)( ); X.PP X.B "char \(**tfind ((char \(**) key, (char \(**\(**) rootp, compar)" X.br X.B int (\(**compar)( ); X.PP X.B "char \(**tdelete ((char \(**) key, (char \(**\(**) rootp, compar)" X.br X.B int (\(**compar)( ); X.PP X.B "void twalk ((char \(**) root, action)" X.br X.B void (\(**action)( ); X.SH DESCRIPTION X.I Tsearch, X.I tfind, X.I tdelete, Xand X.I twalk Xare routines for manipulating binary search trees. XThey are generalized from Knuth (6.2.2) Algorithms T and D. XAll comparisons are done with a user-supplied hook. XThis routine is called with two arguments, Xthe pointers to the elements being compared. XIt returns an integer less than, equal to, Xor greater than 0, according to whether the first argument Xis to be considered less than, equal to or greater than the Xsecond argument (this is the convention used by X.IR strncmp (3)). XThe comparison function need not compare every byte, Xso arbitrary data may be contained in the elements Xin addition to the key values being compared. X.PP X.I Tsearch Xis used to build and access the tree. X.B Key Xis a pointer to a datum to be accessed or stored. XIf there is a datum in the tree Xequal to \(**key (the value pointed to by key), Xa pointer to this found datum is returned. XOtherwise, \(**key is inserted, and a pointer to it returned. XOnly pointers are copied, so the calling routine must store the data. X.B Rootp Xmust point to a variable that points to the root Xof the tree. XA X.SM NULL Xvalue for the variable pointed to by X.B rootp Xdenotes an empty tree; in this case, Xthe variable will be set to point to the datum Xwhich will be at the root of the new tree. X.PP XLike X.IR tsearch , X.I tfind Xwill search for a datum in the tree, returning a pointer Xto it if found. XHowever, if it is not found, X.I tfind Xwill return a X.SM NULL Xpointer. XThe arguments for X.I tfind Xare the same as for X.IR tsearch . X.PP X.I Tdelete Xdeletes a node from a binary search tree. XThe arguments are the same as for X.IR tsearch . XThe variable pointed to by X.B rootp Xwill be changed if the deleted node was the root of the tree. X.I Tdelete Xreturns a pointer to the parent of the deleted node, Xor a X.SM NULL Xpointer if the node is not found. X.PP X.I Twalk Xtraverses a binary search tree. X.B Root Xis the root of the tree to be traversed. X(Any node in a tree may be used as the root for a walk below that node.) X.I Action Xis the name of a routine Xto be invoked at each node. XThis routine is, in turn, Xcalled with three arguments. XThe first argument is the address of the node being visited. XThe second argument is a value from an enumeration data type X.I "typedef enum { preorder, postorder, endorder, leaf }" X.SM X.I VISIT; X(defined in the X.RI < search.h > Xheader file), Xdepending on whether this is the first, second or third Xtime that the node has been visited X(during a depth-first, left-to-right traversal of the tree), Xor whether the node is a leaf. XThe third argument is the level of the node Xin the tree, with the root being level zero. X.PP XThe pointers to the key and the root of the tree should be Xof type pointer-to-element, Xand cast to type pointer-to-character. XSimilarly, although declared as type pointer-to-character, Xthe value returned should be cast into type pointer-to-element. X.SH EXAMPLE XThe following code reads in strings and Xstores structures containing a pointer to each string Xand a count of its length. XIt then walks the tree, printing out the stored strings Xand their lengths in alphabetical order. X.PP X.RS X.nf X.ss 18 X#include <search.h> X#include <stdio.h> X Xstruct node { /\(** pointers to these are stored in the tree \(**/ X char \(**string; X int length; X}; Xchar string_space[10000]; /\(** space to store strings \(**/ Xstruct node nodes[500]; /\(** nodes to store \(**/ Xstruct node \(**root = \s-1NULL\s+1; /\(** this points to the root \(**/ X Xmain( ) X{ X char \(**strptr = string_space; X struct node \(**nodeptr = nodes; X void print_node( ), twalk( ); X int i = 0, node_compare( ); X X while (gets(strptr) != \s-1NULL\s+1 && i++ < 500) { X /\(** set node \(**/ X nodeptr\(mi>string = strptr; X nodeptr\(mi>length = strlen(strptr); X /\(** put node into the tree \(**/ X (void) tsearch((char \(**)nodeptr, &root, X node_compare); X /\(** adjust pointers, so we don't overwrite tree \(**/ X strptr += nodeptr\(mi>length + 1; X nodeptr++; X } X twalk(root, print_node); X} X/\(** X This routine compares two nodes, based on an X alphabetical ordering of the string field. X\(**/ Xint Xnode_compare(node1, node2) Xstruct node \(**node1, \(**node2; X{ X return strcmp(node1\(mi>string, node2\(mi>string); X} X/\(** X This routine prints out a node, the first time X twalk encounters it. X\(**/ X.bp Xvoid Xprint_node(node, order, level) Xstruct node \(**\(**node; X\s-1VISIT\s+1 order; Xint level; X{ X if (order == preorder \(or\(or order == leaf) { X (void)printf("string = %20s, length = %d\en", X (\(**node)\(mi>string, (\(**node)\(mi>length); X } X} X.fi X.RE X.SH SEE ALSO Xbsearch(3C), hsearch(3C), lsearch(3C). X.SH DIAGNOSTICS XA X.SM NULL Xpointer is returned by X.I tsearch Xif there is not enough space available to create a new node. X.br XA X.SM NULL Xpointer is returned by X.I tsearch, X.I tfind Xand X.I tdelete Xif X.B rootp Xis X.SM NULL Xon entry. X.br XIf the datum is found, both X.I tsearch Xand X.I tfind Xreturn a pointer to it. XIf not, X.I tfind Xreturns \s-1NULL\s+1, and X.I tsearch Xreturns a pointer to the inserted Xitem. X.SH WARNINGS XThe X.B root Xargument to X.I twalk Xis one level of indirection less than the X.B rootp Xarguments to X.I tsearch Xand X.IR tdelete . X.br XThere are two nomenclatures used to refer to the order in which Xtree nodes are visited. X.I Tsearch Xuses preorder, postorder and endorder to respectively refer to Xvisting a node before any of its children, after its left child Xand before its right, and after both its children. XThe alternate nomenclature uses preorder, inorder and postorder to Xrefer to the same visits, which could result in some confusion over Xthe meaning of postorder. X.SH BUGS XIf the calling function alters the pointer to the Xroot, results are unpredictable. END_OF_tsearch.3c if test 6251 -ne `wc -c <tsearch.3c`; then echo shar: \"tsearch.3c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 4 \(of 5\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Lenny Tropiano ICUS Software Systems [w] +1 (516) 589-7930 lenny@icus.islp.ny.us Telex; 154232428 ICUS [h] +1 (516) 968-8576 {ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752
lenny@icus.islp.ny.us (Lenny Tropiano) (08/03/89)
#! /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 5 (of 5)." # Contents: Makeposix # Wrapped by lenny@icus on Wed Aug 2 21:40:35 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f Makeposix -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makeposix\" else echo shar: Extracting \"Makeposix\" \(16003 characters\) sed "s/^X//" >Makeposix <<'END_OF_Makeposix' X: use /bin/sh X# Makeposix -- add a POSIX-conformant library to your system X X: a sanity check XPATH='.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc' Xexport PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0; kill $$) X X(alias) >/dev/null 2>&1 && \ X echo "(Some versions of ksh blow up on Makeposix, especially on" && \ X echo "exotic machines. If yours does, try the Bourne shell instead.)" X XLIBC=/lib/libc.a X X# . ../configsys.sh X Xcase $1 in '') system="$species" ;; *) system=$1 ;; esac X Xif test -f /usr/lib/lint/llib-lc Xthen X LINTLIB=/usr/lib/lint/llib-lc Xelse X LINTLIB=/usr/lib/llib-lc Xfi X Xcat <<EOF >/dev/null XThis script generates a Makefile and lint library patch for your system that, Xwhen applied, will move it a good part of the way towards conformance with the XPOSIX/SVID/X3J11 C library standards. X XThis script assumes X X 1) that your C library is at $LIBC X 2) that your lint library is at $LINTLIB X XIf either of these assumptions is incorrect, you'll need to edit the shell Xvariable assignments at the beginning of the script. X XHit interrupt key to quit, return key to continue. XEOF X: read stuff X XUSG=-DUSG X XHDS=/usr/include XLINTPATCH=posix.lint X X# X# All pieces of libposix.a must be listed here X# XSTRINGS="strchr.o strrchr.o strcspn.o strpbrk.o strspn.o strtok.o strdup.o" XMEM="memccpy.o memcpy.o memcmp.o memchr.o memset.o" XDIRENT="seekdir.o readdir.o getdents.o closedir.o opendir.o rewinddir.o telldir.o" XMKDIR="mkdir.o rmdir.o" XSEARCH="lsearch.o lfind.o tsearch.o tfind.o bsearch.o" XMISCOBJS="ssignal.o strtol.o getopt.o rename.o putpwent.o" X Xtrap 'rm -f /tmp/needed$$ /tmp/allobjs$$ /tmp/present$$ /tmp/remove$$; exit 0' 0 1 2 15 X X# X# ALLOBJS should list all possible libposix.a parts, with one trailing space X# XALLOBJS="$STRINGS $MEM $SEARCH $MISCOBJS " X X# X# Put support modules that shouldn't show in the feature lists here X# XSUPPORT=getdents.o X Xecho $ALLOBJS | tr " " "\012" >/tmp/allobjs$$ Xecho " " Xecho "Facilities available in the POSIX/SVID/X3J11 compatibility library:" Xsort /tmp/allobjs$$ | grep -v $SUPPORT | pr -5 -t -l1 X Xcase $system in SVR3) X echo " " X echo "You said you're running $system, I'll assume you have:" X echo $DIRENT | tr " " "\012" >/tmp/present$$ X pr -5 -t -l1 </tmp/present$$ X;; X4.3BSD|BSD4_3) X echo " " X echo "You said you're running $system, I'll assume you have:" X echo $MEM | tr " " "\012" > /tmp/present$$ X pr -5 -t -l1 </tmp/present$$ X USG= X;; X4.[12]BSD|BSD4_[12]) X USG= X;; esac Xecho " " Xecho "Analyzing your C library, please wait..." Xar t $LIBC $ALLOBJS 2>/dev/null >>/tmp/present$$ Xsort -u /tmp/present$$ -o /tmp/present$$ Xecho "POSIX/SVID/X3J11 library facilities already present on your system:" Xgrep -v $SUPPORT </tmp/present$$ | pr -5 -t -l1 2>/dev/null Xecho " " X: echo "Hit interrupt key to quit, return key to continue." X: read stuff X Xif grep rewinddir /tmp/present$$ >/dev/null 2>&1 Xthen X cp /dev/null /tmp/needed$$ Xelse X echo $DIRENT | tr " " "\012" >/tmp/needed$$ X echo "You don't have rewinddir, I'll assume you need the new dirent" X echo "package." X echo " " Xfi X X# Extract already-present faculities from allobjs, preserving sort order Xsed -e "/^.*$/s//\/&\/d/" </tmp/present$$ >/tmp/remove$$ Xsed -f /tmp/remove$$ </tmp/allobjs$$ >>/tmp/needed$$ Xecho " " Xecho "POSIX/SVID/X3J11 library facilities that should be installed:" Xsort /tmp/needed$$ | pr -5 -t -l1 2>/dev/null Xecho " " X: echo "Hit interrupt key to quit, return key to continue." X: read stuff X X# set corresponding shell variable for each object file needed Xfor x in `tr "\012" " " </tmp/needed$$` Xdo X set eval `expr $x : "\(.*\).o"`"=y" Xdone X Xecho " " Xecho "A copy of your lint patch will be written to $LINTPATCH." Xecho "/* POSIX library extensions */" >$LINTPATCH X Xif grep lockf $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int lockf(fd, fn, sz) int fd, fn; long sz; {return 0;}" >>$LINTPATCH Xfi Xif [ ! -f $HDS/dirent.h ] Xthen X dirent='yes' X man4list="$man4list dirent.4" Xfi Xif grep getdents $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X cat >>$LINTPATCH <<EOF X/* DIRECTORY(3C) */ X#include <dirent.h> Xint getdents(f, b, n) int f; char *b; unsigned n; { return 0; } XEOF Xfi X Xif grep closedir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int closedir(p) DIR *p; { return 0; }" >>$LINTPATCH Xfi Xif grep opendir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "DIR *opendir(f) char *f; {return (DIR *)NULL;}" >>$LINTPATCH Xfi Xif grep readdir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "struct dirent *readdir(p) DIR *p; {return (struct dirent*)NULL;}" >>$LINTPATCH Xfi Xif grep seekdir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "void seekdir(p, l) DIR *p; long l; {}" >>$LINTPATCH Xfi Xif grep telldir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "long telldir(p) DIR *p; {return 1L;}" >>$LINTPATCH Xfi X Xif grep mkdir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "/* MKDIR(3) */" >>$LINTPATCH X echo "int mkdir(s, p) char *s; int p; {return (0);}" >>$LINTPATCH X man3list="$man3list mkdir.3" Xfi Xif grep rmdir $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "/* RMDIR(3) */" >>$LINTPATCH X echo "int rmdir(s) char *s; {return (0);}" >>$LINTPATCH X man3list="$man3list rmdir.3" Xfi X Xif grep str /tmp/needed$$ >/dev/null 2>&1 Xthen X echo "/* STRING(3C) */" >>$LINTPATCH X strings='yes' X man3list="$man3list string.3" Xfi Xif grep strcat $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strcat(a, b) char *a, *b; { return (a); }" >>$LINTPATCH Xfi Xif grep strncat $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strncat(a, b, n) char *a, *b; { return (a); }" >>$LINTPATCH Xfi Xif grep strcmp $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int strcmp(a, b) char *a, *b; { return (0); }" >>$LINTPATCH Xfi Xif grep strncmp $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int strncmp(a, b, n) char *a, *b; { return (n); }" >>$LINTPATCH Xfi Xif grep strcpy $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strcpy(a, b) char *a, *b; { return (a); }" >>$LINTPATCH Xfi Xif grep strncpy $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strncpy(a, b, n) char *a, *b; { return (a); }" >>$LINTPATCH Xfi Xif grep strlen $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int strlen(s) char *s; { return (0); }" >>$LINTPATCH Xfi Xif grep strchr $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strchr(a, b) char *a, b; { return (a); }" >>$LINTPATCH Xfi Xif grep strrchr $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strrchr(a, b) char *a, b; { return (a); }" >>$LINTPATCH Xfi Xif grep strpbrk $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strpbrk(a, b) char *a, *b; { return (a); }" >>$LINTPATCH Xfi Xif grep strspn $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int strspn(a, b) char *a, *b; { return (0); }" >>$LINTPATCH Xfi Xif grep strcspn $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int strcspn(a, b) char *a, *b; { return (0); }" >>$LINTPATCH Xfi Xif grep strtok $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strtok(a, b) char *a, *b; { return (a); }" >>$LINTPATCH Xfi Xif grep strdup $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char * strdup(a) char *a; { return (a); }" >>$LINTPATCH Xfi X Xif grep str /tmp/needed$$ >/dev/null 2>&1 Xthen X echo "/* MEMORY(3C) */" >>$LINTPATCH X memory='yes' X man3list="$man3list memory.3" Xfi Xif [ X$memccpy != X ] Xthen X echo "char *memccpy(a,b,c,n) char *a,*b; {return(a);}" >>$LINTPATCH Xfi Xif [ X$memchr != X ] Xthen X echo "char *memchr(s,c,n) char *s; {return (s);}" >>$LINTPATCH Xfi Xif [ X$memcmp != X ] Xthen X echo "int memcmp(a, b, n) char *a, *b; {return(n);}" >>$LINTPATCH Xfi Xif [ X$memcpy != X ] Xthen X echo "char *memcpy(a,b,n) char *a, *b; {return (a);}" >>$LINTPATCH Xfi Xif [ X$memset != X ] Xthen X echo "char *memset(s,c,n) char *s; {return (s);}" >>$LINTPATCH Xfi X Xif grep lsearch $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "/* LSEARCH(3C) */" >>$LINTPATCH X echo "char *lsearch(k,b,n,w,c) char *k,*b; unsigned *n,w; int (*c)(); {return(k);}" >>$LINTPATCH Xfi Xif grep lfind $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char *lfind(k,b,n,w,c) char *k,*b; unsigned *n,w; int (*c)();{return(k); }" >>$LINTPATCH Xfi X#include <search.h> Xif grep bsearch /tmp/needed$$ >/dev/null 2>&1 Xthen X echo "/* BSEARCH(3C) */" >>$LINTPATCH X search='yes' X man3list="$man3list bsearch.3c" Xfi Xif grep bsearch $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char *bsearch(k,b,n,w,c) char *k,*b; unsigned n,w; int (*c)();{return(k);}" >>$LINTPATCH Xfi Xif grep tsearch /tmp/needed$$ >/dev/null 2>&1 Xthen X echo "/* TSEARCH(3C) */" >>$LINTPATCH X search='yes' X man3list="$man3list tsearch.3c" Xfi Xif grep tsearch $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char *tsearch(k,r,c) char *k, **r; int (*c)(); {return(k);}" >>$LINTPATCH Xfi Xif grep tfind $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "char *tfind(k,r,c) char *k,**r; int (*c)(); {return(k);}" >>$LINTPATCH Xfi Xif grep [gs]signal $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "/* SSIGNAL(3) */" >>$LINTPATCH X echo "int (*ssignal(s, a))() int (*a)(); { return (a); }" >>$LINTPATCH X echo "int gsignal(s) {return (s);}" >>$LINTPATCH X man3list="$man3list ssignal.3c" Xfi X Xif grep strtol $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "long strtol(s,t,b) char *s,**t; {return(0L);}" >>$LINTPATCH X man3list="$man3list strtol.3c" Xfi Xif grep getopt $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "int getopt(c,v,o) char **v, *o; {return(c);}" >>$LINTPATCH X man3list="$man3list getopt.3c" Xfi Xif grep rename $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "/* RENAME(3) */" >>$LINTPATCH X echo "int rename(s, t) char *s, *t; {return (0);}" >>$LINTPATCH X man3list="$man3list rename.3c" Xfi Xif grep putpwent $LINTLIB >/dev/null 2>&1 Xthen X : do nothing Xelse X echo "/* PUTPWENT(3C) */" >>$LINTPATCH X echo "int putpwent(s,f) struct passwd *s; FILE *f; {return(0);}" >>$LINTPATCH X man3list="$man3list putpwent.3c" Xfi X Xcat <<EOT >/dev/null X XProductions that can install these changes will now be written to Makefile. XRemember to edit out the -DUSG from the CFLAGS line if you're on a non-AT&T XUNIX (i.e. a V7 or BSD-based version). -DUSG will be removed for you Xautomatically if you had specified 4.2BSD or 4.3BSD as the type of Xyour system. Other installation instructions will be found in a Xleading comment in the generated Makefile. XEOT Xobjlist=`tr '\012' ' ' </tmp/needed$$` X Xcat >Makefile <<EOF X# This makefile will install a number of X3J11/POSIX/SVID functions in your X# standard C library. If you have a source license, the method described X# in DIRENT.INSTALL is recommended instead. X# X# To make the library: X# a. Edit getdents.c if necessary to define UFS, NFS or BFS. X# X# b. Type 'make'. If you get errors, stop and fix them. X# This will create a local copy of the code named libposix.a X# which you can use for testing or install in /lib. X# X# To install it: X# X# a. Go superuser and type 'make install'. That's all there is to it. X# You may want to do 'make -n install' first so you know what it's X# doing. If you don't like the default action you can edit the X# Makefile. X# X# b. If you don't like this option, you can put the libposix.a library X# in your libraries directory and add an appropriate -I option to X# your include file search path. X# X# Note: the implementations of strchr() and strrchr() are pure C code, so they X# may be marginally slower than the (presumably tuned) index/rindex in V7/BSD. X# You can #define them to index/rindex via the the preprocessor, or ar x X# copies of the index.o and rindex.o object files, patch the function names X# with adb and wedge the copies in. X XSHELL = /bin/sh XHDS = $HDS XMAN = /usr/man XLIBC = $LIBC XLINTLIB = $LINTLIB XSTRINGS= $STRINGS XMEM= $MEM XDIRENT= $DIRENT XMKDIR= $MKDIR XSEARCH= $SEARCH XMISCOBJS= $MISCOBJS XPORTOBJS = ${objlist} X# CF = -Dvoid=int # Uncomment this for cc versions with no void XCC = cc XCFLAGS = -O $USG -I. \$(CF) X XMAINDIR = .. XLIBSDIR = \$(MAINDIR) X Xlibposix.a: \$(PORTOBJS) X ar lruv libposix.a \$(PORTOBJS) X @echo "If you're on an AT&T UNIX, ignore the next error message" X -ranlib libposix.a X (cd profiled; ar lrc ../libposix_p.a \$?) X @echo "If you're on an AT&T UNIX, ignore the next error message" X ranlib libposix_p.a X X.c.o: X \${CC} -p \${CFLAGS} -c \$*.c X mv \$*.o profiled/\$*.o X \${CC} \${CFLAGS} -c \$*.c X Xexport: libposix.a X @rm -f $(LIBSDIR)/libposix.a X -ln libposix.a $(LIBSDIR) X @rm -f $(LIBSDIR)/profiled/libposix.a X -ln libposix_p.a $(LIBSDIR)/profiled/libposix.a X @-mkdir ../sys X @rm -f ../sys/dirent.h X -ln sys.dirent.h ../sys/dirent.h X @rm -f ../dirent.h ../search.h ../unistd.h ../memory.h ../string.h X -ln dirent.h search.h unistd.h memory.h string.h .. X XMakefile: Makeposix posix_conf X Makeposix X Xclean: X rm -f libposix.a *.o posix_conf Makefile profiled/* X Xtestdir: testdir.c libposix.a X \$(CC) \$(CFLAGS) \$(LFLAGS) testdir.c libposix.a -o testdir X Xmkdirtest: mkdirtest.c libposix.a X \$(CC) \$(CFLAGS) \$(LFLAGS) mkdirtest.c libposix.a -o mkdirtest X XLINTPATCH = $LINTPATCH X X# Restore original library, lint and header files Xrestore: X -cp \$(LIBC)-orig \$(LIBC) X -cp \$(LINTLIB)-orig \$(LINTLIB) X -cp \$(LINTLIB).ln-orig \$(LINTLIB).ln X -cp \$(HDS)/string.h-orig \$(HDS)/string.h X -cp \$(HDS)/memory.h-orig \$(HDS)/memory.h X -cp \$(HDS)/search.h-orig \$(HDS)/search.h X X# Recompile the lint library (AT&T SVr2 or later) Xrelint: X cp \$(LINTLIB) llib-lc.c X lint -c llib-lc.c; rm llib-lc.c X mv llib-lc.ln \$(LINTLIB).ln X X# Make everything (for test purposes) Xtestlib.a: $ALLOBJS X ar lruv testlib.a $ALLOBJS X @echo "If you're on an AT&T UNIX, ignore the next error message" X -ranlib testlib.a X X# Install all the portability hacks Xinstall: \$(PORTOBJS) XEOF Xif [ ! -f $HDS/unistd.h ] Xthen X echo " @echo 'Installing unistd.h header file...'" >>Makefile X echo " -cp unistd.h \$(HDS)/unistd.h;" >>Makefile Xfi Xif [ "X$dirent" != "X" ] Xthen X echo " @echo 'Installing dirent library headers...'" >>Makefile X echo " -cp dirent.h \$(HDS)/dirent.h;" >>Makefile X echo " -cp sys.dirent.h \$(HDS)/sys/dirent.h;" >>Makefile Xfi Xif [ "X$strings" != "X" ] Xthen X echo " @echo 'Installing string library headers...'" >>Makefile X echo " -cp \$(HDS)/string.h \$(HDS)/string.h-orig;" >>Makefile X echo " -cp string.h \$(HDS)/string.h;" >>Makefile Xfi Xif [ "X$memory" != "X" ] Xthen X echo " @echo 'Installing memory library headers...'" >>Makefile X echo " -cp \$(HDS)/memory.h \$(HDS)/memory.h-orig;" >>Makefile X echo " -cp memory.h \$(HDS)/memory.h;" >>Makefile Xfi Xif [ "X$search" != "X" ] Xthen X echo " @echo 'Installing search library headers...'" >>Makefile X echo " -cp \$(HDS)/search.h \$(HDS)/search.h-orig;" >>Makefile X echo " -cp search.h \$(HDS)/search.h;" >>Makefile Xfi Xcat >>Makefile <<EOF X @echo "Installing new C library functions..." X -cp \$(LIBC) \$(LIBC)-orig X ar lruv \$(LIBC) \$(PORTOBJS) X @echo "If you're on an AT&T UNIX, ignore the next error message" X -ranlib \$(LIBC) X @echo "Installing extension library manuals..." X -cp ${man3list} \$(MAN)/man3; X -cp ${man4list} \$(MAN)/man4; X @echo "Installing lint library additions..." X cp \$(LINTLIB) \$(LINTLIB)-orig X cp \$(LINTLIB).ln \$(LINTLIB).ln-orig X cat $LINTPATCH >>\$(LINTLIB) X @echo "Your $LINTLIB will need to be recompiled" X @echo "If you are on an SVr2 or later, just do 'make relint'" XEOF X Xcat <<EOF >/dev/null X XNow type 'make' to make the library. Test productions have been Xincluded. When you're satisfied that everything works, go root and Xtype 'make install' (you may want to look at the Makefile to make Xsure it's not doing anything untoward). X XIf you're on SVr2 or later, you will probably want to do a 'make relint' Xafter the installation. On V7, SIII and BSD systems you'll have to work out Xyour own way of recompiling the modified lint file. X XA restore production is provided to back out the changes. XEOF X Xtouch posix_conf Xmkdir profiled 2>&1 >/dev/null X# Portability library config script ends here END_OF_Makeposix if test 16003 -ne `wc -c <Makeposix`; then echo shar: \"Makeposix\" unpacked with wrong size! fi chmod +x Makeposix # end of overwriting check fi echo shar: End of archive 5 \(of 5\). cp /dev/null ark5isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Lenny Tropiano ICUS Software Systems [w] +1 (516) 589-7930 lenny@icus.islp.ny.us Telex; 154232428 ICUS [h] +1 (516) 968-8576 {ames,talcott,decuac,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752