dono@killer.DALLAS.TX.US (Don OConnell) (12/17/88)
I had posted this file on dec 14th and then we(killer) had several disk
crashes so I don't know it these went out. I had also posted an older version
of the directory routines that didn't use dirent.h(but since the posting
by EFTH I won't repost them).
This implementation came from one of the comp.sources directories (can't
remember which). It is an implentation of lc from BSD type machines(columnar
output) similar to ls -C on sysV machines. Copyright is from U. of Waterloo.
It requires the bsd - directory style access routines that have been posted.
--------------------------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 shell archive."
# Contents: lc.c lc.man
# Wrapped by dono@killer on Wed Dec 14 12:06:41 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lc.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lc.c\"
else
echo shar: Extracting \"lc.c\" \(7322 characters\)
sed "s/^X//" >lc.c <<'END_OF_lc.c'
X#ifndef lint
Xstatic char *copyright =
X "LC - Copyright University of Waterloo, 1978,1985,1987";
X#endif lint
X/*
X * lc [directory ...]
X */
X
X#include <stdio.h>
X#include <string.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X#include <errno.h>
X
X#ifndef MAXPATHLEN
X#define MAXPATHLEN 1024 /* For older systems */
X#endif
X
X /* this assumes that S_IFMT is a mask of contiguous 1s */
X#define IFMT_OFFSET 12 /* may be system-dependent */
X#define IFMT (S_IFMT >> IFMT_OFFSET)
X
X#define MODEX(m) (((m)>>IFMT_OFFSET)&IFMT) /* IFMT to table index */
X
Xextern int errno,sys_nerr;
Xextern char *strcpy(),*strncpy();
Xextern char *sys_errlist[];
Xint pstrcmp();
X
X#define NMALLOC 100 /* how much to malloc in growlist() */
X#define COLUMNWIDTH 15 /* number of characters in a column */
X#define INDENT " " /* blanks at beginning of a column */
X
Xstruct filelist {
X char **names; /* pointer to array of names */
X int size; /* how many elements */
X int end; /* next element to use */
X int flag;
X char *title;
X}
X dlist = {(char **) NULL, 0, 0, 0, "Directories"},
X flist = {(char **) NULL, 0, 0, 0, "Files"},
X plist = {(char **) NULL, 0, 0, 0, "Pipes"},
X blist = {(char **) NULL, 0, 0, 0, "Block Spec. Files"},
X clist = {(char **) NULL, 0, 0, 0, "Char. Spec. Files"},
X mpclist = {(char **) NULL, 0, 0, 0, "MPX Char. Files"},
X mpblist = {(char **) NULL, 0, 0, 0, "MPX Block Files"},
X symlist = {(char **) NULL, 0, 0, 0, "Unsatisfied Symbolic Links"},
X soclist = {(char **) NULL, 0, 0, 0, "Sockets"},
X /* flag is always on for this list */
X goklist = {(char **) NULL, 0, 0, 1, "**GOK"};
X
Xstruct filelist *printlist[] = {
X &dlist, &flist, &plist, &blist, &clist, &mpclist, &mpblist, &symlist,
X &soclist, &goklist, 0
X};
X
Xstruct filelist *listtype[IFMT-1];
X
Xstruct xinit {
X int x_flag;
X struct filelist *x_list;
X} xinit[] ={
X#ifdef S_IPIPE
X S_IPIPE, &plist,
X#endif
X#ifdef S_IFPIP
X S_IFPIP, &plist,
X#endif
X S_IFREG, &flist,
X S_IFDIR, &dlist,
X S_IFCHR, &clist,
X S_IFBLK, &blist,
X#ifdef S_IFMPC
X S_IFMPC, &mpclist,
X#endif
X#ifdef S_IFMPB
X S_IFMPB, &mpblist,
X#endif
X#ifdef S_IFLNK
X S_IFLNK, &symlist,
X#endif
X#ifdef S_IFSOCK
X S_IFSOCK, &soclist,
X#endif
X -1,
X};
X
Xint nfl; /* flag; this is not the first line of output */
Xint errcall; /* flag; last line of output was error message */
Xint notfirst; /* flag; means not the first thing in this directory */
Xint nflg; /* flag; no output - just want exit status */
Xint ncols = 5; /* number of columns */
Xint linewidth;
Xint manyflg;
Xint anyfound;
Xint all = 1;
Xchar pathbuf[MAXPATHLEN];
Xchar *fnptr = pathbuf;
Xint aflg;
X
Xmain(argc, argv)
X char *argv[];
X{
X register char *path, *p, *q;
X struct xinit *xp;
X int i;
X
X for (i = 0 ; i < IFMT ; i++)
X listtype[i] = &goklist;
X for (xp = xinit; xp->x_flag != -1; xp++)
X listtype[MODEX(xp->x_flag)] = xp->x_list;
X if(argc >= 2 && argv[1][0] == '-') {
X argv++;
X argc--;
X for(p = &argv[0][1]; *p; p++)
X switch(*p) {
X case 'a':
X aflg++;
X break;
X
X case 'n':
X nflg++;
X break;
X
X case '1':
X ncols=1;
X break;
X
X default:
X switch(*p) {
X case 'f':
X flist.flag++;
X break;
X
X case 'd':
X dlist.flag++;
X break;
X
X case 'b':
X blist.flag++;
X break;
X
X case 'c':
X clist.flag++;
X break;
X
X case 'B':
X mpblist.flag++;
X break;
X
X case 'C':
X mpclist.flag++;
X break;
X
X case 's':
X blist.flag++;
X clist.flag++;
X mpblist.flag++;
X mpclist.flag++;
X break;
X
X case 'p':
X plist.flag++;
X break;
X
X default:
X fprintf(stderr, "Unknown flag: %c\n",
X *p);
X continue;
X }
X all = 0;
X }
X }
X
X if (all)
X flist.flag = dlist.flag = blist.flag = clist.flag
X = mpblist.flag = mpclist.flag
X = symlist.flag = soclist.flag
X = plist.flag = 1;
X
X linewidth = ncols * COLUMNWIDTH;
X
X if(argc < 3) {
X path = argc == 1 ? "." : argv[1];
X listdir(path);
X } else {
X manyflg++;
X while(--argc) {
X path = p = *++argv;
X if(strlen(path) >= MAXPATHLEN) {/* = for '/' */
X errno=ENAMETOOLONG;
X warn(path);
X continue;
X }
X q = pathbuf;
X while(*q++ = *p++);
X q[-1] = '/';
X fnptr = q;
X listdir(path);
X }
X }
X exit(anyfound==0);
X}
X
Xlistdir(path)
X char *path;
X{
X register char *p;
X struct direct *d;
X struct filelist **pr;
X DIR *u;
X struct stat ibuf;
X
X if(stat(path, &ibuf) < 0) {
X warn(path);
X return;
X }
X if((ibuf.st_mode&S_IFMT) != S_IFDIR) {
X if(!manyflg){
X errno=ENOTDIR;
X warn(path);
X }
X return;
X }
X if((u = opendir(path)) == NULL) {
X warn(path);
X return;
X }
X if(manyflg) {
X if(nfl++)
X putchar('\n');
X printf("%s:\n", path);
X } else
X chdir(path);
X while((d = readdir(u)) != NULL) {
X if(fnptr + d->d_namlen >= &pathbuf[MAXPATHLEN]) {
X errno=ENAMETOOLONG;
X warn(pathbuf);
X/*
X err("%s: Component `%s' makes pathname > %d bytes.\n",
X pathbuf, d->d_name, MAXPATHLEN);
X*/
X continue;
X }
X (void)strcpy(fnptr, d->d_name);
X if(stat(pathbuf, &ibuf) < 0 && lstat(pathbuf, &ibuf) < 0) {
X warn(pathbuf);
X continue;
X }
X /*
X * ignore "." and ".."
X */
X if((ibuf.st_mode&S_IFMT) == S_IFDIR && aflg == 0) {
X p = d->d_name;
X if(*p++ == '.' && (*p == '\0'
X || *p++ == '.' && *p == '\0'))
X continue;
X }
X
X build(listtype[MODEX(ibuf.st_mode)], d->d_name);
X }
X
X closedir(u);
X notfirst = 0;
X for(pr = printlist; *pr; pr++)
X if((*pr)->names && (*pr)->end != 0) {
X qsort( (*pr)->names, (*pr)->end,
X sizeof (char *), pstrcmp );
X print(*pr);
X }
X fflush(stdout);
X}
X
Xwarn(name)
X char *name;
X{
X if(nfl && !errcall)
X putchar('\n');
X if((errno>=0)&&(errno<sys_nerr))
X fprintf(stdout,"%s: %s\n", name,sys_errlist[errno]);
X else
X fprintf(stdout,"%s: unknown error (%d).\n", name,errno);
X fflush(stdout);
X errcall=nfl=1;
X errno=0;
X}
X
Xprint(list)
X struct filelist *list;
X{
X register int cursor, i;
X register char **p;
X
X if(notfirst++)
X putchar('\n');
X if(ncols!=1) {
X if (manyflg)
X fputs(INDENT, stdout);
X printf("%s:\n", list->title);
X }
X cursor = 0;
X for(p = list->names, i = 0; i < list->end; i++) {
X int len;
X int posused; /* positions used by blanks and filename */
X register char *fname;
X
X fname = p[i];
X len = strlen(fname);
X posused = len + ((cursor == 0) ? 0 : COLUMNWIDTH - cursor%COLUMNWIDTH);
X if ((cursor + posused) > linewidth) {
X printf("\n");
X cursor = 0;
X posused = len;
X }
X if (manyflg && (cursor == 0)) fputs(INDENT, stdout);
X printf("%*s", posused, fname);
X cursor += posused;
X }
X if(cursor != 0)
X printf("\n");
X errcall = 0;
X if (manyflg)
X release(list);
X}
X
Xbuild(list, name)
X struct filelist *list;
X char *name;
X{
X register int n;
X
X if(list->flag == 0)
X return;
X anyfound++;
X if(nflg)
X return;
X if (list->end >= list->size)
X growlist(list);
X n = strlen( name ) + 1;
X
X (list->names)[list->end++] = strncpy( malloc( n ), name, n );
X}
X
Xgrowlist( list )
X struct filelist *list;
X{
X register int oldsize, newsize;
X register char **newlist;
X
X oldsize = list->size * sizeof (char *);
X newsize = oldsize + (NMALLOC * sizeof (char *));
X
X newlist = (char **) malloc( newsize );
X
X if (oldsize != 0) {
X bcopy( list->names, newlist, oldsize );
X free( list->names );
X }
X
X list->names = newlist;
X list->size += NMALLOC;
X}
X
Xrelease( list )
X struct filelist *list;
X{
X register char **p;
X register int i;
X
X for (p = list->names, i = 0; i < list->end; i++)
X free( p[i] );
X
X list->end = 0;
X}
X
Xpstrcmp( a, b )
X char **a, **b;
X{
X return (strcmp( *a, *b ));
X}
END_OF_lc.c
if test 7322 -ne `wc -c <lc.c`; then
echo shar: \"lc.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f lc.man -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lc.man\"
else
echo shar: Extracting \"lc.man\" \(2069 characters\)
sed "s/^X//" >lc.man <<'END_OF_lc.man'
XNAME - lc list directory and file names in columns
X
X
XSYNOPSIS - lc [-fdbcspan1] [ directory ... ]
X
X
XDESCRIPTION
X
X Lc lists the elements of the given directories. The elements are divided
X into the five basic types (files, directories, character special files,
X block special files, and pipes) and are printed in alphabetical order.
X They are normally printed 5 to a line, preceeded by a title indicating
X the type, but the -1 option can be used to force single-column untitled
X output.
X
X If the argument list contains more than one name, the contents of the
X directories named in the list are displayed and all other names
X are ignored. If no directory is specified the current working directory
X is listed by default. The special entries ``.'' and ``..'' are normally
X not listed; the -a option causes them to be listed as well.
X
X The -n option turns off all output; this is useful when only the exit
X status is wanted. (The exit status is 0 if something would have been
X printed, 1 otherwise.)
X
X If any of the following option arguments are given,
X lc lists only those types of entries; otherwise, all entries are listed.
X
X The options and their meanings are:
X
X -f list ordinary files
X -d list directories
X -b list block special files
X -c list character special files
X -s list all special files
X -p list permanent pipes
X
X
X Lc may be used with the substitution features of the Shell to select
X particular kinds of files (eg, directories) to take part in some
X processing, for example:
X
X ls -l `lc -1d`
X This lists the contents of all sub-directories of the current directory.
X
X
XDIAGNOSTICS
X Symbolic links are normally followed, and each prints under the category
X of the type of thing to which it is linked. If the symbolic link points
X to a nonexistent pathname, or if you do not have permission to resolve
X the pathname, lc will list the link under the category "Unresolved
X Symbolic Links."
X
END_OF_lc.man
if test 2069 -ne `wc -c <lc.man`; then
echo shar: \"lc.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0