home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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.
- *
- */
-
- /* C Libraries */
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/dir.h>
- #include <sys/stat.h>
- #define BUFSIZE 256
-
- /* 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);
-
- /* Display Results */
- out=popen("more","w");
- display(&env);
- pclose(out);
- }
-
- /* Process Command Options */
- opts(cmdstr,env)
- char *cmdstr;
- struct environ *env;
- {
- while (*cmdstr != '\0')
- switch (*cmdstr++) {
- case 'A' :
- case 'a' :
- env->showrwx = 1; /* show file attributes */
- break;
- case 'H' :
- case 'h' :
- env->showhid = 1; /* show hidden files */
- default :
- break;
- }
- }
-
- /* Display Entries in Linked List */
- display(env)
- struct environ *env;
- {
- struct dirnode *lptr, *rptr, *elt();
- char *fname;
- int i;
-
- if (env->filecnt > 0) {
- fprintf(out," -- Filename -- - Size -");
- if (env->showrwx) fprintf(out," Atr");
- }
- if (env->filecnt > 1) {
- fprintf(out," -- Filename -- - Size -");
- if (env->showrwx) fprintf(out," Atr");
- }
- fprintf(out,"\n");
- lptr = elt(0,env); /* Pt to first element in left col */
- rptr = elt(env->filecnt%2 ? env->filecnt/2+1 : env->filecnt/2, env);
- for (i=0; i < env->filecnt/2; i++) {
- prelt(lptr,env); /* Print Left Element */
- prelt(rptr,env); /* Print Right Element */
- fprintf(out,"\n"); /* New Line */
- lptr = lptr->next; /* Pt to next */
- rptr = rptr->next;
- }
- if (env->filecnt%2) {
- prelt(lptr,env); /* Print Odd Element */
- fprintf(out,"\n");
- }
- fprintf(out," -- %d Entries Displayed, %ld Bytes --\n",
- env->filecnt, env->totsize);
- }
-
- /* Print Element Pointed To */
- prelt(ptr,env)
- struct dirnode *ptr;
- struct environ *env;
- {
- char *fname;
- int j;
-
- if (ptr->dir) fprintf(out,"D "); /* Print Dir Flag */
- else fprintf(out," ");
- fname = ptr->name;
- for (j=0; j < DIRSIZ; j++) /* Print File Name */
- if (*fname == '\0') fputc(' ',out);
- else fputc(*fname++,out);
- fprintf(out," %8ld", ptr->size); /* Print File Size */
- if (env->showrwx) fprintf(out," %c%c%c", /* Print RWX Flags */
- (ptr->mode & S_IREAD) ? 'r' : '-',
- (ptr->mode & S_IWRITE) ? 'w' : '-',
- (ptr->mode & S_IEXEC) ? 'x' : '-');
- fprintf(out," ");
- }
-
- /* 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();
-
- for (gap = env->filecnt/2; gap > 0; gap /= 2)
- for (i = gap; i < env->filecnt; i++)
- for (j = i-gap; j >= 0; j -= gap) {
- eltj = elt(j,env); /* pt to elt j */
- eltjg = elt(j+gap,env); /* pt to elt j+gap */
- if (strcmp(eltj->name,eltjg->name) <= 0)
- break;
- /* temp = v[j] */
- *dir.name = '\0'; /* clear str */
- strcat(dir.name,eltj->name);
- dir.dir = eltj->dir;
- dir.size = eltj->size;
- dir.mode = eltj->mode;
- /* v[j] = v[j+gap] */
- *eltj->name = '\0'; /* clear str */
- strcat(eltj->name,eltjg->name);
- eltj->dir = eltjg->dir;
- eltj->size = eltjg->size;
- eltj->mode = eltjg->mode;
- /* v[j+gap] = temp */
- *eltjg->name = '\0'; /* clear str */
- strcat(eltjg->name,dir.name);
- eltjg->dir = dir.dir;
- eltjg->size = dir.size;
- eltjg->mode = dir.mode;
- }
- }
-
- /* 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;
- }
-
- /* Check Hidden Entries */
- if (*name == '.' && !(env->showhid)) 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);
- }
-
-