home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / dirutl / ks_ls.arc / LS.C next >
C/C++ Source or Header  |  1988-10-04  |  23KB  |  1,033 lines

  1. /*
  2.  * public domain implementation of the BSD UNIX(c) `ls' routine.
  3.  *
  4.  * written by Kevin Sweet. entered into the public domain 1988.
  5.  *
  6.  * compile with: tcc -ms -f- -Z -O -G -k -N ls 
  7.  *
  8.  */
  9.  
  10. #include <alloc.h>
  11. #include <ctype.h>
  12. #include <dir.h>
  13. #include <dos.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/stat.h>
  18. #include <time.h>
  19. #define FA_EXEC        0x40
  20.  
  21. #define DOT_AL        /* if defined, the entries '.' and '..' are
  22.              * only displayed when both the 'a' and the 'l'
  23.              * options are selected */
  24. #define SIZE_CL        /* display file size in clusters rather than
  25.              * "kilobytes" */
  26.  
  27. struct datum {
  28.     int    attrib;
  29.     long    sizeb;
  30.     time_t    date;
  31.     char     pname[MAXPATH];
  32. };
  33. #define fname(a)    (strrchr((a)->pname, '\\')+1)
  34. #ifdef SIZE_CL
  35. #define sizek(a)    (((a)->sizeb+cluster_size-1)/cluster_size)
  36. #else
  37. #define sizek(a)    (((a)->sizeb+1023L)/1024L)
  38. #endif
  39.  
  40. struct flags {
  41.     short f_all;
  42.     short f_column;
  43.     short f_directory;
  44.     short f_long;
  45.     short f_kilobyte;
  46.     short f_nosort;
  47.     short f_pwd;
  48.     short f_recursive;
  49.     short f_type;
  50.     short f_zoo;
  51.     short s_reverse;
  52.     short s_size;
  53.     short s_time;
  54. };
  55.  
  56. extern char    *main_cwd;
  57. extern int    main_dev;
  58. extern int    main_year;
  59. #ifdef SIZE_CL
  60. extern long    cluster_size;
  61. #endif
  62. extern short    FA_FILES;
  63. extern unsigned onceover;
  64. extern struct flags flags;
  65.  
  66. int    ls(int argc, char **argv);
  67.  
  68. int    parse_file(char *path, char *d, char *p, char *f, char *e);
  69. #define getwd() getcwd((char *) NULL, MAXPATH*sizeof(char))
  70.  
  71. char    *main_cwd;
  72. int    main_dev;
  73. int    main_year;
  74. short    FA_FILES;
  75. unsigned onceover;
  76. struct flags flags;
  77.  
  78. static int    break_func(void);
  79. static int    getarg(char c, char off);
  80. static void    gethelp();
  81.  
  82. #define new_entry(a,e) { \
  83.     *((a)) = (char *) malloc((strlen((e))+1)*sizeof(char)); \
  84.     strcpy(*(((a)++)), (e)); \
  85. }
  86. #define last_entry(c,a) if ((c)) { \
  87.     *((a)) = (char *) NULL; \
  88.     (a) -= (c); \
  89. }
  90. #define alloc_error() { \
  91.     fprintf(stderr, "insufficient memory"); \
  92.     exit(1); \
  93. }
  94.  
  95. main(int argc, char **argv)
  96. {
  97.     int nfiles;
  98.     char **files;
  99.     int ndirs;
  100.     char **dirs;
  101.     char *cp;
  102.     long ltime;
  103.     char d[MAXDRIVE], p[MAXDIR], f[MAXFILE], e[MAXEXT];
  104.     char arg[MAXPATH], path[MAXPATH];
  105.     int i, wild;
  106.     struct ffblk ffblk;
  107.  
  108.     main_cwd = getwd();
  109.     main_dev = getdisk();
  110.     ctrlbrk(break_func);
  111.  
  112.     time(<ime);
  113.     daylight = 0;            /* account for daylight savings time */
  114.     main_year = atoi(asctime(localtime(<ime))+20);
  115.  
  116.     onceover = 0;
  117.     FA_FILES = FA_DIREC;
  118.     flags.f_all = 0;
  119.     flags.f_column = 1;
  120.     flags.f_long = 0;
  121.     flags.f_kilobyte = 0;
  122.     flags.f_nosort = 0;
  123.     flags.f_pwd = 0;
  124.     flags.f_recursive = 0;
  125.     flags.f_type = 0;
  126.     flags.f_zoo = 0;
  127.     flags.s_reverse = 0;
  128.     flags.s_size = 0;
  129.     flags.s_time = 0;
  130.  
  131.     /* find options
  132.      * since the selected files will depend on flags.f_directory
  133.      */
  134.     for (cp = getenv("LS"); *cp; ++cp) getarg(*cp, *(cp+1));
  135.  
  136.     for (++argv; *argv; ++argv)
  137.     switch (**argv) {
  138.         case '-':
  139.             for (cp = *argv, ++cp; *cp; ++cp)
  140.                 if (getarg(*cp, *(cp+1)))
  141.                     exit(0);
  142.             break;
  143.         default:
  144.     }
  145.     argv -= argc;
  146.  
  147.     /* find the number of selected files
  148.      * find the number first for space saving
  149.      */
  150.     ndirs = nfiles = 0;
  151.     for (++argv; *argv; ++argv)
  152.     switch (**argv) {
  153.         case '-':
  154.             break;
  155.         default:
  156.             parse_file(*argv, d, p, f, e);
  157.             sprintf(arg, "%s%s%s%s", d, p, f, e);
  158.             wild = findfirst(arg, &ffblk,
  159.                 FA_DIREC | FA_HIDDEN | FA_SYSTEM);
  160.             if (wild) {
  161.                 nfiles++;
  162.                 continue;
  163.             }
  164.             while (!wild) {
  165.                 if (flags.f_directory) {
  166.                     nfiles++;
  167.                 } else if (ffblk.ff_attrib & FA_DIREC) {
  168.                     if (*ffblk.ff_name != '.')
  169.                     ndirs++;
  170.                 } else {
  171.                     nfiles++;
  172.                 }
  173.                 wild = findnext(&ffblk);
  174.             }
  175.     }
  176.     argv -= argc;
  177.  
  178.     if (!nfiles && !ndirs) {
  179.         ndirs = 1;
  180.         dirs = (char **) calloc(2, sizeof(char *));
  181.         if (!dirs) alloc_error();
  182.         getcwd(path, MAXPATH*sizeof(char));
  183.         if (path[3]) strcat(path, "\\.");
  184.         *dirs = path;
  185.         *(dirs+1) = (char *) NULL;
  186.     } else {
  187.         if (nfiles) {
  188.             files = (char **) calloc((nfiles+1),
  189.                 sizeof(char *));
  190.             if (!files) alloc_error();
  191.         }
  192.         if (ndirs) {
  193.             dirs = (char **) calloc((ndirs+1),
  194.                 sizeof(char *));
  195.             if (!dirs) alloc_error();
  196.         }
  197.  
  198.         /* save the selected files
  199.          */
  200.         for (++argv; *argv; ++argv) switch (**argv) {
  201.         case '-':
  202.             break;
  203.         default:
  204.             parse_file(*argv, d, p, f, e);
  205.             sprintf(arg, "%s%s%s%s", d, p, f, e);
  206.             wild = findfirst(arg, &ffblk,
  207.                 FA_DIREC | FA_HIDDEN | FA_SYSTEM);
  208.             if (wild) {
  209.                 new_entry(files, arg);
  210.                 continue;
  211.             }
  212.             sprintf(path, "%s%s", d, p);
  213.             if (!strcmp(path, arg)) {
  214.                 argc = 0;
  215.                 if (f[1]) strcat(path, "\\.");
  216.             } else {
  217.                 argc = 1;
  218.                 if (!f[0]) strcat(path, "\\");
  219.             }
  220.             while (!wild) {
  221.                 if (argc)
  222.                     sprintf(arg, "%s%s", path,
  223.                         ffblk.ff_name);
  224.                 else
  225.                     strcpy(arg, path);
  226.                 if (flags.f_directory) {
  227.                     new_entry(files, arg);
  228.                 } else if (ffblk.ff_attrib & FA_DIREC) {
  229.                     if (*ffblk.ff_name != '.')
  230.                     new_entry(dirs, arg);
  231.                 } else {
  232.                     new_entry(files, arg);
  233.                 }
  234.                 wild = findnext(&ffblk);
  235.             }
  236.         }
  237.         last_entry(ndirs, dirs);
  238.         last_entry(nfiles, files);
  239.     }
  240.  
  241.     if (flags.f_all) FA_FILES |= FA_HIDDEN | FA_SYSTEM;
  242.     wild = ls(nfiles, files);
  243.     if (nfiles) free(files);
  244.  
  245.     for (i = 0; i < ndirs; ++i, ++dirs) {
  246.         if (wild++) {
  247.             if (!flags.f_zoo) printf("\n\n");
  248.             onceover = 1;
  249.         } else if (ndirs > 1) {
  250.             onceover = 1;
  251.         }
  252.         ls(1, dirs);
  253.     }
  254.  
  255.     break_func();
  256.     exit(0);
  257. }
  258.  
  259. static
  260. int
  261. break_func(void)
  262. {
  263.     setdisk(main_dev);
  264.     chdir(main_cwd);
  265.     exit(0);
  266. }
  267.  
  268. static
  269. int
  270. getarg(char c, char off)
  271. {
  272.     switch (c) {
  273.         case '1':
  274.             flags.f_column = 0;
  275.             if (off == '-') flags.f_column = 1;
  276.             return(0);
  277.         case 'C':
  278.             if (!flags.f_long)
  279.                 flags.f_column = 1;
  280.             if (off == '-')
  281.                 flags.f_column = 0;
  282.             return(0);
  283.         case 'F':
  284.             flags.f_type = 1;
  285.             if (off == '-') flags.f_type = 0;
  286.             return(0);
  287.         case 'P':
  288.             flags.f_pwd = 1;
  289.             if (off == '-') flags.f_pwd = 0;
  290.             return(0);
  291.         case 'R':
  292.             flags.f_recursive = 1;
  293.             if (off == '-') flags.f_recursive = 0;
  294.             return(0);
  295.         case 'S':
  296.             flags.s_size = 1;
  297.             if (off == '-') flags.s_size = 0;
  298.             else flags.s_time = 0;
  299.             return(0);
  300.         case 'Z':
  301.             flags.f_zoo = 1;
  302.             if (off == '-') flags.f_zoo = 0;
  303.             return(0);
  304.         case 'a':
  305.             flags.f_all = 1;
  306.             if (off == '-') flags.f_all = 0;
  307.             return(0);
  308.         case 'd':
  309.             flags.f_directory = 1;
  310.             if (off == '-') flags.f_directory = 0;
  311.             return(0);
  312.         case 'f':
  313.             flags.f_nosort = 1;
  314.             if (off == '-') flags.f_nosort = 0;
  315.             return(0);
  316.         case 'l':
  317.             flags.f_long = 1;
  318.             if (off == '-') flags.f_long = 0;
  319.             else flags.f_column = 0;
  320.             return(0);
  321.         case 'r':
  322.             flags.s_reverse = 1;
  323.             if (off == '-') flags.s_reverse = 0;
  324.             return(0);
  325.         case 's':
  326.             flags.f_kilobyte = 1;
  327.             if (off == '-') flags.f_kilobyte = 0;
  328.             return(0);
  329.         case 't':
  330.             flags.s_time = 1;
  331.             if (off == '-') flags.s_time = 0;
  332.             else flags.s_size = 0;
  333.             return(0);
  334.         case 'H':
  335.         case 'h':
  336.         case '?':
  337.             gethelp();
  338.             return(1);
  339.         default:
  340.             return(0);
  341.     }
  342. }
  343.  
  344. static
  345. void
  346. gethelp()
  347. {
  348.     printf("ls - list the contents of a directory");
  349.     printf(" in alphabetical order\n");
  350.     printf("\nusage:\tls [-1CFPRSZadflrst] name ...\n\n");
  351.     printf("options:\n");
  352.     printf("-1\tlist in one column format\n");
  353.     printf("-C\tlist in multi-column format (default)\n");
  354.     printf("-F\tdirectories are marked with a trailing '\\', ");
  355.     printf("system files are marked\n");
  356.     printf("\twith a trailing '@' and executable files are ");
  357.     printf("marked with a trailing '*'\n");
  358.     printf("-P\tprint the directory name before listing\n");
  359.     printf("-R\trecursively list subdirectories\n");
  360. #ifdef SIZE_CL
  361.     printf("-S\tsort by file size in bytes (cluster size if ");
  362.     printf("option 's' is selected)\n");
  363. #else
  364.     printf("-S\tsort by file size in bytes (size in kilobytes if ");
  365.     printf("option 's' is selected)\n");
  366. #endif
  367.     printf("-Z\tlist full pathnames in one column for input to ");
  368.     printf("Zoo\n");
  369.     printf("-a\tlist all entries including hidden and system ");
  370.     printf("files\n");
  371.     printf("-d\tlist directories as if they were a normal file\n");
  372.     printf("-f\tdo not sort (list in the order files appear");
  373.     printf(" in the directory)\n");
  374. #ifdef SIZE_CL
  375.     printf("-l\tlist in long format ([size in clusters,] mode, ");
  376. #else
  377.     printf("-l\tlist in long format ([size in kilobytes,] mode, ");
  378. #endif
  379.     printf("size, date, name)\n");
  380.     printf("-r\treverse the order of the selected sort\n");
  381. #ifdef SIZE_CL
  382.     printf("-s\tlist the file size in clusters\n");
  383. #else
  384.     printf("-s\tlist the file size in kilobytes\n");
  385. #endif
  386.     printf("-t\tsort by time\n");
  387.     printf("\nls parses the environment variable LS for options ");
  388.     printf("before parsing the command\n");
  389.     printf("line. options may be turned off with a trailing '-'");
  390.     printf(" (i.e., ls -1F-s turns on\n");
  391.     printf("the '1' and 's' options and turns off the 'F' ");
  392.     printf("option).");
  393. }
  394.  
  395. #ifdef SIZE_CL
  396. long    cluster_size;
  397. #endif
  398.  
  399. int    sort_datum(void *a, void *b);
  400. void    display_entries(int icd, int nitems, struct datum *items);
  401.  
  402. int
  403. ls(int argc, char **argv)
  404. {
  405.     int i;
  406.     int nitems = 0;
  407.     struct datum *items = (struct datum *) NULL;
  408.     char **fargv = (char **) calloc(2, sizeof(char *));
  409.  
  410.     char *argv_dir, *cp;
  411.     char ls_d[MAXDRIVE], ls_p[MAXDIR], ls_f[MAXFILE], ls_e[MAXEXT];
  412.     char ls_pwd[MAXDRIVE+MAXDIR], ls_wd[MAXPATH];
  413.     int argv_drive, icd, wild;
  414.     struct fatinfo fi;
  415.     struct ffblk ffblk;
  416.     struct stat sbuf;
  417.  
  418.     if (!argc) return(0);
  419.     if (!fargv) return(0);
  420.  
  421.     argv_drive = getdisk();
  422.     parse_file(*argv, ls_d, ls_p, ls_f, ls_e);
  423.     setdisk((int) (ls_d[0] - 'A'));
  424.     sprintf(ls_pwd, "%s%s", ls_d, ls_p);
  425.     argv_dir = getwd();
  426.     icd = 0;
  427.     if (!flags.f_directory)
  428.     if (argc == 1 && !ls_f[0]) {
  429.         icd = 1;
  430.         chdir(ls_pwd);
  431.     }
  432.  
  433.     /* run through the loop once for speed and (mostly) size savings
  434.      */
  435.     nitems = 0;
  436.     for (i = 0; i < argc; ++i, ++argv)
  437.     {
  438.         if (icd)
  439.             wild = findfirst("*.*", &ffblk, FA_FILES);
  440.         else
  441.             wild = findfirst(*argv, &ffblk, FA_FILES);
  442.         while (!wild) {
  443.             if (flags.f_directory) {
  444.                 if (ffblk.ff_attrib & ~FA_DIREC) {
  445.                     wild = findnext(&ffblk);
  446.                     continue;
  447.                 }
  448.             } else {
  449.                 if (*ffblk.ff_name == '.')
  450. #ifdef DOT_AL
  451.                 if (onceover ||
  452.                     !(flags.f_all && flags.f_long))
  453. #else
  454.                 if (onceover || !flags.f_all)
  455. #endif
  456.                 {
  457.                     wild = findnext(&ffblk);
  458.                     continue;
  459.                 }
  460.             }
  461.             nitems++;
  462.             wild = findnext(&ffblk);
  463.         } /* while */
  464.     } /* for */
  465.     argv -= argc;
  466.  
  467.     if (!nitems) {
  468.         if (!flags.f_zoo && onceover) printf("%s:", ls_pwd);
  469.         return(0);
  470.     }
  471.  
  472.     items = (struct datum *) calloc((nitems+1),
  473.         sizeof(struct datum));
  474.     if (!items) {
  475.         if (onceover) fputc('\n', stderr);
  476.         fprintf(stderr, "insufficient memory ");
  477.         fprintf(stderr, "for %d entr%s", nitems,
  478.             nitems > 1 ? "ies" : "y");
  479.         return(1);
  480.     }
  481.  
  482.     for (i = 0; i < argc; ++i, ++argv)
  483.     {
  484.         if (icd) {
  485.             wild = findfirst("*.*", &ffblk, FA_FILES);
  486.             getcwd(ls_wd, MAXPATH*sizeof(char));
  487.             parse_file(ls_wd, ls_d, ls_p, ls_f, ls_e);
  488.             if (ls_p[1])
  489.                 sprintf(ls_wd, "%s%s\\", ls_d, ls_p);
  490.             else
  491.                 sprintf(ls_wd, "%s%s", ls_d, ls_p);
  492.         } else
  493.         {
  494.             wild = findfirst(*argv, &ffblk, FA_FILES);
  495.             ls_d[0] = **argv;
  496.             ls_wd[0] = '\0';
  497.         }
  498.  
  499. #ifdef SIZE_CL
  500.         getfat((int) (ls_d[0] - 'A' + 1), &fi);
  501.         cluster_size = (long) (fi.fi_sclus * fi.fi_bysec);
  502. #endif
  503.  
  504.         while (!wild) {
  505.             if (flags.f_directory) {
  506.                 if (ffblk.ff_attrib & ~FA_DIREC) {
  507.                     wild = findnext(&ffblk);
  508.                     continue;
  509.                 }
  510.             } else {
  511.                 if (*ffblk.ff_name == '.')
  512. #ifdef DOT_AL
  513.                 if (onceover ||
  514.                     !(flags.f_all && flags.f_long))
  515. #else
  516.                 if (onceover || !flags.f_all)
  517. #endif
  518.                 {
  519.                     wild = findnext(&ffblk);
  520.                     continue;
  521.                 }
  522.             }
  523.  
  524.             if (ls_wd[0])
  525.                 sprintf(items->pname, "%s%s", ls_wd,
  526.                     ffblk.ff_name);
  527.             else
  528.                 sprintf(items->pname, "%s", *argv);
  529.  
  530.             stat(items->pname, &sbuf);
  531.             items->date = (time_t) sbuf.st_atime;
  532.  
  533.             items->sizeb = ffblk.ff_fsize;
  534.  
  535.             items->attrib = (int) ffblk.ff_attrib;
  536.             if (cp = strrchr(ffblk.ff_name, '.')) {
  537.                 if (!strcmp(++cp, "EXE"))
  538.                     items->attrib |= FA_EXEC;
  539.                 else if (!strcmp(cp, "COM"))
  540.                     items->attrib |= FA_EXEC;
  541.                 else if (!strcmp(cp, "BAT"))
  542.                     items->attrib |= FA_EXEC;
  543.                 if (ffblk.ff_attrib & FA_SYSTEM)
  544.                     items->attrib &= ~FA_EXEC;
  545.             }
  546.  
  547.             items++;
  548.             wild = findnext(&ffblk);
  549.         } /* while */
  550.     } /* for */
  551.     argv -= argc;
  552.     items -= nitems;
  553.  
  554.     chdir(argv_dir);
  555.     free(argv_dir);
  556.     setdisk(argv_drive);
  557.  
  558.     if (!flags.f_nosort)
  559.         qsort(items, nitems, sizeof(struct datum), sort_datum);
  560.  
  561.     if (!flags.f_zoo) {
  562.         if (onceover++) printf("%s:\n", ls_pwd);
  563.         else if (flags.f_pwd) printf("%s\n", ls_pwd);
  564.         display_entries(icd, nitems, items);
  565.     } else {
  566.         for (i = 0 ; i < nitems ; ++i, ++items)
  567.         if (items->attrib & ~FA_DIREC)
  568.         printf("%s\n", items->pname);
  569.         items -= nitems;
  570.     }
  571.  
  572.     if (!flags.f_directory)
  573.     if (flags.f_recursive) {
  574.         for (i = 0; i < nitems; ++i, ++items) {
  575. /*
  576.             if (items->attrib & ~FA_DIREC) continue;
  577. */
  578.             if (!(items->attrib & FA_DIREC)) continue;
  579. /* */
  580.             if (*fname(items) == '.') continue;
  581.             if (!flags.f_zoo) printf("\n\n");
  582.             *fargv = items->pname;
  583.             *(fargv+1) = (char *) NULL;
  584.             ls(1, fargv);
  585.         }
  586.         items -= nitems;
  587.     }
  588.  
  589.     free(fargv);
  590.     free(items);
  591.     return(1);
  592. }
  593.  
  594. int
  595. sort_datum(void *ea, void *eb)
  596. {
  597.     register struct datum *a = (struct datum *) ea;
  598.     register struct datum *b = (struct datum *) eb;
  599.     register int i;
  600.     register long as, bs;
  601.     register size_t al, bl;
  602.     register char *ac = a->pname;
  603.     register char *bc = b->pname;
  604.  
  605.     al = strlen(ac);
  606.     bl = strlen(bc);
  607.     if (flags.s_time) {
  608.         as = (long) a->date;
  609.         bs = (long) b->date;
  610.         if (as - bs > 0L) i = -1;
  611.         else if (as - bs < 0L) i = 1;
  612.         else i = strncmp(ac, bc, al > bl ? bl : al);
  613.     } else if (flags.s_size) {
  614.         if (flags.f_kilobyte) {
  615.             as = sizek(a);
  616.             bs = sizek(b);
  617.         } else {
  618.             as = a->sizeb;
  619.             bs = b->sizeb;
  620.         }
  621.         if (as - bs < 0L) i = -1;
  622.         else if (as - bs > 0L) i = 1;
  623.         else i = strncmp(ac, bc, al > bl ? bl : al);
  624.     } else {
  625.         i = strncmp(ac, bc, al > bl ? bl : al);
  626.     }
  627.     if (flags.s_reverse) i *= -1;
  628.  
  629.     if (i)
  630.         return(i);
  631.     else {
  632.         if (flags.s_reverse && !flags.s_time && !flags.s_size)
  633.             return( al < bl ? 1 : -1 );
  634.         else
  635.             return( al > bl ? 1 : -1 );
  636.     }
  637. }
  638.  
  639. static int    display_largest;
  640. static int    display_length;
  641. static short    display_column;
  642. static short    display_pname;
  643.  
  644. static void    display_entry(struct datum *sd);
  645.  
  646. void
  647. display_entries(int icd, int nitems, struct datum *items)
  648. {
  649.     long    display_total;
  650.  
  651.     char *cp, pn1[MAXPATH], pn2[MAXPATH];
  652.     int cnt, extra, i, j, loops, maybe, rows, total;
  653.     int *pos;
  654.     int lenmod, maxlen;
  655.  
  656.     if (!nitems) {
  657.         if (flags.f_kilobyte || (icd && flags.f_long))
  658.         printf("total 0\n");
  659.         return;
  660.     }
  661.  
  662.     display_pname = 0;
  663.     strcpy(pn1, items->pname);
  664.     cp = strrchr(pn1, '\\'), *cp = '\0';
  665.     if (!pn1[2]) { pn1[2] = '\\'; pn1[3] = '\0'; }
  666.     for (i = 0; i < nitems; ++i, ++items) {
  667.         strcpy(pn2, items->pname);
  668.         cp = strrchr(pn2, '\\'), *cp = '\0';
  669.         if (!pn2[2]) { pn2[2] = '\\'; pn2[3] = '\0'; }
  670.         if (strcmp(pn1, pn2)) {
  671.             display_pname = 1;
  672.             break;
  673.         }
  674.         else if (!icd && strcmp(main_cwd, pn2)) {
  675.             display_pname = 1;
  676.             break;
  677.         }
  678.         strcpy(pn1, pn2);
  679.     }
  680.     items -= i;
  681.  
  682.     display_total = maxlen = 0L;
  683.     display_length = 0;
  684.     for (i = 0; i < nitems; ++i, ++items) {
  685.         display_total += sizek(items);
  686.         maxlen = max(maxlen, sizek(items));
  687.         if (display_pname)
  688.             display_length = max(display_length,
  689.                 (int) strlen(items->pname));
  690.         else
  691.             display_length = max(display_length,
  692.                 (int) strlen(fname(items)));
  693.     }
  694.     items -= nitems;
  695.     display_length += 3;
  696.  
  697.     if (flags.f_kilobyte) {
  698.         display_largest = 2;
  699.         while (maxlen /= 10L) display_largest++;
  700.     } else
  701.         display_largest = 0;
  702.  
  703.     if (flags.f_kilobyte || (icd && flags.f_long))
  704.     printf("total %ld\n", display_total);
  705.  
  706.     pos = (int *) calloc((nitems+1), sizeof(int));
  707.     if (!pos) return;
  708.     for (i = 0; i < nitems; ++i, ++pos) *pos = 0;
  709.     pos -= nitems;
  710.  
  711.     maxlen = display_largest + display_length;
  712.     if (flags.f_kilobyte) maxlen++;
  713.     if (flags.f_type) maxlen++;
  714.     lenmod = 80 / maxlen;
  715.  
  716.     if (flags.f_column) {
  717.         rows = nitems / lenmod;
  718.         extra = nitems % lenmod;
  719.         loops = rows + extra;
  720.         total = 0;
  721.         for (i = 0; i < loops; ++i) {
  722.             cnt = i;
  723.             if (cnt >= nitems) goto end;
  724.             if (*(pos+cnt)) goto end;
  725.             *(pos+cnt) = 1;
  726.             total++;
  727.             display_column = 0;
  728.             display_entry(items+cnt);
  729.  
  730.             maybe = extra;
  731.             for (j = 0; j < lenmod-1; ++j) {
  732.                 if (maybe-- > 0) cnt += rows + 1;
  733.                 else cnt += rows;
  734.                 if (cnt >= nitems) goto end;
  735.                 if (*(pos+cnt)) goto end;
  736.                     *(pos+cnt) = 1;
  737.                 total++;
  738.                 if (j < lenmod-2) {
  739.                     display_column = 0;
  740.                     display_entry(items+cnt);
  741.                 } else {
  742.                     display_column = 1;
  743.                     display_entry(items+cnt);
  744.                     if (total != nitems)
  745.                         putchar('\n');
  746.                 }
  747.             }
  748.  
  749.         }
  750.     } else { /* !flags.f_column */
  751.         display_column = 1;
  752.         for (i = 0; i < nitems-1; ++i, ++items) {
  753.             display_entry(items);
  754.             putchar('\n');
  755.         }
  756.         display_entry(items++);
  757.         items -= nitems;
  758.     }
  759.  
  760. end:
  761.     free(pos);
  762.     return;
  763. }
  764.  
  765. static
  766. void
  767. display_entry(struct datum *sd)
  768. {
  769.     char fmt[6], ftime[13];
  770.     char *cp, *filename;
  771.     int i, itime, len;
  772.  
  773.     if (display_pname)
  774.         filename = sd->pname;
  775.     else
  776.         filename = fname(sd);
  777.     len = (int) strlen(filename);
  778.  
  779.     if (flags.f_long)
  780.     {
  781.         if (flags.f_kilobyte) {
  782.             if (sd->attrib & FA_DIREC)
  783.                 printf("        ", sizek(sd));
  784.             else
  785.                 printf("%7ld ", sizek(sd));
  786.         }
  787.  
  788.         if (sd->attrib & FA_DIREC) putchar('d');
  789.             else putchar('-');
  790.         putchar('r');
  791.         if (sd->attrib & FA_RDONLY) putchar('-');
  792.             else putchar('w');
  793.         if (sd->attrib & FA_EXEC) putchar('x');
  794.             else putchar('-');
  795.         if (sd->attrib & FA_HIDDEN) putchar('h');
  796.             else putchar('-');
  797.         if (sd->attrib & FA_SYSTEM) putchar('s');
  798.             else putchar('-');
  799.         if (sd->attrib & FA_ARCH) putchar('a');
  800.             else putchar('-');
  801.  
  802.         if (sd->attrib & FA_DIREC)
  803.             printf("           ", sd->sizeb);
  804.         else
  805.             printf("%10ld ", sd->sizeb);
  806.  
  807.         cp = asctime(localtime(&sd->date));
  808.         itime = atoi(cp+20);
  809.         if (itime != main_year)
  810.             sprintf(ftime, "%6.6s%6d", cp+4, itime);
  811.         else
  812.             sprintf(ftime, "%12.12s", cp+4);
  813.  
  814.         printf("%s %s", ftime, filename);
  815.     }
  816.     else /* if (!flags.f_long) */
  817.     {
  818.         if (flags.f_kilobyte) {
  819.             if (sd->attrib & FA_DIREC){
  820.                 for (i = 0; i <= display_largest; ++i)
  821.                 putchar(' ');
  822.             } else {
  823.                 sprintf(fmt, "%%%dld ",
  824.                     display_largest);
  825.                 printf(fmt, sizek(sd));
  826.             }
  827.         }
  828.  
  829.         printf("%s", filename);
  830.     }
  831.  
  832.     if (flags.f_type)
  833.     {
  834.         if (sd->attrib & FA_DIREC) putchar('\\'), len++;
  835.         else if (sd->attrib & FA_EXEC) putchar('*'), len++;
  836.         else if (sd->attrib & FA_SYSTEM) putchar('@'), len++;
  837.     }
  838.  
  839.     if (!display_column)
  840.     {
  841.         for (i = len; i < display_length; ++i)
  842.             putchar(' ');
  843.     }
  844. }
  845.  
  846. /*
  847. #include <dir.h>
  848. #include <dos.h>
  849. #include <string.h>
  850. */
  851.  
  852. static int strpos(char *s, char c), strrpos(char *s, char c);
  853.  
  854. int
  855. parse_file(char *pf_path,
  856.            char *pf_d, char *pf_p, char *pf_f, char *pf_e)
  857. {
  858.     char pf_cwd1[MAXPATH], pf_cwd2[MAXPATH];
  859.     char pf_nwd[MAXPATH], *pf_twd;
  860.     int pf_dev;
  861.     int dp, pp, fp, ep;
  862.     int pl;
  863.     int pf_flag = 0x0;
  864.     register int i, j;
  865.  
  866.     if (!pf_path) return(pf_flag);
  867.  
  868.     pf_dev = getdisk();
  869.     getcwd(pf_cwd1, MAXPATH*sizeof(char));
  870.  
  871.     pl = (int) strlen(pf_path);
  872.     for (i = 0; i < pl; ++i)
  873.         if (*(pf_path+i) == '/') *(pf_path+i) = '\\';
  874.     if (strchr(pf_path, '*'))
  875.         pf_flag |= WILDCARDS;
  876.     else if (strchr(pf_path, '?'))
  877.         pf_flag |= WILDCARDS;
  878.  
  879.     dp = strpos(pf_path, ':');
  880.     pp = dp + 1;
  881.     fp = strrpos(pf_path, '\\')+1;
  882.     if (!fp)
  883.         fp = pp;
  884.     ep = strrpos(pf_path, '.');
  885.     if (ep < 0)
  886.         ep = pl;
  887.     else if (ep < fp)
  888.         ep = pl;
  889.     else if (ep > pl-2)
  890.         ep = pl;
  891.     else if (*(pf_path+(ep+1)) == '\\')
  892.         ep = pl;
  893.     if (*(pf_path+(ep-1)) == '.')
  894.         fp = ep;
  895.  
  896.     *pf_d = *pf_p = *pf_f = *pf_e = '\0';
  897.  
  898.     /* find drive
  899.      */
  900.     if (dp > -1) {
  901.         for (i = 0, j = 0; i < MAXDRIVE-1 && j < pp; ++i, ++j)
  902.         {
  903.             *(pf_d+i) = toupper(*(pf_path+j));
  904.             *(pf_d+(i+1)) = '\0';
  905.             if (!i) pf_flag |= DRIVE;
  906.         }
  907.     } else {
  908.         sprintf(pf_d, "%c:", 'A' + getdisk());
  909.     }
  910.  
  911.     /* find file name
  912.      */
  913.     if (fp > -1)
  914.     for (i = 0, j = fp; i < MAXFILE-1 && j < ep; ++i, ++j)
  915.     {
  916.         *(pf_f+i) = toupper(*(pf_path+j));
  917.         *(pf_f+(i+1)) = '\0';
  918.         if (!i) pf_flag |= FILENAME;
  919.     }
  920.  
  921.     /* find file extension
  922.      */
  923.     for (i = 0, j = ep; i < MAXEXT-1 && j < pl; ++i, ++j)
  924.     {
  925.         *(pf_e+i) = toupper(*(pf_path+j));
  926.         *(pf_e+(i+1)) = '\0';
  927.         if (!i) pf_flag |= EXTENSION;
  928.     }
  929.  
  930.     /* find directory name
  931.      */
  932.     setdisk((int) (*pf_d - 'A'));
  933.     getcwd(pf_cwd2, MAXPATH*sizeof(char));
  934.  
  935.     if (pp > -1)
  936.     for (i = 0, j = pp; i < MAXDIR-1 && j < fp; ++i, ++j)
  937.     {
  938.         if (i && 
  939.             *(pf_p+(i-1)) == '\\' && 
  940.             *(pf_path+j) == '\\') {
  941.             --i;
  942.         } else {
  943.             *(pf_p+i) = toupper(*(pf_path+j));
  944.             *(pf_p+(i+1)) = '\0';
  945.             if (!i) pf_flag |= DIRECTORY;
  946.         }
  947.     }
  948.  
  949.     /* if no directory found, use current directory
  950.      */
  951.     if (!*pf_p)
  952.         sprintf(pf_p, ".");
  953.  
  954.     /* if there's a period in the directory, find the directory
  955.      */
  956.     if (strchr(pf_p, '.')) {
  957.         if (*(pf_p+(fp-1)) == '\\')
  958.             *(pf_p+(fp-1)) = '\0';
  959.         strcpy(pf_nwd, pf_p);
  960.         i = strpos((pf_p+1), '\\');
  961.         if (i > -1) pf_nwd[i+1] = '\0';
  962.         chdir(pf_nwd);
  963.         pf_twd = pf_p;
  964.         while ( (pf_twd = strchr(++pf_twd, '\\')) ) {
  965.             strcpy(pf_nwd, pf_twd);
  966.             i = strpos(&pf_nwd[1], '\\');
  967.             if (i > -1) pf_nwd[i+1] = '\0';
  968.             chdir(&pf_nwd[1]);
  969.         }
  970.         getcwd(pf_nwd, MAXPATH*sizeof(char));
  971.         strcpy(pf_p, &pf_nwd[2]);
  972.     }
  973.  
  974.     /* make sure that the directory name ends in a backslash
  975.      */
  976.     i = strlen(pf_p)-1;
  977.     if (i < MAXDIR-2 && *(pf_p+i) != '\\') {
  978.         *(pf_p+(i+1)) = '\\';
  979.         *(pf_p+(i+2)) = '\0';
  980.     }
  981.  
  982.     if (!*pf_f) {
  983.         /* if there was no file name, strip the trailing 
  984.          * backslash from the directory name
  985.          */
  986.         i = strlen(pf_p)-1;
  987.         if (i) *(pf_p+i) = '\0';
  988.     } else {
  989.         /* if the file name (including the file extension) is
  990.          * a directory, reset the directory and clear the file
  991.          * name and file extension
  992.          */
  993.         sprintf(pf_nwd, "%s%s%s", pf_p, pf_f, pf_e);
  994.         if (!chdir(pf_nwd)) {
  995.             strcpy(pf_p, pf_nwd);
  996.             *pf_f = '\0';
  997.             *pf_e = '\0';
  998.         }
  999.     }
  1000.  
  1001.     /* make sure the current directory for each disk is the same as
  1002.      * that when the subroutine was called
  1003.      */
  1004.     chdir(pf_cwd2);
  1005.     setdisk(pf_dev);
  1006.     chdir(pf_cwd1);
  1007.  
  1008.     return(pf_flag);
  1009. }
  1010.  
  1011. static
  1012. int
  1013. strpos(char *s, char c)
  1014. {
  1015.     register int i = 0;
  1016.     register char *cp = s;
  1017.  
  1018.     for (; *cp; ++i) if (*cp++ == c) return(i);
  1019.     return(-1);
  1020. }
  1021.  
  1022. static
  1023. int
  1024. strrpos(char *s, char c)
  1025. {
  1026.     register int i = (int) strlen(s) - 1;
  1027.     register char *cp = s+i;
  1028.  
  1029.     for (; i > -1; --i) if (*cp-- == c) return(i);
  1030.     return(-1);
  1031. }
  1032.  
  1033.