home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / unix_c / cpm / dir11.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-21  |  7.6 KB  |  303 lines

  1. /*
  2.  *  DIR by Richard Conn
  3.  *
  4.  * Revision History --
  5.  *  DIR Version 1.1 -- Modified by Frank Wancho
  6.  *        Several changes made to provide operation with MORE
  7.  *  DIR Version 1.0 by Richard Conn
  8.  *
  9.  *    DIR is an enhanced directory display utility for UNIX.
  10.  * It produces a sorted listing of file names and sizes in two columns,
  11.  * and the files are sorted down the columns.  If a file is a directory,
  12.  * its name is prefixed with a "D".  File count and size totals are displayed
  13.  * at the bottom of the listing.
  14.  *
  15.  */
  16.  
  17. /*  C Libraries  */
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/dir.h>
  21. #include <sys/stat.h>
  22. #define    BUFSIZE    256
  23.  
  24. /*  Structure of a Directory Element as Stored for DIR  */
  25. struct dirnode {
  26.     char name[DIRSIZ];    /* Name of File */
  27.     int dir;        /* Dir or Not? */
  28.     off_t size;        /* Size in Bytes */
  29.     short mode;        /* R/W/X */
  30.     struct dirnode *next;    /* Ptr to Next File */
  31. };
  32.  
  33. /*  Global Environment */
  34. struct environ {
  35.     int showhid;        /* Show Hidden Files? */
  36.     int showrwx;        /* Show Attributes? */
  37.     int filecnt;        /* Number of Files in List */
  38.     off_t totsize;        /* Sum of All File Sizes */
  39.     struct dirnode *first;    /* Ptr to First Elt in List */
  40.     struct dirnode *last;    /* Ptr to Last Elt in List */
  41. };
  42.  
  43. FILE    *out;
  44.  
  45. main(argc,argv)
  46. char *argv[];
  47. {
  48.     char buf[BUFSIZE];
  49.     struct environ env;
  50.     int i, first;
  51.  
  52.     /* Init Environment */
  53.     env.first = NULL;    /* No First Entry */
  54.     env.showhid = 0;    /* No Hidden Files */
  55.     env.showrwx = 0;    /* No R/W/X */
  56.     env.filecnt = 0;    /* No Files */
  57.     env.totsize = 0;    /* Accumulated File Size */
  58.  
  59.     /* Build Linked List of DIR Elements */
  60.     if (argc == 1) build(".",&env,0);    /* current dir */
  61.     else {
  62.         first = 1;                /* first file is 1 */
  63.         if (*argv[1] == '-') {
  64.             first = 2;            /* first file is 2 */
  65.             opts(argv[1],&env);
  66.             if (argc == 2) build(".",&env,0);    /* curr dir */
  67.         }
  68.         for (i=first; i<argc; i++) build(argv[i],&env,0);    /* ea */
  69.     }
  70.  
  71.     /* Sort Linked List of DIR Elements */
  72.     sort(&env);
  73.  
  74.     /* Display Results */
  75.     out=popen("more","w");
  76.     display(&env);
  77.     pclose(out);
  78. }
  79.  
  80. /*  Process Command Options  */
  81. opts(cmdstr,env)
  82. char *cmdstr;
  83. struct environ *env;
  84. {
  85.     while (*cmdstr != '\0')
  86.         switch (*cmdstr++) {
  87.         case 'A' :
  88.         case 'a' :
  89.             env->showrwx = 1;    /* show file attributes */
  90.             break;
  91.         case 'H' :
  92.         case 'h' :
  93.             env->showhid = 1;    /* show hidden files */
  94.         default :
  95.             break;
  96.         }
  97. }
  98.  
  99. /*  Display Entries in Linked List  */
  100. display(env)
  101. struct environ *env;
  102. {
  103.     struct dirnode *lptr, *rptr, *elt();
  104.     char *fname;
  105.     int i;
  106.  
  107.     if (env->filecnt > 0) {
  108.         fprintf(out,"  -- Filename --  - Size -");
  109.         if (env->showrwx) fprintf(out,"  Atr");
  110.     }
  111.     if (env->filecnt > 1) {
  112.         fprintf(out,"      -- Filename --  - Size -");
  113.         if (env->showrwx) fprintf(out,"  Atr");
  114.     }
  115.     fprintf(out,"\n");
  116.     lptr = elt(0,env);    /* Pt to first element in left col */
  117.     rptr = elt(env->filecnt%2 ? env->filecnt/2+1 : env->filecnt/2, env);
  118.     for (i=0; i < env->filecnt/2; i++) {
  119.         prelt(lptr,env);    /* Print Left Element */
  120.         prelt(rptr,env);    /* Print Right Element */
  121.         fprintf(out,"\n");    /* New Line */
  122.         lptr = lptr->next;    /* Pt to next */
  123.         rptr = rptr->next;
  124.     }
  125.     if (env->filecnt%2) {
  126.         prelt(lptr,env);    /* Print Odd Element */
  127.         fprintf(out,"\n");
  128.     }
  129.     fprintf(out,"           -- %d Entries Displayed, %ld Bytes --\n",
  130.     env->filecnt, env->totsize);
  131. }
  132.  
  133. /*  Print Element Pointed To  */
  134. prelt(ptr,env)
  135. struct dirnode *ptr;
  136. struct environ *env;
  137. {
  138.     char *fname;
  139.     int j;
  140.  
  141.     if (ptr->dir) fprintf(out,"D ");        /* Print Dir Flag */
  142.     else fprintf(out,"  ");
  143.     fname = ptr->name;
  144.     for (j=0; j < DIRSIZ; j++)            /* Print File Name */
  145.         if (*fname == '\0') fputc(' ',out);
  146.         else fputc(*fname++,out);
  147.     fprintf(out,"  %8ld", ptr->size);        /* Print File Size */
  148.     if (env->showrwx) fprintf(out,"  %c%c%c",    /* Print RWX Flags */
  149.     (ptr->mode & S_IREAD)  ? 'r' : '-',
  150.     (ptr->mode & S_IWRITE) ? 'w' : '-',
  151.     (ptr->mode & S_IEXEC)  ? 'x' : '-');
  152.     fprintf(out,"    ");
  153. }
  154.  
  155. /*  Shell Sort Directory Entries (See Pg 108 of K&R for Algorithm)  */
  156. sort(env)
  157. struct environ *env;
  158. {
  159.     int gap, i, j;
  160.     struct dirnode dir, *eltj, *eltjg, *elt();
  161.  
  162.     for (gap = env->filecnt/2; gap > 0; gap /= 2)
  163.         for (i = gap; i < env->filecnt; i++)
  164.             for (j = i-gap; j >= 0; j -= gap) {
  165.                 eltj = elt(j,env);    /* pt to elt j */
  166.                 eltjg = elt(j+gap,env);    /* pt to elt j+gap */
  167.                 if (strcmp(eltj->name,eltjg->name) <= 0)
  168.                     break;
  169.                 /* temp = v[j] */
  170.                 *dir.name = '\0';    /* clear str */
  171.                 strcat(dir.name,eltj->name);
  172.                 dir.dir = eltj->dir;
  173.                 dir.size = eltj->size;
  174.                 dir.mode = eltj->mode;
  175.                 /* v[j] = v[j+gap] */
  176.                 *eltj->name = '\0';    /* clear str */
  177.                 strcat(eltj->name,eltjg->name);
  178.                 eltj->dir = eltjg->dir;
  179.                 eltj->size = eltjg->size;
  180.                 eltj->mode = eltjg->mode;
  181.                 /* v[j+gap] = temp */
  182.                 *eltjg->name = '\0';    /* clear str */
  183.                 strcat(eltjg->name,dir.name);
  184.                 eltjg->dir = dir.dir;
  185.                 eltjg->size = dir.size;
  186.                 eltjg->mode = dir.mode;
  187.             }
  188. }
  189.  
  190. /* Point to Nth (Starting at 0) Element in Linked List */
  191. struct dirnode *elt(n,env)
  192. int n;
  193. struct environ *env;
  194. {
  195.     struct dirnode *rover;
  196.     int i;
  197.  
  198.     rover = env->first;    /* pt to first element */
  199.     for (i=0; i<n; i++) rover = rover->next;    /* adv thru list */
  200.     return (rover);
  201. }
  202.  
  203. /* Build Linked List Structure Containing Directory Entries */
  204. build(name,env,level)
  205. char *name;
  206. struct environ *env;
  207. int level;
  208. {
  209.     struct stat stbuf;
  210.     struct dirnode dir;
  211.     struct dirnode *calloc();
  212.     char *nameptr;
  213.     int i, ccnt;
  214.  
  215.     /* Check for File Existence */
  216.     if (stat(name,&stbuf) == -1) {
  217.         fprintf(stderr,"Can't find %s\n", name);
  218.         return;
  219.     }
  220.  
  221.     /* Check to See if File is a Directory */
  222.     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {    /* we have a dir */
  223.         directory(name,env,level);
  224.         if (!level) return;
  225.     }
  226.  
  227.     /*  Check Hidden Entries */
  228.     if (*name == '.' && !(env->showhid)) return;
  229.  
  230.     /*  Store Entry in Memory  */
  231.     if (env->first == NULL) {    /* First Entry Processing */
  232.         env->first = calloc(1, sizeof(dir));
  233.         env->last = env->first;
  234.     }
  235.     else {                /* Nth Entry Processing */
  236.         (*env->last).next = calloc(1, sizeof(dir));
  237.         env->last = (*env->last).next;
  238.     }
  239.     if (env->last == NULL) {
  240.         fprintf(stderr, "Dynamic Memory Overflow\n");
  241.         exit(0);
  242.     }
  243.  
  244.     /* Store Entry Values */
  245.     env->filecnt++;        /* Increment File Count */
  246.     (*env->last).next = NULL;
  247.     nameptr = name;        /* Pt to first char of file name */
  248.     ccnt = strlen(name);    /* Number of chars in file name */
  249.     for (i=0; i < ccnt; i++)    /* Find Last Part of Name */
  250.         if (*name++ == '/') nameptr = name;
  251.     strcat((*env->last).name,nameptr);    /* Save File Name */
  252.     (*env->last).size = stbuf.st_size;    /* Save File Size */
  253.     (*env->last).mode = stbuf.st_mode;    /* Save Mode Bits */
  254.     env->totsize += stbuf.st_size;        /* Increment Total Sizes */
  255.     if ((stbuf.st_mode & S_IFMT) == S_IFDIR)     /* Set Dir Flag */
  256.         (*env->last).dir = 1;
  257.     else (*env->last).dir = 0;
  258. }
  259.  
  260. /* Process All Entries in a Directory */
  261. directory(name,env,level)
  262. char *name;
  263. struct environ *env;
  264. int level;
  265. {
  266.     struct direct dirbuf;
  267.     char *nbp, *nep;
  268.     char dirname[BUFSIZE];
  269.     char filename[DIRSIZ];
  270.     int i,fd;
  271.  
  272.     if (level) return;    /* don't recurse */
  273.  
  274.     /* Build Name of Directory into DIRNAME */
  275.     nep = dirname;
  276.     nbp = name;
  277.     while (*nbp != '\0') *nep++ = *nbp++;
  278.     *nep = '\0';    /* terminate string */
  279.     if (nep+DIRSIZ+2 >= dirname+BUFSIZE)    /* name too long */
  280.         return;
  281.  
  282.     /* Log Into Directory */
  283.     if (chdir(dirname)) {
  284.         fprintf(stderr, "Directory %s Not Found\n", dirname);
  285.         return;
  286.     }
  287.  
  288.     /* Open Directory File */
  289.     if ((fd = open(".",0)) == -1) return;
  290.  
  291.     /* Read Through the Elements in the Directory */
  292.     while (read(fd, (char *)&dirbuf, sizeof(dirbuf)) > 0) {
  293.         if (dirbuf.d_ino == 0)    /* slot not in use */
  294.             continue;
  295.         for (i=0, nep=filename; i<DIRSIZ; i++)    /* build file name */
  296.             *nep++ = dirbuf.d_name[i];
  297.         *nep++ = '\0';
  298.         build(filename,env,level+1);    /* reenter build for new file */
  299.     }
  300.     close(fd);
  301. }
  302.  
  303.