[comp.os.minix] ls -C

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