home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / DIR / RH_LS.ZIP / LS.C next >
Encoding:
C/C++ Source or Header  |  1991-08-30  |  28.3 KB  |  787 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /* ls - a Unix-like directory listing program for MS-DOS 2.x +               */
  4. /*                                                                           */
  5. /*               1984  R. Edward Nather                                      */
  6. /*               1985  Larry A. Shurr                                        */
  7. /*               1989  R. Ray Hensel  Comverted to Microsoft V.5             */
  8. /*                                    cleaned up code                        */
  9. /*                                    added many coments                     */
  10. /*                                    replaced heap sort with quick sort     */
  11. /*                                                                           */
  12. /*****************************************************************************/
  13. #include <stdio.h>
  14. #include <dos.h>
  15.  
  16. char*     malloc();                     /*Assure that malloc() is char* type*/
  17.  
  18. typedef int bool;                       /*Define "boolean" type*/
  19. typedef int mchar;                      /*Define "metachar" type*/
  20.  
  21. #define FALSE 0                         /*Define "false" value*/
  22. #define TRUE  1                         /*Define "true"  value*/
  23. #define is ==                           /*Define some readable stuff*/
  24. #define isnot !=
  25. #define and &&
  26. #define or ||
  27. /*****************************************************************************/
  28.                /* customizing constants */
  29.  
  30. #define NAMESIZ 13                      /*12 character name + NULL*/
  31. #define ONECS   512                     /*cluster size on one-sided floppy*/
  32. #define TWOCS   1024                    /*cluster size on two-sided floppy*/
  33. #define HARDCS  4096                    /*cluster size on hard disk*/
  34. #define SCRSIZ  22                      /*scrolling size of display screen*/
  35. /*****************************************************************************/
  36. struct dta {                            /*DOS Disk Transfer Address table*/
  37.   char reserved[21];                    /*used in "find next" operation*/
  38.   char attr;                            /*file attribute byte*/
  39.   unsigned ftime;                       /*time of last modification*/
  40.   unsigned fdate;                       /*date of last modification*/
  41.   long fsize;                           /*file size in bytes*/
  42.   char fname[NAMESIZ];                  /*filename and extension*/
  43. };
  44. typedef struct dta DTA;
  45. /*****************************************************************************/
  46. struct outbuf {                         /*output buffer -- array of file info*/
  47.   unsigned oattr;                       /*file attributes*/
  48.   unsigned odate;                       /*file creation/modification date*/
  49.   unsigned otime;                       /*file creation/modification time*/
  50.   long     osize;                       /*file size in bytes*/
  51.   char     oname[NAMESIZ+1];            /*file name*/
  52. } *obuf;
  53. typedef struct outbuf OUTBUF;
  54. /*****************************************************************************/
  55. char spath[80];                         /*holds current pathname string*/
  56.  
  57. mchar qs       = '\\';                  /*filename separator character*/
  58. char  dqs[]    = "\\";                  /*filename separator (string)*/
  59.                                                    
  60. bool  df_all   = FALSE,                 /*1 => show hidden files by default*/
  61.       df_colm  = FALSE,                 /*1 => 1-column listing by default*/
  62.       df_du    = FALSE,                 /*1 => include disk use by default*/
  63.       df_id    = FALSE,                 /*1 => always identify directory*/
  64.       df_long  = FALSE,                 /*1 => long listing by default*/
  65.       df_more  = FALSE,                 /*1 => pause for more*/
  66.       df_rsort = FALSE,                 /*1 => reverse sort by default*/
  67.       df_tsort = FALSE,                 /*1 => time sort by default*/
  68.       f_help   = FALSE                  /*Help screen requested*/
  69.       ;
  70.                 /* global variables and flags */
  71.  
  72. int   f_all,                            /*Include hidden & system files*/
  73.       f_colm,                           /*1-column format*/
  74.       f_du,                             /*Print disk usage*/
  75.       f_long,                           /*Long listing*/
  76.       f_rsort,                          /*Reverse sort*/
  77.       f_tsort,                          /*Timesort the listing*/
  78.       f_more  = FALSE,                  /*Pause for more*/
  79.       f_recd  = FALSE,                  /*Recursive descent requested*/
  80.       f_so    = FALSE,                  /*Print sizes only*/
  81.       f_tsc   = FALSE,                  /*Output is to console screen*/
  82.       np,                               /*number of groups printed*/
  83.       nargs,                            /*number of non-option arguments*/
  84.       clsize  = 0,                      /*size of a cluster, in bytes*/
  85.       clmask,                           /*clsize-1 for rounding & chopping*/
  86.       drive                             /*code number for drive requested*/
  87.       ;
  88.       
  89. long  left,                             /*unused space left on disk*/
  90.       total                             /*total of sizes encountered*/
  91.       ;
  92. /*****************************************************************************/
  93. main(argc, argv)
  94. int  argc;
  95. char *argv[];
  96. {
  97. char  *s
  98.         ;
  99. int  c = 0,
  100.      nt = 0
  101.      ;
  102.  
  103.   setbuf(stdout,malloc(BUFSIZ));        /*Force standard output buffered*/
  104.  
  105.   df_all   = envbool("LSALL",df_all);   /*1 => show hidden files by default*/
  106.   df_colm  = envbool("LSCOLM",df_colm); /*1 => 1-column listing by default*/
  107.   df_du    = envbool("LSDU",df_du);     /*1 => include disk use by default*/
  108.   df_id    = envbool("LSID",df_id);     /*1 => always identify directory*/
  109.   df_long  = envbool("LSLONG",df_long); /*1 => long listing by default*/
  110.   df_more  = envbool("LSMORE",df_more); /*1 => pause for more*/
  111.   df_rsort = envbool("LSRSORT",df_rsort);/*1 => reverse sort by default*/
  112.   df_tsort = envbool("LSTSORT",df_tsort);/*1 => time sort by default*/
  113.  
  114.   qs = envchar("LSQS",qs);              /*Get default directory separator*/
  115.   dqs[0] = qs;
  116.  
  117.   f_all   = df_all;                     /*include hidden & system files*/
  118.   f_colm  = df_colm;                    /*1-column format*/
  119.   f_du    = df_du;                      /*print disk usage*/
  120.   f_long  = df_long;                    /*long listing*/
  121.   f_more  = df_more;                    /*pause for more*/
  122.   f_rsort = df_rsort;                   /*reverse sort*/
  123.   f_tsort = df_tsort;                   /*timesort the listing*/
  124.  
  125.   f_recd  = FALSE;                      /*recursive descent requested*/
  126.   f_so    = FALSE;                      /*print sizes only*/
  127.  
  128.                /* process input options */
  129.  
  130.     while(--argc > 0 and (*++argv)[0] is '-') {
  131.           for(s = argv[0]+1; *s isnot '\0'; s++) {
  132.               switch(*s) {
  133.                 case 'a':               /*-a: list all files*/
  134.                       f_all   = !f_all;
  135.                       break;                    
  136.                 case 'c':               /*-c: 1-column listing requested*/
  137.                       f_colm  = !f_colm;
  138.                       break;
  139.                 case 'h':               /*-h: print help and quit*/
  140.                       f_help  = TRUE;
  141.                       break;
  142.                 case 'l':               /*-l: long listing requested*/
  143.                       f_long  = !f_long;
  144.                       break;
  145.                 case 'm':               /*-m: pause for more*/
  146.                       f_more  = TRUE;
  147.                       break;
  148.                 case 'r':               /*-r: reverse sort direction*/
  149.                       f_rsort = !f_rsort;
  150.                       break;
  151.                 case 's':               /*-s: print sizes only*/
  152.                       f_so = TRUE;
  153.                       if (*(s+1) is '1') {
  154.                         clsize = ONECS; /*diskuse for 1-sided floppy*/
  155.                         s++;
  156.                         nt++;
  157.                       }
  158.                       else if (*(s+1) is '2') {
  159.                         clsize = TWOCS; /*or 2-sided*/
  160.                             s++;
  161.                         nt++;
  162.                       }
  163.                       break;
  164.                 case 't':               /*-t: time sort requested*/
  165.                       f_tsort = !f_tsort;
  166.                       break;
  167.                     case 'u':           /*-u: print disk usage*/
  168.                       f_du    = !f_du;     
  169.                       break;
  170.                 case 'R':               /*-R: recursively list subdirs*/
  171.                       f_recd  = TRUE;
  172.                       break;
  173.                 default:
  174.                       fprintf(stderr, "unknown arg %c\n", *s);
  175.                       exit(1);
  176.                }
  177.         }
  178.     }
  179.  
  180.     if (f_help) {                       /*If help requested...*/
  181.         give_help();                    /*Print the help stuff*/
  182.         return;                         /*And quit now*/
  183.     }                                   /*Otherwise, continue...*/
  184.  
  185.     nargs = argc;
  186.     f_tsc = toscreen();                 /*find out if output is to console*/
  187.  
  188.     obuf = (OUTBUF*)malloc(32767);      /*point to free memory*/
  189.   
  190.     if(argc is 0) {
  191.         argc++;
  192.         curdrv(spath);                  /*default to current drive*/
  193.     }
  194.     else
  195.         strcpy(spath, *argv);
  196.   
  197.     for(;;) {                           /*cycle through args present*/
  198.         int i = 0;                      /*spath editing index*/
  199.         int l = strlen(spath);          /*spath string length*/
  200.  
  201. /*the following while loop should be looked at carefully if things*/
  202. /*don't look right. compilers don't process the increment the same*/
  203.         while (i < l)                   /*Scan spath string...*/
  204.               spath[i++] = tolower(spath[i]); /*Convert to lower case*/
  205.  
  206.         if (spath[1] is ':' and     spath[2] is '\0') /*If path is drive only */
  207.               getpath(spath);             /*get path*/
  208.         if (f_du or f_so or f_long)     /*If we need the usage data...*/
  209.               c = getsize(spath);         /*get it*/
  210.         if (c is 0)
  211.               search(spath);              /*go do the hard work*/
  212.         if (--argc > 0)
  213.               strcpy(spath, *++argv);
  214.         else {
  215.               if (f_du or f_so) {
  216.             if(np > 1) {
  217.                   fprintf(stdout,"-------\n%7ld bytes total",total);
  218.               if(!nt) 
  219.                 fputs("; ", stdout);
  220.             }
  221.             if(!nt) 
  222.                   fprintf(stdout,"%7ld bytes left on drive %c\n",left,drive+'a');
  223.           }
  224.           break;
  225.     }
  226. }
  227. }
  228. /******************************************************************************/
  229. getsize(path)                           /*get file cluster size*/
  230. char *path;
  231. {
  232.     if (clsize is 0)                    /*if size not already set*/
  233.         if ((clsize = getcl(path)) is 0) {    /*get cluster size for drive*/
  234.               fprintf(stderr,"Invalid drive: %c\n",*path);
  235.               return(1);                  /*also, return error flag*/
  236.           }                               /*But if we got the cluster size...*/
  237.       clmask = clsize-1;                  /*Set the cluster size mask as well*/
  238.       return(0);                          /*And return a 'no error' flag*/
  239. }
  240. /******************************************************************************/
  241. toscreen()                    /*find out if output is to console*/
  242. {
  243.   struct {                              /*Register file for IOCTL*/
  244.     int   ax;
  245.     int   bx;
  246.     int   cx;
  247.     int   dx;
  248.     int   si;
  249.     int   di;
  250.     int   ds;
  251.     int   es;
  252.   } r;
  253.  
  254.   r.ax = 0x4400;                        /*Set 'i/o control' function code*/
  255.   r.bx = 1;                             /*Set 'get device info' subfunction*/
  256.   sysint(0x21, &r, &r);                 /*Call DOS*/
  257.   return((int)r.dx & 1);                /*Return 'is console input' status*/
  258. }
  259. /*****************************************************************************/
  260. search(path)                            /*search for filename or directory*/
  261. char *path;
  262. {
  263.   DTA     dta;                          /*DOS file data table*/
  264.   int     path_len;                     /*length of initial path*/
  265.   int     z;                            /*char counter*/
  266.   int     k = 0;                        /*counts number of entries found*/
  267.   char     work[80];                    /*working path string*/
  268.   int     comp();                       /*string, time comparison routine*/
  269.   int     mask = 0x0010;                /*attribute mask*/
  270.   long     bytes = 0;                   /*count of disk usage this directory*/
  271.  
  272.     if (f_all) mask = 0x001F;
  273.           strcpy(work,path);
  274.       path_len = strlen(work);            /*save original path length*/
  275.  
  276.     if (!find_first(work, &dta, 0) or work[path_len-1] is qs) {
  277.         if(work[path_len-1] isnot qs) {
  278.              strcat(work, dqs);          /*if path is to a directory*/
  279.               path_len++;
  280.         }
  281.         strcat(work,"*.*");             /*list everything in it*/
  282.       }
  283.  
  284.     if(find_first(work, &dta, mask)) {
  285.         do {
  286.               if (dta.attr & 0x08)        /*ignore volume label*/
  287.                 continue;
  288.             if (dta.fname[0] is '.' and !f_all)  /*unless -a option*/
  289.                   continue;               /*ignore "." and ".."*/
  290.                 
  291.             obuf[k].oattr = dta.attr;   /*stash this entry*/
  292.             obuf[k].otime = dta.ftime;
  293.               obuf[k].odate = dta.fdate;
  294.               obuf[k].osize = dta.fsize;
  295.               strcpy(obuf[k].oname, dta.fname);
  296.         
  297.             if (f_du or f_so) {
  298.                 if((dta.attr & 0x10) and dta.fname[0] isnot '.') {
  299.                       bytes += clsize;    /*sum up disk usage*/
  300.                 }
  301.                  else if(dta.fsize) {
  302.                       obuf[k].osize = ((dta.fsize + clmask) & (long)(~clmask));
  303.                       bytes += obuf[k].osize;
  304.                 }
  305.               }
  306.             k++;
  307.         } while(!find_next(&dta));
  308.     }
  309.     else {
  310.         work[path_len-1] = NULL;
  311.         fprintf(stderr, "Can't find a file or directory named \"%s\"\n", work);
  312.         return;
  313.       }
  314.  
  315.     work[path_len] = NULL;              /*restore directory pathname*/
  316.       if(np++ and !f_so) {
  317.         fputc(endlin(),stdout);         /*separate listing blocks*/
  318.     if (f_tsc) 
  319.         fflush(stdout);
  320.       }
  321.     if (f_du or f_so) {
  322.         total += bytes;                 /*total bytes to date*/
  323.         fprintf(stdout, "%7ld  ", bytes);
  324.       }
  325.     if (f_recd or nargs > 1 or f_du or f_so or df_id) {
  326.         fprintf(stdout, "%s", work);    /*identify the block*/
  327.         fputc(endlin(),stdout);
  328.         if (f_tsc) 
  329.               fflush(stdout);
  330.       }
  331.  
  332.     if (!f_so) {
  333.         qsort(obuf,k,sizeof(obuf[0]),comp);  /*sort the entries*/
  334.         if (f_long)
  335.               longlist(k);                /*and print them*/
  336.         else
  337.               shortlist(k);
  338.       }
  339.  
  340.     if (!f_recd) 
  341.         return;                         /*quit if not -R*/
  342.  
  343.     strcat(work, "*.*");
  344.       if(find_first(work, &dta, mask))    /*else find all sub-dirs*/
  345.         do     {
  346.               if(dta.attr & 0x10 and dta.fname[0] isnot '.') {
  347.                 work[path_len] = 0;     /*discard old name              */
  348.                    for(z=0; dta.fname[z] isnot NULL; z++)
  349.                        dta.fname[z] = tolower(dta.fname[z]);
  350.                    strcat(work, dta.fname);/*install a new one*/
  351.                    strcat(work, dqs);
  352.                    search(work);           /*and recurse*/
  353.            }
  354.        } while(!find_next(&dta));
  355. return;
  356. }
  357. /******************************************************************************/
  358. getpath(sp)                    /*get drive's current directory path*/
  359. char     *sp;
  360. {
  361.     struct {                    /*Register file for GET PATH*/
  362.       int   ax;
  363.       int   bx;
  364.       int   cx;
  365.       int   dx;
  366.       char* si;
  367.       int   di;
  368.       int   ds;
  369.       int   es;
  370.     } r;
  371.  
  372.   strcat(sp, dqs);                      /*append root symbol to drive name*/
  373.  
  374.                                         /*Prepare to get current path...*/
  375.   r.ax = 0x4700;                        /*Set 'get current directory' code*/
  376.   r.dx = *sp - '`';                     /*Set drive number*/
  377.   r.ds = _showds();                     /*Set pathname buffer segment*/
  378.   r.si = sp + 3;                        /*Set pathname buffer offset*/
  379.   sysint(0x21, &r, &r);                 /*Call DOS*/
  380. }
  381. /******************************************************************************/
  382. /*getcl - get cluster size & space left on requested drive*/
  383. getcl(pp)
  384. char *pp;
  385. {
  386.   int cs;
  387.  
  388. if(*(pp+1) is ':')               /*use specified drive if any*/
  389.      cs = *pp - 'a';
  390. else {
  391.      cs = disk_drive();
  392.      }
  393. drive = cs & 0x7F;
  394. if (!f_du and !f_so and drive is 2) 
  395.      return(HARDCS);
  396.  
  397. return(disk_left(cs + 1));
  398.  
  399. }
  400.  
  401. /******************************************************************************/
  402. /*comp - compare size of two entries*/
  403. comp(a,b)
  404. struct outbuf *a, *b;
  405. {
  406. int y;
  407.  
  408. if (f_tsort) {
  409.      if(a->odate isnot b->odate)                         /*if dates differ*/
  410.           y = (a->odate < b->odate) ? -1 : 1;          /*that settles it*/
  411.      else
  412.           y = (a->otime < b->otime) ? -1 : 1;          /*else compare times*/
  413.      return((f_rsort) ? y : -y);
  414.      }
  415. else {
  416.      y = strcmp(a->oname, b->oname);                    /*name comparison*/
  417.     return((f_rsort) ? -y : y);
  418.      }
  419. }
  420. /******************************************************************************/
  421. shortlist(k)                    /*List filenames in 1-to-5 columns*/
  422. int k;                         /*total number to print*/
  423. {
  424. int i, 
  425.     m, 
  426.     n
  427.     ;
  428.  
  429.     if (f_colm) {                       /*If single-column output selected...*/
  430.         n = k;                          /*Set for 1-column listing*/
  431.     }                                   /*Otherwise...*/
  432.     else 
  433.         n = (k + 4)/5;                  /*Set for 2-to-5-column listing*/
  434.     for (i = 0; i < n; i++) {           /*Scan the directory buffer...*/
  435.            for (m = 0; (i+m) < k; m += n) {  /*Scan a row of data...*/
  436.             if (obuf[i+m].oattr & 0x10) { /*If file is a directory file...*/
  437.                    strcat(obuf[i+m].oname,dqs); /*Mark it so*/
  438.             }                           /*Otherwise, continue...*/
  439.         putname(i+m);                   /*Print the name*/
  440.         fputs("   ", stdout);           /*Output blanks to the next column*/
  441.         }                               /*End of scan-a-row*/
  442.     fputc(endlin(),stdout);             /*Output an end-of-line to stdout*/
  443.     if (f_tsc) 
  444.         fflush(stdout);                 /*Force line out if stdout is console*/
  445.       }                                   /*End of scan-directory-buffer*/
  446. }
  447. /******************************************************************************/
  448. /*putname - convert name to lower case and print*/
  449. putname(i)
  450. int i;
  451. {
  452. int c, 
  453.     j = 0
  454.     ;
  455.  
  456.     while ((c = tolower(obuf[i].oname[j])) isnot 0) {
  457.         fputc(c, stdout);
  458.         j++;
  459.     }
  460.     while (j++ < NAMESIZ - 1) {          /*pad to columnarize*/
  461.         fputc(' ', stdout);
  462.       }
  463. }
  464. /******************************************************************************/
  465. static int lc = 0;                         /*line counter*/
  466. endlin()                                /*End line & watch for screen full*/
  467. {
  468. int key;                                /*Gets user key-in*/
  469.  
  470.     if (f_tsc  and f_more and ++lc >= SCRSIZ) { /*If output is to screen and...*/
  471.                                         /*If pause for more flag set and...*/
  472.                                         /*If we have shown a screenful...*/
  473.         fputs("\n--More--",stdout);     /*Pause and...*/
  474.         fflush(stdout);                 /*Force output to standard output*/
  475.         key = ci();                     /*Await user action code*/
  476.  
  477.         fputs("\b\b\b\b\b\b\b\b        \b\b\b\b\b\b\b",stdout); 
  478.                                         /*Blank it out*/
  479.  
  480.         switch(key) {                   /*Do what user asked for...*/
  481.               case '\r':                  /*<RETURN> - show 1 more line*/
  482.                  lc = SCRSIZ - 1;
  483.                 break;
  484.               case 'q':                   /*quit with "q" or "ctrl-C"*/
  485.               case '\003':
  486.                  exit(0);
  487.               default:                    /*else show another screenful*/
  488.                  lc = 0;
  489.                  break;
  490.         }
  491.         return('\b');
  492.     }     
  493.     else return('\n');
  494. }
  495. /******************************************************************************/
  496. struct llst {                    /*structure to hold file information*/
  497.   char     *fattr;                      /*file attribute pointer*/
  498.   long     size;                        /*file size*/
  499.   int     day;                          /*the day of creation*/
  500.   int     mnum;                         /*month number*/
  501.   int     yr;
  502.   int     hh;                           /*creation times*/
  503.   int     mm;
  504.   int     ap;                           /*am or pm*/
  505. } l;
  506.  
  507. longlist(k)                             /*list everything about the files*/
  508. int     k;                              /*total number to list*/
  509. {
  510.  
  511. int i, m, n, cdate;
  512. char *mon, *mname();
  513.  
  514. cdate = gcdate();                   /*get current date (in months)*/
  515.     if (f_colm) {                    
  516.         n = k;                          /*set for 1 column listing*/
  517.       }
  518.     else 
  519.         n = (k + 1)/2;                  /*or for 2 column listing*/
  520.       for (i = 0; i < n; i++) {
  521.         for (m = 0; (m+i) < k; m += n) {          
  522.               fill(i+m, &l);              /*fill llst structure*/
  523.               mon = mname(l.mnum);        /*conv month # to name*/
  524.               fprintf(stdout,"%s%7ld  %2d %s ",l.fattr,l.size,l.day, mon);
  525.               if (cdate >= (l.yr * 12 +l.mnum) + 12) 
  526.                   fprintf(stdout, " %4d  ",l.yr); /*print year if too old*/
  527.               else 
  528.                  fprintf(stdout,"%2d:%02d%c ",l.hh,l.mm,l.ap);
  529.               putname(i+m);
  530.               if (m+n < k) 
  531.                 fputs("\272 ",stdout);  /*double bar separator*/
  532.         }
  533.         fputc(endlin(),stdout);
  534.         if (f_tsc) 
  535.             fflush(stdout);
  536.     }
  537. }
  538. /******************************************************************************/
  539. /*fill - fill long list structure with file information*/
  540.  
  541. fill(i, ll)
  542. int i;
  543. struct llst *ll;
  544. {
  545. int j, k;
  546. static char fbuf[16][4] = {"--w","---","-hw","-h-","s-w","s--","shw","sh-",
  547.                            "d-w","d--","dhw","dh-","d-w","d--","dhw","dh-"};
  548.  
  549.     if((obuf[i].oattr & 0x10) and obuf[i].oname[0] isnot '.') {
  550.          ll->size = clsize;
  551.          j = 8;                          /*if directory, use block size*/
  552.     }                                   /*and set dir attr offset*/
  553.     else {
  554.         ll->size = obuf[i].osize;       /*else use file size*/
  555.          j = 0;                          /*and file attr offset*/
  556.     }
  557.     ll->fattr = fbuf[(obuf[i].oattr & 0x07) + j];  /*point to symbolic attr*/
  558.     ll->day = obuf[i].odate & 0x1F;
  559.     ll->mnum = (obuf[i].odate >> 5) & 0x0F;
  560.     ll->yr = (obuf[i].odate >> 9) + 1980;
  561.     k = obuf[i].otime >> 5;             /*this is a mess*/
  562.     ll->mm = k & 0x3f;
  563.     ll->ap = ((ll->hh = k >> 6) >= 12) ? 'p' : 'a';
  564.     if(ll->hh > 12)
  565.            ll->hh -= 12;
  566.     if(ll->hh is 0)
  567.         ll->hh = 12;
  568.     return;
  569. }
  570. /*****************************************************************************/
  571. char* mname(n)                    /*convert month number to month name*/
  572. int n;
  573. {
  574.                                    /*Array of month names*/
  575. static char *name[] = { "???","Jan","Feb","Mar","Apr","May","Jun",
  576.                         "Jul","Aug","Sep","Oct","Nov","Dec"  };
  577.  
  578.   return((n < 1 or n > 12) ? name[0] : name[n]);
  579. }
  580. /*****************************************************************************/
  581. #define onoff(arg)  arg ? "ON " : "OFF"
  582. #define forrev(arg) arg ? "REVERSE" : "FORWARD"
  583.  
  584. give_help()                    /*Give some help to one who needs it*/
  585. {
  586.   printf("\n");
  587.   printf("      -a    Reverse the \"list all files\" option default\n");
  588.   printf("      -c    Reverse the \"one-column listing\" option default\n");
  589.   printf("      -h    Print this help message and the default settings\n");
  590.   printf("      -l    Reverse the \"long listing\" option default\n");
  591.   printf("      -m    Reverse the \"pause for more\" option default\n");
  592.   printf("      -r    Reverse the default sort direction\n");
  593.   printf("      -R    Recursively list sub-directories\n");
  594.   printf("      -s    Print sizes\n");
  595.   printf("      -s1   Print sizes for single-sided diskette\n");
  596.   printf("      -s2   Print sizes for double-sided diskette\n");
  597.   printf("      -t    Reverse the \"time sort\" option default\n");
  598.   printf("      -u    Reverse the \"include disk usage\" option default\n");
  599.   printf("\n");
  600.  
  601.   printf("List all files default is     %3s      ",onoff(df_all));
  602.   printf("Default sort direction is     %7s  \n",forrev(df_rsort));
  603.  
  604.   printf("One-column listing default is %3s      ",onoff(df_colm));
  605.   printf("Include disk usage default is %3s      \n",onoff(df_du));
  606.  
  607.   printf("Long listing default is       %3s      ",onoff(df_long));
  608.   printf("Time sort option default is   %3s      \n",onoff(df_tsort));
  609.  
  610.   printf("Pause for more default is     %3s      ",onoff(df_more));
  611.   printf("Always print dir default is   %3s      \n",onoff(df_id));
  612.  
  613.   printf("\n");
  614. }
  615. /*****************************************************************************/
  616. /*                                                                           */
  617. /*                Compiler-specific code for                                 */
  618. /*                                                                           */
  619. /*                 Microsoft version 5.0 and later                           */
  620. /*                                                                           */
  621. /*****************************************************************************/
  622.  
  623.  
  624. struct sysreg {                    /*Generic register file*/
  625.     int ax;
  626.     int bx;
  627.     int cx;
  628.     int dx;
  629.     int si;
  630.     int di;
  631.     int ds;
  632.     int es; 
  633. };
  634. typedef struct sysreg SYSREG;
  635.  
  636. int     _stack = 3072;
  637. char*     getenv();
  638.  
  639. /*********************************/
  640.  
  641. gcdate()                    /*get current date for comparison*/
  642. {
  643. struct dosdate_t date;
  644.   _dos_getdate(&date);
  645.   return((int)date.year * 12 + date.month);     /*Return date in months*/
  646. }
  647.  
  648. /*********************************/
  649.  
  650. find_first(path, dta, mask)          /*find first file in directory*/
  651. char     *path;
  652. struct find_t *dta;
  653. int     mask;
  654. {
  655.     return(!(_dos_findfirst(path, mask , dta)));
  656. }
  657.  
  658. /*********************************/
  659.  
  660. find_next(dta)                    /*find next file in same directory*/
  661. struct find_t *dta;
  662. {
  663.     return(_dos_findnext(dta));
  664. }
  665.  
  666. /*********************************/
  667.  
  668. curdrv(sp)                    /*get current default drive*/
  669. char     *sp;
  670. {
  671.     *sp++ = disk_drive() + 'a';
  672.     *sp++ = ':';
  673. }
  674. /*********************************/
  675.  
  676. int _showds()                    /*Obtain DS register value*/
  677. {
  678.   struct SREGS sfile;
  679.  
  680.   segread(&sfile);
  681.  
  682.   return(sfile.ds);
  683. }
  684.  
  685. /*********************************/
  686.  
  687. bool envbool(env,val)               /*Get environment boolean*/
  688. char*     env;
  689. bool     val;
  690. {
  691. char*     envval = getenv(env);
  692.  
  693.     if (*envval) 
  694.         val = *envval-'0';
  695.     return(val);
  696. }
  697.  
  698. /*********************************/
  699.  
  700. mchar envchar(env,val)               /*Get environment character*/
  701. char*     env;
  702. mchar     val;
  703. {
  704. char*     envval = getenv(env);
  705.  
  706.     if (*envval) 
  707.         val = *envval;
  708.     return(val);
  709. }
  710.  
  711. /*********************************/
  712.  
  713. ci()                         /*Quick and dirty 'console input'*/
  714. {
  715.   return( (bdos(0xc,0,7)) & 0xFF);
  716. }
  717.  
  718. /*********************************/
  719.  
  720. sysint(interupt,r_in,r_out)          /*Interface sysint() to int86x()*/
  721. int     interupt;
  722. SYSREG* r_in;
  723. SYSREG* r_out;
  724. {
  725.   int     result;
  726.  
  727.  union  REGS  rfile;
  728.   struct SREGS sfile;
  729.  
  730.   segread(&sfile);
  731.  
  732.   rfile.x.ax = r_in->ax;
  733.   rfile.x.bx = r_in->bx;
  734.   rfile.x.cx = r_in->cx;
  735.   rfile.x.dx = r_in->dx;
  736.   rfile.x.si = r_in->si;
  737.   rfile.x.di = r_in->di;
  738.  
  739.   sfile.ds = r_in->ds;
  740.   sfile.es = r_in->es;
  741.  
  742.   result = int86x(interupt,&rfile,&rfile,&sfile);
  743.  
  744.   r_out->ax = rfile.x.ax;
  745.   r_out->bx = rfile.x.bx;
  746.   r_out->cx = rfile.x.cx;
  747.   r_out->dx = rfile.x.dx;
  748.   r_out->si = rfile.x.si;
  749.   r_out->di = rfile.x.di;
  750.  
  751.   r_out->ds = sfile.ds;
  752.   r_out->es = sfile.es;
  753.  
  754.   return(result);
  755. }
  756.  
  757. /*********************************/
  758.  
  759. disk_drive()
  760. {
  761. unsigned drive;
  762.      _dos_getdrive(&drive);
  763.      return(drive - 1);
  764. }
  765.  
  766. /*********************************/
  767.  
  768. disk_left(drive)
  769. int drive;
  770. {
  771. struct diskfree_t s;
  772.  
  773.   if(_dos_getdiskfree(drive,&s))
  774.      return(0);
  775.   left = (long)s.avail_clusters * (long)s.sectors_per_cluster * 
  776.          (long)s.bytes_per_sector;
  777.  
  778.      return(s.sectors_per_cluster * s.bytes_per_sector);
  779. }
  780.  
  781.  
  782. /*****************************************************************************/
  783. /********************  end of code  ******************************************/
  784. /********************  end of code  ******************************************/
  785. /********************  end of code  ******************************************/
  786. /*****************************************************************************/
  787.