/*
* DIR by Richard Conn
*
* Revision History --
* DIR Version 1.1 -- Modified by Frank Wancho
* Several changes made to provide operation with MORE
* DIR Version 1.0 by Richard Conn
*
* DIR is an enhanced directory display utility for UNIX.
* It produces a sorted listing of file names and sizes in two columns,
* and the files are sorted down the columns. If a file is a directory,
* its name is prefixed with a "D". File count and size totals are displayed
* at the bottom of the listing.
*
*/
/* Structure of a Directory Element as Stored for DIR */
struct dirnode {
char name[DIRSIZ]; /* Name of File */
int dir; /* Dir or Not? */
off_t size; /* Size in Bytes */
short mode; /* R/W/X */
struct dirnode *next; /* Ptr to Next File */
};
/* Global Environment */
struct environ {
int showhid; /* Show Hidden Files? */
int showrwx; /* Show Attributes? */
int filecnt; /* Number of Files in List */
off_t totsize; /* Sum of All File Sizes */
struct dirnode *first; /* Ptr to First Elt in List */
struct dirnode *last; /* Ptr to Last Elt in List */
};
FILE *out;
main(argc,argv)
char *argv[];
{
char buf[BUFSIZE];
struct environ env;
int i, first;
/* Init Environment */
env.first = NULL; /* No First Entry */
env.showhid = 0; /* No Hidden Files */
env.showrwx = 0; /* No R/W/X */
env.filecnt = 0; /* No Files */
env.totsize = 0; /* Accumulated File Size */
/* Build Linked List of DIR Elements */
if (argc == 1) build(".",&env,0); /* current dir */
else {
first = 1; /* first file is 1 */
if (*argv[1] == '-') {
first = 2; /* first file is 2 */
opts(argv[1],&env);
if (argc == 2) build(".",&env,0); /* curr dir */
}
for (i=first; i<argc; i++) build(argv[i],&env,0); /* ea */
}
/* Sort Linked List of DIR Elements */
sort(&env);
/* Shell Sort Directory Entries (See Pg 108 of K&R for Algorithm) */
sort(env)
struct environ *env;
{
int gap, i, j;
struct dirnode dir, *eltj, *eltjg, *elt();
/* Point to Nth (Starting at 0) Element in Linked List */
struct dirnode *elt(n,env)
int n;
struct environ *env;
{
struct dirnode *rover;
int i;
rover = env->first; /* pt to first element */
for (i=0; i<n; i++) rover = rover->next; /* adv thru list */
return (rover);
}
/* Build Linked List Structure Containing Directory Entries */
build(name,env,level)
char *name;
struct environ *env;
int level;
{
struct stat stbuf;
struct dirnode dir;
struct dirnode *calloc();
char *nameptr;
int i, ccnt;
/* Check for File Existence */
if (stat(name,&stbuf) == -1) {
fprintf(stderr,"Can't find %s\n", name);
return;
}
/* Check to See if File is a Directory */
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { /* we have a dir */
directory(name,env,level);
if (!level) return;
}
/* Store Entry in Memory */
if (env->first == NULL) { /* First Entry Processing */
env->first = calloc(1, sizeof(dir));
env->last = env->first;
}
else { /* Nth Entry Processing */
(*env->last).next = calloc(1, sizeof(dir));
env->last = (*env->last).next;
}
if (env->last == NULL) {
fprintf(stderr, "Dynamic Memory Overflow\n");
exit(0);
}
/* Store Entry Values */
env->filecnt++; /* Increment File Count */
(*env->last).next = NULL;
nameptr = name; /* Pt to first char of file name */
ccnt = strlen(name); /* Number of chars in file name */
for (i=0; i < ccnt; i++) /* Find Last Part of Name */
if (*name++ == '/') nameptr = name;
strcat((*env->last).name,nameptr); /* Save File Name */
(*env->last).size = stbuf.st_size; /* Save File Size */
(*env->last).mode = stbuf.st_mode; /* Save Mode Bits */
env->totsize += stbuf.st_size; /* Increment Total Sizes */
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) /* Set Dir Flag */
(*env->last).dir = 1;
else (*env->last).dir = 0;
}
/* Process All Entries in a Directory */
directory(name,env,level)
char *name;
struct environ *env;
int level;
{
struct direct dirbuf;
char *nbp, *nep;
char dirname[BUFSIZE];
char filename[DIRSIZ];
int i,fd;
if (level) return; /* don't recurse */
/* Build Name of Directory into DIRNAME */
nep = dirname;
nbp = name;
while (*nbp != '\0') *nep++ = *nbp++;
*nep = '\0'; /* terminate string */
if (nep+DIRSIZ+2 >= dirname+BUFSIZE) /* name too long */
return;
/* Log Into Directory */
if (chdir(dirname)) {
fprintf(stderr, "Directory %s Not Found\n", dirname);
return;
}
/* Open Directory File */
if ((fd = open(".",0)) == -1) return;
/* Read Through the Elements in the Directory */
while (read(fd, (char *)&dirbuf, sizeof(dirbuf)) > 0) {
if (dirbuf.d_ino == 0) /* slot not in use */
continue;
for (i=0, nep=filename; i<DIRSIZ; i++) /* build file name */
*nep++ = dirbuf.d_name[i];
*nep++ = '\0';
build(filename,env,level+1); /* reenter build for new file */
}
close(fd);
}