dono@killer.DALLAS.TX.US (Don OConnell) (12/15/88)
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 I am also posting. --------------------------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