home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / DIR / LS_N_DF.ZIP / LS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-02  |  10.3 KB  |  454 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <dos.h>
  4. #include <dir.h>
  5. #include <io.h>
  6. #include <time.h>
  7. #include <string.h>
  8.  
  9. typedef    char    Boolean;
  10. #define    False    0
  11. #define    True    1
  12. #define    Null    NULL
  13.  
  14. struct ffblk    ff;
  15. time_t    pascal    __dostimetou(int ff_fdate, int ff_ftime);
  16. #define    TIMEOF(ff)    __dostimetou(ff.ff_fdate, ff.ff_ftime)
  17.  
  18. char    optstr[]    = "adlrstu1ACFR";
  19. char    opts[12];
  20. #define    opt_a    opts[0]
  21. #define    opt_d    opts[1]
  22. #define    opt_l    opts[2]
  23. #define    opt_r    opts[3]
  24. #define    opt_s    opts[4]
  25. #define    opt_t    opts[5]
  26. #define    opt_u    opts[6]
  27. #define    opt_1    opts[7]
  28. #define    opt_A    opts[8]
  29. #define    opt_C    opts[9]
  30. #define    opt_F    opts[10]
  31. #define    opt_R    opts[11]
  32.  
  33. char    dir_d    = 0;
  34. char    dir_F    = 0;
  35. char    dir_R    = FA_DIREC;
  36. char    dot_R    = 0xe5;
  37.  
  38. int    maxcols    = 0;
  39. char    slash    = '\\';
  40. char    findattr= FA_DIREC;
  41. time_t    ltime;
  42.  
  43. char    attrmsk[]    = {FA_DIREC, FA_ARCH, FA_SYSTEM, FA_HIDDEN, FA_RDONLY};
  44.  
  45. struct node    {
  46.     struct node    *next;
  47.     char        attrib;
  48.     long        size;
  49.     int        csize;
  50.     time_t        time;
  51.     char        *name;
  52. };
  53. struct node    *flist;
  54. int        nfiles;
  55. int        nclust;
  56. int        longest;
  57. unsigned int    clust;            /* cluster size */
  58. int        lenbase;        /* length of -s & -l stuff */
  59.  
  60. char    line[128];
  61. char    currdir[128];
  62.  
  63. void    showfiles(int dirlen, struct node *dlist);
  64.  
  65. Boolean    do_opts(char *p) {
  66.     char    *p1;
  67.  
  68.     for (; *p != '\0'; ++p) {
  69.         if ((p1 = strchr(optstr, *p)) == Null) return False;
  70.         opts[p1 - optstr] = True;
  71.     }
  72.     return True;
  73. }
  74.  
  75. void    setclust(int drive) {
  76.     unsigned int    clust1;
  77.  
  78.     _AH = 0x1c;
  79.     _DL = drive;
  80.     geninterrupt(0x21);
  81.     clust1 = _AL * _CX;
  82.     _DS = _SS;
  83.     clust = clust1;
  84. }
  85.  
  86. void    freelist(struct node *np) {
  87.     struct node *np2;
  88.  
  89.     while (np != Null) {
  90.         np2 = np->next;
  91.         free(np->name);
  92.         free(np);
  93.         np = np2;
  94.     }
  95. }
  96.  
  97. int    addtolist(struct node **head, char *name, Boolean dtflag) {
  98.     int        len;
  99.     struct node    *np;
  100.  
  101.     if ((np = malloc(sizeof(struct node))) == Null ||
  102.         (np->name = malloc((len = strlen(name)) + 1)) == Null) {
  103.         fputs("Out of memory.\n", stderr);
  104.         exit(2);
  105.     }
  106.     np->next = *head;
  107.     *head = np;
  108.     np->attrib = ff.ff_attrib;
  109.     np->size = ff.ff_fsize;
  110.     np->time = 0;
  111.     if (dtflag) np->time = TIMEOF(ff);
  112.     strcpy(np->name, name);
  113.     return len;
  114. }
  115.  
  116. void    addfile(char *name, struct node **dlistp, char dot_a, Boolean dtflag) {
  117.     int    len;
  118.  
  119.     if (!(ff.ff_attrib & dir_d) && *name != dot_a) {
  120.         len = addtolist(&flist, name, dtflag);
  121.         ++nfiles;
  122.         if (ff.ff_attrib & dir_F) ++len;
  123.         if (len > longest) longest = len;
  124.         flist->csize = 0;
  125.         if (!(ff.ff_attrib & FA_DIREC) && ff.ff_fsize != 0)
  126.         nclust += (flist->csize = (ff.ff_fsize - 1) / clust + 1);
  127.     }
  128.     if ((ff.ff_attrib & dir_R) && *name != dot_R)
  129.         (void) addtolist(dlistp, name, dtflag);
  130. }
  131.  
  132. int    opt_findfirst(char *base, int baselen, char *fn) {
  133.     char    attr    = findattr;
  134.     Boolean    nowild    = (strchr(fn, '*') == Null && strchr(fn, '?') == Null);
  135.  
  136.     memcpy(line, base, baselen);
  137.     strcpy(line + baselen, fn);
  138.     if (strchr(fn, '.') == Null) {
  139.         if (nowild &&
  140.         findfirst(line, &ff, attr | FA_HIDDEN | FA_SYSTEM) == 0 &&
  141.         ff.ff_attrib & FA_DIREC) return 0;
  142.         strcat(line + baselen, ".*");
  143.     }
  144.     else if (nowild) attr |= FA_HIDDEN | FA_SYSTEM;
  145.     return findfirst(line, &ff, attr);
  146. }
  147.  
  148. Boolean    processopt(char *base, int baselen, char *fn, struct node **dlistp,
  149.         Boolean showfull) {
  150.     char    dot_a;
  151.  
  152.     if (opt_findfirst(base, baselen, fn) != 0) return False;
  153.     dot_a = opt_a || (*fn != '*' && *fn != '?') ? 0 : '.';
  154.     for (;;) {
  155.         char *p1 = ff.ff_name;
  156.         char *p2 = line + baselen;
  157.  
  158.         for (;;) {
  159.         char    c    = *p1;
  160.         if (c >= 'A' && c <= 'Z') c |= 0x20;
  161.         *p2++ = c;
  162.         if (c == '\0') break;
  163.         ++p1;
  164.         }
  165.         addfile(line + (showfull ? 0 : baselen), dlistp, dot_a, True);
  166.         if (findnext(&ff) != 0) break;
  167.     }
  168.     return True;
  169. }
  170.  
  171. struct node    *mergesort(struct node *head, Boolean reverse) {
  172.     struct node    *p1, *p2, *newhead, *t;
  173.  
  174.     if ((p2 = head->next) == Null) return head;
  175.     p1 = head;
  176.     if (opt_u)
  177.         if (reverse) return head;
  178.         else p2 = Null;
  179.     else {
  180.         for (;;) {
  181.         if ((p2 = p2->next) == Null) break;
  182.         if ((p2 = p2->next) == Null) break;
  183.         p1 = p1->next;
  184.         }
  185.         reverse ^= 1;
  186.         p2 = mergesort(p1->next, reverse);
  187.         p1->next = Null;
  188.         p1 = mergesort(head, reverse);
  189.     }
  190.     /*
  191.      *    Now merge p1 and p2.
  192.      */
  193.     newhead = Null;
  194.     while (p2 != Null) {
  195.         if (reverse ^ (opt_t ? p1->time > p2->time :
  196.             strcmp(p1->name, p2->name) < 0)) {
  197.         t = p1;
  198.         p1 = p2;
  199.         }
  200.         else t = p2;
  201.         p2 = t->next;
  202.         t->next = newhead;
  203.         newhead = t;
  204.     }
  205.     while (p1 != Null) {
  206.         t = p1;
  207.         p1 = p1->next;
  208.         t->next = newhead;
  209.         newhead = t;
  210.     }
  211.     return newhead;
  212. }
  213.  
  214. void    putlong(long value, char *p, int len) {
  215.     char    temp[10];
  216.     int    i;
  217.  
  218.     (void) ltoa(value, temp, 10);
  219.     i = len - strlen(temp);
  220.     while (--i >= 0) *p++ = ' ';
  221.     strcpy(p, temp);
  222. }
  223.  
  224. void    showdir(int len) {
  225.     struct node    *dlist    = Null;
  226.     static    char    total[]    = "Total xxxxxx";
  227.     char    drive    = 0;
  228.  
  229.     if (len != 0) {
  230.         char c = currdir[len - 1];
  231.  
  232.         if (c != ':' && c != '/' && c != '\\')
  233.         if (c == '.' && (len == 1 || (len == 3 && currdir[1] == ':')))
  234.             --len;
  235.         else currdir[len++] = slash;
  236.         c = *currdir | 0x20;
  237.         if (c >= 'a' && c <= 'z' && currdir[1] == ':')
  238.         drive = c - ('a' - 1);
  239.     }
  240.     setclust(drive);
  241.     processopt(currdir, len, "*.*", &dlist, False);
  242.     if (opt_s | opt_l) {
  243.         (void) ltoa(nclust, total + 6, 10);
  244.         puts(total);
  245.     }
  246.     showfiles(len, dlist);
  247. }
  248.  
  249. void    showfiles(int dirlen, struct node *dlist) {
  250.     struct node *np;
  251.  
  252.     if (flist != Null) {
  253.         int ncols, nrows;
  254.         struct node *np;
  255.         int i;
  256.  
  257.         flist = mergesort(flist, opt_r);
  258.         longest = (lenbase + longest) / 8 + 1;
  259.         if ((ncols = maxcols / longest) == 0) ncols = 1;
  260.         i = nrows = (nfiles - 1) / ncols + 1;
  261.         np = flist;
  262.         while (i > 0) {    /* loop over rows */
  263.         struct node    *np1    = np;
  264.         int        nleft    = nfiles;
  265.  
  266.         for (;;) {    /* loop over columns */
  267.             int len = lenbase + strlen(np1->name);
  268.             int i;
  269.  
  270.             if (opt_s | opt_l) {
  271.             char    *p    = line;
  272.             char    *timep;
  273.  
  274.             if (opt_s) {
  275.                 if (np1->attrib & FA_DIREC) memset(p, ' ', 5);
  276.                 else {
  277.                 putlong(np1->csize, p, 4);
  278.                 if (np1->csize < 10000) p[4] = ' ';
  279.                 }
  280.                 p += 5;
  281.             }
  282.             if (opt_l) {
  283.                 int i;
  284.  
  285.                 for (i = 0; i < sizeof(attrmsk); ++i)
  286.                 *p++ = np1->attrib & attrmsk[i] ?
  287.                     "dashr"[i] : '-';
  288.                 if (np1->attrib & FA_DIREC) memset(p, ' ', 8);
  289.                 else putlong(np1->size, p, 8);
  290.                 p += 8;
  291.                 if (np1->time == 0) memset(p, ' ', 14);
  292.                 else {
  293.                 timep = ctime(&np1->time);
  294.                 memcpy(p, timep + 3, 8);
  295.                 memcpy(p + 8,
  296.                     timep + (np1->time < ltime ? 19 : 11), 5);
  297.                 p[13] = ' ';
  298.                 }
  299.                 p += 14;
  300.             }
  301.             (void) fwrite(line, 1, p - line, stdout);
  302.             }
  303.             fputs(np1->name, stdout);
  304.             if (np1->attrib & dir_F) {
  305.             putchar('/');
  306.             ++len;
  307.             }
  308.             if ((nleft -= nrows) <= 0) break;
  309.             i = nrows;
  310.             while (--i >= 0) np1 = np1->next;
  311.             len /= 8;
  312.             while (len < longest) {
  313.             putchar('\t');
  314.             ++len;
  315.             }
  316.         }
  317.         putchar('\n');
  318.         np = np->next;
  319.         --nfiles;
  320.         --i;
  321.         }
  322.         freelist(flist);
  323.         flist = Null;
  324.         nfiles = 0;
  325.         nclust = 0;
  326.         longest = 0;
  327.     }
  328.     if (dlist == Null) return;
  329.     dlist = mergesort(dlist, opt_r);
  330.     for (np = dlist; np != Null; np = np->next) {
  331.         int len = strlen(np->name);
  332.  
  333.         memcpy(currdir + dirlen, np->name, len);
  334.         currdir[len += dirlen] = '\0';
  335.         putchar('\n');
  336.         fputs(currdir, stdout);
  337.         puts(":");
  338.         showdir(len);
  339.     }
  340.     freelist(dlist);
  341. }
  342.  
  343. void    cdecl    main(int argc, char **argv) {
  344.     static    struct node    *dlist    = Null;
  345.     char    **argvend = argv + argc;
  346.     char    *p;
  347.  
  348.     if ((p = getenv("LS")) != Null) {
  349.         if (*p == '-') ++p;
  350.         if (!do_opts(p))
  351.         fputs("Illegal flag in environment variable LS\n", stderr);
  352.     }
  353.     for (++argv; argv < argvend;) {
  354.         if (*(p = *argv) != '-') break;
  355.         ++argv;
  356.         if (*++p == '\0') break;
  357.         if (!do_opts(p)) {
  358.         fputs("Usage:  ls -adlrstu1ACFR file1 ...\n", stderr);
  359.         exit(1);
  360.         }
  361.     }
  362.         /* get screen width */
  363.     if (!opt_1 && (opt_C || (!opt_l && isatty(1)))) {
  364.         _AH = 0x0f;
  365.         geninterrupt(0x10);
  366.         maxcols = _AH / 8;
  367.     }
  368.     if (!opt_d) dir_d = FA_DIREC;
  369.     else if (!opt_R) dir_R = 0;
  370.     if (opt_F) dir_F = FA_DIREC;
  371.     if (opt_s) lenbase += 5;
  372.     if (opt_l) {
  373.         lenbase += 27;
  374.         ltime = time(Null) - 180L * 24 * 60 * 60;
  375.     }
  376.     if (opt_a | opt_A) findattr |= FA_HIDDEN | FA_SYSTEM;
  377.     if (getswitchar() != '/') slash = '/';
  378.     if (argv >= argvend) *--argv = "";    /* if no args */
  379.     for (; argv < argvend; ++argv) {
  380.         char *arg;
  381.         char *arg1;
  382.         char c;
  383.  
  384.         arg = arg1 = *argv;
  385.         if ((c = *arg | 0x20) >= 'a' && c <= 'z' && arg[1] == ':') {
  386.         setclust(c - ('a' - 1));
  387.         arg1 += 2;
  388.         }
  389.         else setclust(0);
  390.         if (*arg1 == '\0' || (*arg1 == '.' && arg1[1] == '\0')) {
  391.         static    char    dotname[] = "x:.";
  392.  
  393.         *dotname = *arg;
  394.         if (findfirst(dotname + (arg + 2 - arg1), &ff, FA_DIREC) == 0) {
  395.             addfile(arg, &dlist, 0, True);
  396.             continue;
  397.         }
  398.         }
  399.         else if ((*arg1 != '/' && *arg1 != '\\') || arg1[1] != '\0') {
  400.         if ((p = strrchr(arg1, '/')) != Null) arg1 = p + 1;
  401.         if ((p = strrchr(arg1, '\\')) != Null) arg1 = p + 1;
  402.         if (!processopt(arg, arg1 - arg, arg1, &dlist, True)) {
  403.             fputs(arg, stderr);
  404.             fputs(": no match.\n", stderr);
  405.         }
  406.         continue;
  407.         }
  408.         /* otherwise, do the root directory */
  409.         {
  410.         /*
  411.          *    Get date of disk volume, if possible.
  412.          *    No I can't use findfirst:  there's a bug in DOS 2.1.
  413.          */
  414.         static    struct {
  415.             char    xfcb[7];
  416.             char    drive;
  417.             char    name[11];
  418.         }
  419.         fcb1    = {{-1,0,0,0,0,0,8}, 0, "???????????"};
  420.         struct    {
  421.             char    xfcb[7];
  422.             char    drive;
  423.             char    fill[22];
  424.             int    time, date;
  425.             char    fill2[6];
  426.         } fcb2;
  427.         Boolean    dtflag;
  428.  
  429.         fcb1.drive = arg1 > arg ? *arg - ('a' - 1) : 0;
  430.         setdta((char far *) &fcb2);
  431.         _AH = 0x11;
  432.         _DX = (int) &fcb1;
  433.         geninterrupt(0x21);
  434.         dtflag = !_AL;
  435.         ff.ff_fdate = fcb2.date;
  436.         ff.ff_ftime = fcb2.time;
  437.         ff.ff_attrib = FA_DIREC;
  438.         addfile(arg, &dlist, 0, dtflag);
  439.         }
  440.     }
  441.     /*
  442.      *    Do the printing.
  443.      */
  444.     if (!opt_R) dir_R = 0;
  445.     dir_d = 0;
  446.     dot_R = '.';
  447.     if (flist == Null && dlist != Null && dlist->next == Null) {
  448.         int len = strlen(dlist->name);
  449.         memcpy(currdir, dlist->name, len);
  450.         showdir(len);
  451.     }
  452.     else showfiles(0, dlist);
  453. }
  454.