home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / c / pcw_c.zip / CDIR.C < prev    next >
Text File  |  1990-01-30  |  15KB  |  375 lines

  1. /**********************************************************/
  2. /* Program Id.               Cdir.C.                      */
  3. /* Author.                   Stan Milam.                  */
  4. /* Installation.             Mountain View College        */
  5. /* Date Written.             09/06/87.                    */
  6. /* Compiler.                 Turbo C V1.00,               */
  7. /*                       Microsoft C V5.00,               */
  8. /*                       Mix Power C V1.00.               */
  9. /* Comments:  This program was written to demonstrate the */
  10. /* use of software interrupts, both DOS & BIOS. The       */
  11. /* functions performed are to get a directory listing by  */
  12. /* making DOS interrupt calls and to display the directory*/
  13. /* on the screen with a window managed by ROM BIOS.  Also */
  14. /* the bit masking & shifting capabilities of C are       */
  15. /* demonstrated.                                          */
  16. /* WARNING! Do not try to redirect the output to the      */
  17. /* printer since some of the line feeds will be performed */
  18. /* by ROM BIOS.                                           */
  19. /**********************************************************/
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <dos.h>
  24. #include <conio.h>
  25. #include <pcwproto.h>
  26.  
  27. #define  TRUE 1
  28. #define  FALSE 0
  29.  
  30. int pause = FALSE;                     /* A flag to signal pause */
  31.  
  32. struct dta_type {                      /* Defines Disk Transfer Area */
  33.     char          reserved[21];        /* Reserved by DOS */
  34.     char          fattrib;             /* File attribute  */
  35. /************************************/
  36. /* The next 3 fields are bit fields */
  37. /************************************/
  38.     unsigned int  fsec:5;              /* Second file was created */
  39.     unsigned int  fmin:6;              /* Minute file was created */
  40.     unsigned int  fhour:5;             /* Hour file was created */
  41.     unsigned int  fdate;               /* Date the file was created */
  42.     long          fsize;               /* Size of the file in bytes */
  43.     char          fname[13];           /* File name */
  44.   };
  45.  
  46. /***********************************************************/
  47. /*                         SET_DTA                         */
  48. /* This function (procedure) will establish a new Disk     */
  49. /* Transfer Area.  The new DTA will be a structure that    */
  50. /* will mirror the information DOS will return to us when  */
  51. /* we call the firstfile and nextfile functions.           */
  52. /***********************************************************/
  53.  
  54. void set_dta(dta)
  55. struct dta_type *dta; {
  56.  
  57.   struct SREGS sregs;
  58.   union  REGS regs;
  59.  
  60.   segread(&sregs);                    /* Get segment registers' values */
  61.   regs.x.ax = 0x1A00;                 /* DOS function Set Disk Transfer Area */
  62.   regs.x.dx = (unsigned int) dta;     /* Address of our DTA */
  63.   int86x(0x21,®s,®s,&sregs);    /* Call DOS to set up new DTA */
  64. }
  65.  
  66. /***********************************************************/
  67. /*                       INITIALIZE                        */
  68. /* This function will initialize the program. Mainly it    */
  69. /* will clear the screen, print some headings and invoke   */
  70. /* the function to set up a new DTA for the program.       */
  71. /***********************************************************/
  72.  
  73. void initialize(dta)
  74. struct dta_type *dta; {                /* Pointer to DTA */
  75.   vcls();                              /* Clear the screen */
  76.   set_dta(dta);                        /* Establish Disk Transfer Area */
  77.   printf("\n\n\n");
  78.   printf("       File Name       Size       Date        Time      Attribute\n");
  79.   printf("      ------------    ------    --------    --------  -------------\n");
  80. }
  81.  
  82. /**********************************************************/
  83. /*                        FIRSTFILE                       */
  84. /*  This function will find the first file that matches   */
  85. /*  search argument.  First a call is made to DOS to set  */
  86. /*  up a Disk Transfer Area in a structure dta.  Next the */
  87. /*  call is made to find the first file.  When the file is*/
  88. /*  found DOS will pass information about the file back to*/
  89. /*  us in the Disk Transfer area that we set up.          */
  90. /**********************************************************/
  91.  
  92. int firstfile(s_arg)
  93. char   *s_arg; {                      /* Pointer to the search argument */
  94.  
  95.   union  REGS regs;
  96.   struct SREGS sregs;
  97.  
  98.   segread(&sregs);                    /* Get segment registers */
  99.   regs.x.ax = 0x4e00;                 /* DOS function Find First File */
  100.   regs.x.dx = (unsigned int) s_arg;   /* Offset of search argument */
  101.   regs.x.cx = 0x003f;                 /* File Attribute = ALL */
  102.   int86x(0x21,®s,®s,&sregs);    /* Call DOS to find first file */
  103.  
  104.   if (regs.x.ax == 0)                 /* if no error occured then */
  105.      return(TRUE);                    /* return a true condition */
  106.   else
  107.      return(FALSE);                   /* otherwise .... */
  108. }
  109.  
  110. /***********************************************************/
  111. /*                         NEXTFILE                        */
  112. /*  This function is much like the last except it gets the */
  113. /*  next file which matchs our search argument.  It passes */
  114. /*  back a flag = FALSE when no more files are found       */
  115. /***********************************************************/
  116.  
  117. int nextfile(void) {
  118.  
  119.   union REGS regs;
  120.  
  121.   regs.x.ax = 0x4f00;                  /* DOS function for nextfile */
  122.   int86(0x21,®s,®s);             /* Call DOS */
  123.   if (regs.x.ax == 0)                  /* Check for an error or no more */
  124.      return(TRUE);                     /* files. */
  125.   else
  126.      return(FALSE);
  127. }
  128.  
  129. /***********************************************************/
  130. /*                          PFILE                          */
  131. /* This function will print all the pertinate information  */
  132. /* about the file retrieved such as its name, time & date  */
  133. /* created, and its attribute (read-only, hidden, system   */
  134. /* etc...).                                                */
  135. /***********************************************************/
  136.  
  137. void pfile(dta,fcount)
  138. struct dta_type *dta;
  139. int fcount;               {
  140.  
  141.    int      hour,min,sec,year,day,month;  /* variables to get from dta */
  142.    char     attribute[16];                /* pointer to attribute description */
  143.    long     size;                         /* size of file */
  144.    int      dattr;                        /* debug only */
  145.    char     *pr1, *pr2;                   /* print strings */
  146.    char     name[9], extention[4];        /* File Name & Extention */
  147.    char     *wrk;
  148.  
  149.    pr1 = "      %-8s %-3s    %6ld    %02d/%02d/%02d    %02d:%02d:%02d  %s\n";
  150.    pr2 = "      %-8s %-3s    %6ld    %02d/%02d/%02d    %02d:%02d:%02d  %s";
  151.  
  152.    attribute[0] = '\0';
  153.  
  154.    size = dta->fsize;
  155.    hour = dta->fhour;                  /* Hour from bit field */
  156.    min  = dta->fmin;                   /* Minute from bit field */
  157.    sec  = dta->fsec * 2;               /* Seconds * 2 from bit field */
  158.    year = (dta->fdate & 0xfe00) >> 9;  /* mask & shift to get year */
  159.    month =(dta->fdate & 0x01e0) >> 5;  /* mask & shift to get month */
  160.    day  = (dta->fdate & 0x001f);       /* just mask to get day */
  161.    year += 80;                         /* year + 1980 */
  162.  
  163.    if ((wrk = strchr(dta->fname,'.')) == NULL) { /* Find Extention */
  164.       strcpy(name, dta->fname);
  165.       strcpy(extention, "   ");
  166.    }
  167.    else  {
  168.       if (strcmp(dta->fname, wrk) != 0) {   /* Is it ".." or "." */
  169.          *wrk = '\0';                       /* No - delimit name & ext */
  170.          strcpy(name, dta->fname);          /* Copy file name */
  171.          strcpy(extention, ++wrk);          /* Copy extention */
  172.       }
  173.       else  {
  174.          strcpy(name, dta->fname);          /* Copy ".." or "." */
  175.          strcpy(extention, "   ");          /* Put spaces into ext. */
  176.       }
  177.    }
  178.  
  179.    if ((dta -> fattrib & 0x01) == 0x01)
  180.       strcat(attribute,"R ");              /* Read Only    */
  181.    else
  182.       strcat(attribute,". ");
  183.    if ((dta -> fattrib & 0x02) == 0x02)
  184.       strcat(attribute,"H ");              /* Hidden       */
  185.    else
  186.       strcat(attribute,". ");
  187.    if ((dta -> fattrib & 0x04) == 0x04)
  188.       strcat(attribute,"S ");              /* System       */
  189.    else
  190.       strcat(attribute,". ");
  191.    if ((dta -> fattrib & 0x08) == 0x08)
  192.       strcat(attribute,"V ");              /* Volume Label */
  193.    else
  194.       strcat(attribute,". ");
  195.    if ((dta -> fattrib & 0x10) == 0x10)
  196.       strcat(attribute,"D ");              /* Directory    */
  197.    else
  198.       strcat(attribute,". ");
  199.    if ((dta -> fattrib & 0x20) == 0x20)
  200.       strcat(attribute,"Arc");              /* Archive      */
  201.    else
  202.       strcat(attribute,"...");
  203.  
  204.  
  205.    if (fcount % 12 == 0 && pause){          /* If pause then stop */
  206.       while(!kbhit());                      /* and wait for a key */
  207.       getch();
  208.    }
  209.  
  210.    if (fcount >= 13) {
  211.       printf(pr2,
  212.           name,extention,size,month,day,year,hour,min,sec,attribute);
  213.       scroll(6,2,18,79,7,0,-1);
  214.       set_cursor_pos(18,1);
  215.    }
  216.    else
  217.       printf(pr1,
  218.           name,extention,size,month,day,year,hour,min,sec,attribute);
  219. }
  220.  
  221. /**********************************************************/
  222. /*                       FREE_SPACE                       */
  223. /* This function will print the total number of files     */
  224. /* listed along with the total disk space, total disk     */
  225. /* space used, total disk space available, and percent of */
  226. /* free disk space.  We are going to use the DOS function */
  227. /* Get Free Disk Space (Int 0x21 function 0x36) to do all */
  228. /* of this fancy stuff.   Upon return from the DOS call   */
  229. /* the registers will reflect the following:              */
  230. /* AX = sectors per cluster.                              */
  231. /* BX = number of available clusters.                     */
  232. /* CX = bytes per sector.                                 */
  233. /* DX = total number of clusters.                         */
  234. /**********************************************************/
  235.  
  236. void free_space(fcount,drive)
  237. int fcount; int drive; {
  238.  
  239.   union  REGS regs;                    /* Set up registers of course */
  240.   unsigned long   total,avail,used;    /* Need longs for big numbers */
  241.   int    percent;                      /* Nuff said?  */
  242.  
  243.   regs.x.ax = 0x3600;                  /* DOS function Free Space */
  244.   regs.x.dx = drive;                   /* Set for specified drive */
  245.   int86(0x21,®s,®s);             /* Call DOS */
  246.  
  247.   if (regs.x.ax == 0xffff) {           /* If an error then print a */
  248.      puts("*** Invalid Drive Specification ***"); /* nasty message */
  249.      exit(16);                                    /* and return home */
  250.   }
  251.   total = (long) regs.x.dx * regs.x.cx * regs.x.ax; /* Total bytes on disk */
  252.   avail = (long) regs.x.ax * regs.x.bx * regs.x.cx; /* Available bytes */
  253.   used  = total - avail;                            /* Total used */
  254.   percent = (avail * 100) / total;                  /* % of free space */
  255.  
  256.   puts(" ");
  257.   printf("            %3d file(s)  %8ld total disk space\n",fcount, total);
  258.   printf("                         %8ld total disk space available\n",avail);
  259.   printf("                         %8ld total disk space used\n",used);
  260.   printf("                         %8d percent free disk space\n",percent);
  261. }
  262.  
  263. /**********************************************************/
  264. /*                           PARSER                       */
  265. /* This function will parse the command line for a drive  */
  266. /* specification.  If it is present then the drive spec   */
  267. /* will be used when we call free_space so that we use the*/
  268. /* correct disk drive.   Default drive = 0, A drive = 1,  */
  269. /* B drive = 2, etc....                                   */
  270. /* Changed code to append "*.*" if no file spec was       */
  271. /* entered.  Example:                                     */
  272. /*   cdir a:  will turn into cdir a:*.*                   */
  273. /*   cdir \dos\ will turn into cdir \dos\*.*              */
  274. /**********************************************************/
  275.  
  276. int parser(arg)
  277. char arg[];    {
  278.  
  279.   int  retval = 0;                  /* Assume Defualt Drive */
  280.   char *wrk;                        /* Character Work Pointer */
  281.  
  282.   if (arg[1] == ':')  {             /* If second char is ':' then return */
  283.      retval = toupper(arg[0]) - 64; /* Covert to numeric */
  284.      if (arg[2] == '\0')            /* Char after ':' a null? */
  285.         strcat(arg, "*.*");         /* Yes! - concatenate wildcard */
  286.    }
  287.    if ((wrk = strrchr(arg, '\\')) != NULL) {
  288.       if (*(wrk + 1) == NULL) {
  289.          strcat(arg, "*.*");
  290.       }
  291.    }
  292.    return(retval);
  293. }
  294.  
  295. /***********************************************************/
  296. /*                       PARSE_COMMAND                     */
  297. /*                                                         */
  298. /* This function does two things:  Takes all command line  */
  299. /* arguments and converts the alpha characters to upper    */
  300. /* case.  Secondly, it searches the arguments for "/P" and */
  301. /* returns TRUE indicating that the user wants to pause    */
  302. /* after one full page of output.                          */
  303. /***********************************************************/
  304.  
  305. int parse_command(argc, argv)
  306. int  argc;
  307. char *argv [];
  308.  
  309. {
  310.    int  i;
  311.    char *wrk;
  312.  
  313.    for (i = 1; i < argc; i++) {             /* Change all alpha chars */
  314.        wrk = argv[i];                       /* In command line args to*/
  315.        while(*wrk) {                        /* Upper Case             */
  316.           *wrk = toupper(*wrk);
  317.           wrk++;
  318.        }
  319.    }
  320.  
  321.    for (i = 1; i < argc; i++) {             /* Now search for the */
  322.        wrk = argv[i];                       /* "/P" in one of the */
  323.        if (strcmp(wrk, "/P")  == 0)         /* Arguments          */
  324.           return(TRUE);
  325.    }
  326.    return(FALSE);
  327. }
  328.  
  329.  
  330. /******************************/
  331. /*             MAIN           */
  332. /******************************/
  333. int main(argc,argv)
  334. int  argc;
  335. char *argv[];   {
  336.  
  337.   struct dta_type dta;
  338.   int    fcount = 0, drive =0;
  339.   char   *arg;
  340.  
  341.   set_int24();
  342.   pause = parse_command(argc, argv);
  343.  
  344.   if (pause && argc > 2) {
  345.      arg = argv[1];
  346.      drive = parser(arg);
  347.   }
  348.   else
  349.      if (pause && argc > 1)
  350.         arg = "*.*";
  351.      else
  352.         if (argc > 1) {
  353.            arg = argv[1];
  354.            drive = parser(arg);
  355.         }
  356.         else
  357.            arg = "*.*";
  358.  
  359.   initialize(&dta);                    /* Initialize the program */
  360.   if (firstfile(arg)) {                /* Is there a first file? */
  361.     do {
  362.       fcount += 1;                     /* Yes - print file name until */
  363.       pfile(&dta,fcount);              /* no more matches */
  364.     }
  365.     while (nextfile());
  366.     free_space(fcount,drive);          /* And then print info about */
  367.   }                                    /* the disk */
  368.   else {
  369.     puts("*** No matching files ***");
  370.     free_space(fcount,drive);
  371.     return(16);
  372.   }
  373.   return (0);
  374. }
  375.