le.c

Peter da Silva peter at baylor.UUCP
Fri Aug 16 03:02:06 AEST 1985


Having recieved numerous (well, 2) requests for "le", here's the source offered
without comment. 4.2 people will undoubtedly have to patch it to handle the
crufty new directories, but I have done that for a descendent of this (a visual
shell) and it's no hassle. V7 people rejoice: it runs under that venerable
system. I have never tried to convert it ro its descendents fo SIII/SV, so
let me know what luck you have.

---- le.c -----
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

#define D_DEV	01
#define D_INO	02
#define D_MODE	04
#define D_LINKS	010
#define D_UID	020
#define D_GID	040
#define D_RDEV	0100
#define D_SIZE	0200
#define D_ATIME	0400
#define D_MTIME	01000
#define D_CTIME	02000

#define D_SMODE 04000
#define D_SUID  010000
#define D_SGID  020000

#define FALSE 0
#define TRUE 1

#define MAXENTS 512
#define MAXID 64

struct entry {
	struct direct e_dir;
	char filler;
	struct stat e_stat;
} entries[MAXENTS];
int nentries;

char *errname;
extern int errno;
int xerrno;
char *tab=" ";
long maxsize;
char sizstr[2][10] = {"%6lu%s","%6s%s"};
int dohead=0, dodir=1;
int flags = D_MODE|D_LINKS|D_UID|D_SIZE|D_MTIME;

char *emesg[3]={
	"No such error",
#define TOO_MANY 1
	"Too many directory entries",
	0
};

getdir(dir)
char *dir;
{
	int	entcmp();
	char *nameof();
	FILE *fp;
	int valid;

	if(!(fp = fopen(dir, "r"))) {
		errname=dir;
		return FALSE;
	}

	maxsize=0L;
	for(nentries=0;
	    nentries<MAXENTS &&
	      fread(&entries[nentries].e_dir,
		    sizeof entries[nentries].e_dir, 1, fp)>0;
	    nentries += valid) {
		if(valid=entries[nentries].e_dir.d_ino?1:0) {
			entries[nentries].filler=0;
			if(stat(nameof(entries[nentries].e_dir.d_name, dir),
				&entries[nentries].e_stat
			       )==-1
			  ) {
				fclose(fp);
				errname=nameof(entries[nentries].e_dir.d_name,
						dir);
				return FALSE;
			}
			if(entries[nentries].e_stat.st_size>maxsize)
				maxsize=entries[nentries].e_stat.st_size;
		}
	}

	if(nentries>=MAXENTS) {
		errno=0;
		xerrno=TOO_MANY;
		errname=dir;
		return FALSE;
	}

	fclose(fp);

	qsort(entries, nentries, sizeof(struct entry), entcmp);

	setsize(maxsize);

	return TRUE;
}

setsize(size)
long size;
{
	char tmp[32];
	int siz;
	sprintf(tmp, "%lu", size);
	siz=strlen(tmp);
	if(siz<6) siz=6;
	sprintf(sizstr[0], "%%%dlu%%s", siz);
	sprintf(sizstr[1], "%%%ds%%s", siz);
	if(dohead) {
		header();
		dohead=0;
	}
}

char *
nameof(name, dir)
char *name, *dir;
{
	char nambuf[BUFSIZ];

	if(!dir[0])
		return name;
	if(dir[0]=='.' && !dir[1])
		return name;
	else if(dir[0]=='/' && !dir[1]) {
		sprintf(nambuf, "/%s", name);
		return nambuf;
	} else {
		sprintf(nambuf, "%s/%s", dir, name);
		return nambuf;
	}
}

pname(name)
char *name;
{
	int len = 0;

	for(;*name; name++)
		if(*name<' ') { printf("^%c", *name+'@'); len+=2; }
		else if(*name=='\0177') { printf("^?"); len+=2; }
		else if(*name>'\0177') { printf("\\%03o", *name); len += 4; }
		else { putchar(*name); len++; }
	return len;
}

entcmp(e1, e2)
struct entry *e1, *e2;
{
	return strcmp(e1->e_dir.d_name, e2->e_dir.d_name);
}

fdump(dir)
char *dir;
{
	struct stat sbuf;

	if(stat(dir, &sbuf)==-1) {
		errname=dir;
		return FALSE;
	} else
		if(dodir && (sbuf.st_mode&S_IFMT)==S_IFDIR) {
			if(getdir(dir))
				return dump(dir);
			else
				return FALSE;
		} else {
			setsize(sbuf.st_size);
			statout(dir, &sbuf, ".");
			return TRUE;
		}
}

dump(dir)
char *dir;
{
	int i, j;
	int chars;

	if(flags==0) {
		for(i=0; i<=nentries/5; i++) {
			chars = 0;
			for(j=0; j<5; j++) {
				if(i+j*nentries/5<nentries)
					chars +=
					pname(entries[i+j*nentries/5].e_dir.d_name);
				if(chars<8) { putchar('\t'); chars=8; }
				if(chars<16) { putchar('\t'); chars=16; }
				else { putchar(' '); chars++; }
				chars %= 16;
			}
			putchar('\n');
		}
	}
	else for(i=0; i<nentries; i++)
		statout(entries[i].e_dir.d_name,
			&entries[i].e_stat, dir);
	return TRUE;
}

statout(name, sbuf, dir)
char *name;
struct stat *sbuf;
char *dir;
{
	char *u_name(), *g_name();

	if(flags&D_DEV)
		printf("%3d,%3d%s",
			major(sbuf->st_dev),
			minor(sbuf->st_dev),
			tab);
	if(flags&D_RDEV)
		printf("%3d,%3d%s",
			major(sbuf->st_rdev),
			minor(sbuf->st_rdev),
			tab);
	if(flags&D_INO)
		printf("%5u%s", sbuf->st_ino, tab);
	if(flags&D_SMODE)
		printf("%6o%s", sbuf->st_mode, tab);
	if(flags&D_MODE) {
		int mode = sbuf->st_mode;
		if((mode&S_IFMT)==S_IFCHR) putchar('c');
		else if((mode&S_IFMT)==S_IFBLK) putchar('b');
		else if((mode&S_IFMT)==S_IFDIR) putchar('d');
		else if((mode&S_IFMT)==S_IFREG) putchar('-');
		else putchar('?');
		triad((mode>>6)&7, mode&S_ISUID, 's');
		triad((mode>>3)&7, mode&S_ISGID, 's');
		triad(mode&7, mode&S_ISVTX, 't');
		printf("%s", tab);
	}
	if(flags&D_LINKS)
		printf("%3u%s", sbuf->st_nlink, tab);
	if(flags&D_SUID)
		printf("%3d%s", sbuf->st_uid, tab);
	if(flags&D_UID)
		printf("%-8s%s", u_name(sbuf->st_uid), tab);
	if(flags&D_SGID)
		printf("%3d%s", sbuf->st_gid, tab);
	if(flags&D_GID)
		printf("%-8s%s", g_name(sbuf->st_gid), tab);
	if(flags&D_SIZE)
		printf(sizstr[0], sbuf->st_size, tab);
	if((flags&~(D_ATIME|D_MTIME|D_CTIME)) &&
	   (flags&(D_ATIME|D_MTIME|D_CTIME))) putchar(' ');
	if(flags&D_ATIME)
		printime(&sbuf->st_atime);
	if(flags&D_MTIME)
		printime(&sbuf->st_mtime);
	if(flags&D_CTIME)
		printime(&sbuf->st_ctime);
	pname(nameof(name, dir));
	putchar('\n');
}

struct idtab {
	int id_id;
	char id_name[10];
} u_list[MAXID], g_list[MAXID];
int u_ptr=0, g_ptr=0;

char *
u_name(uid)
int uid;
{
	int i;
	struct passwd *pwptr, *getpwuid();

	for(i=0; i<u_ptr; i++)
		if(u_list[i].id_id==uid)
			return u_list[i].id_name;

	u_list[u_ptr].id_id=uid;

	if(pwptr=getpwuid(uid)) {
		for(i=0; pwptr->pw_name[i]>' '; i++)
			u_list[u_ptr].id_name[i]=pwptr->pw_name[i];
		u_list[u_ptr].id_name[i]=0;
	} else
		sprintf(u_list[u_ptr].id_name, "%d", uid);

	return u_list[u_ptr++].id_name;
}

char *
g_name(gid)
int gid;
{
	int i;
	struct group *grptr, *getgrgid();

	for(i=0; i<g_ptr; i++)
		if(g_list[i].id_id==gid)
			return g_list[i].id_name;

	g_list[g_ptr].id_id=gid;

	if(grptr=getgrgid(gid)) {
		for(i=0; grptr->gr_name[i]>' '; i++)
			g_list[g_ptr].id_name[i]=grptr->gr_name[i];
		g_list[g_ptr].id_name[i]=0;
	} else
		sprintf(g_list[g_ptr].id_name, "%d", gid);

	return g_list[g_ptr++].id_name;
}

printime(clock)
long *clock;
{
	struct tm *tmbuf, *localtime();
	static char *months[12]= {
		"Jan","Feb","Mar","Apr","May","Jun",
		"Jul","Aug","Sep","Oct","Nov","Dec"
	};

	tmbuf=localtime(clock);
	printf("%2d %3s %02d %2d:%02d %s",
		tmbuf->tm_mday,
		months[tmbuf->tm_mon],
		tmbuf->tm_year,
		tmbuf->tm_hour,
		tmbuf->tm_min,
		tab);
}

header()
{
	if(flags&D_DEV)
		printf("%7s%s", "IDev", tab);
	if(flags&D_RDEV)
		printf("%7s%s", "Rdev", tab);
	if(flags&D_INO)
		printf("%5s%s", "Inode", tab);
	if(flags&D_SMODE)
		printf("%6s%s", "Mode", tab);
	if(flags&D_MODE)
		printf("%-10s%s", "Long mode", tab);
	if(flags&D_LINKS)
		printf("%3s%s", "Lnx", tab);
	if(flags&D_SUID)
		printf("%3s%s", "UID", tab);
	if(flags&D_UID)
		printf("%-8s%s", "User", tab);
	if(flags&D_SGID)
		printf("%3s%s", "GID", tab);
	if(flags&D_GID)
		printf("%-8s%s", "Group", tab);
	if(flags&D_SIZE)
		printf(sizstr[1], "Size", tab);
	if((flags&~(D_ATIME|D_MTIME|D_CTIME)) &&
	   (flags&(D_ATIME|D_MTIME|D_CTIME))) putchar(' ');
	if(flags&D_ATIME)
		printf("%-16s%s", "Access time", tab);
	if(flags&D_MTIME)
		printf("%-16s%s", "Modify time", tab);
	if(flags&D_CTIME)
		printf("%-16s%s", "Inode time", tab);
	if(flags)
		printf("%s\n", "File name");
}

triad(bits, special, code)
int bits, special;
char code;
{
	if(bits&4) putchar('r');
	else putchar('-');

	if(bits&2) putchar('w');
	else putchar('-');

	if(special) putchar(code);
	else if(bits&1) putchar('x');
	else putchar('-');
}

main(ac, av)
int ac;
char **av;
{
	int i, j;
	int exit_status = 0;
	int filed=0;

	for(i=1; i<ac; i++) {
		if(av[i][0]=='-')
			for(j=1; av[i][j]; j++)
				switch(av[i][j]) {
					case 'T':
						if(av[i][j+1])
							tab = &av[i][++j];
						else
							tab = &av[++i][j=0];
						while(av[i][j]) j++;
						j--;
						break;
					case 'N': flags = 0; break;
					case 'A': flags = -1; break;
					case 'D': dodir=!dodir; break;
					case 'd': flags ^= D_DEV; break;
					case 'i': flags ^= D_INO; break;
					case 'm': flags ^= D_MODE; break;
					case 'M': flags ^= D_SMODE; break;
					case 'l': flags ^= D_LINKS; break;
					case 'u': flags ^= D_UID; break;
					case 'U': flags ^= D_SUID; break;
					case 'g': flags ^= D_GID; break;
					case 'G': flags ^= D_SGID; break;
					case 'r': flags ^= D_RDEV; break;
					case 's': flags ^= D_SIZE; break;
					case 'a': flags ^= D_ATIME; break;
					case 't': flags ^= D_MTIME; break;
					case 'c': flags ^= D_CTIME; break;
					case 'h': dohead=!dohead; break;
					case 'H': header(); break;
					default:
						printf("Unknown option -%c.\n", av[i][j]);
						printf("\tUsage %s [-A|-N] [-diMmlUuGgrsatc] [-Ttab] [-Hh] [-D] [file]...\n", av[0]);
						break;
				}
		else {
			filed=1;
			if(!fdump(av[i])) {
				fperror(av[0], errname);
				exit_status=errno?errno:(-xerrno);
			}
		}
	}
	if(!filed)
		if(!fdump(".")) {
			fperror(av[0], errname);
			exit_status=errno;
		}

	if(dohead) header();
	exit(exit_status);
}

fperror(prog, file)
char *prog, *file;
{
	fprintf(stderr, "%s -- ", prog);
	if(errno)
		perror(file);
	else
		fprintf(stderr, "%s: %s\n", file, emesg[xerrno]);
}
-- 
	Peter da Silva (the mad Australian)
		UUCP: ...!shell!neuro1!{hyd-ptd,baylor,datafac}!peter
		MCI: PDASILVA; CIS: 70216,1076



More information about the Comp.sources.unix mailing list