home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / dirutl / df_uz.arc / df.c < prev    next >
C/C++ Source or Header  |  1989-07-13  |  7KB  |  262 lines

  1. /*
  2.  *    DF - report disk space        Ver. 1.1
  3.  *
  4.  *        COPYRIGHT (C) 1989 by Urs Zurbuchen
  5.  *            ALL RIGHTS RESERVED
  6.  *
  7.  *        You are granted to the right to copy and
  8.  *        distribute this program via any means
  9.  *        as long as you don't remove this notice.
  10.  *
  11.  *        However, you are specifically prohibited
  12.  *        from charging, requesting any donations,
  13.  *        and from distributing it with commercial
  14.  *        products without prior written permission.
  15.  *
  16.  *    ------------------------------------------------------------
  17.  *
  18.  *    Displays a space usage statistic for all known drives in the
  19.  *    systems. For join'ed drives their real free space is reported.
  20.  *    Floppy sizes are only reported on request and if there is really
  21.  *    a floppy in the drive. If there is none, the program continues
  22.  *    without an error message.
  23.  *
  24.  *    Example:
  25.  *        C\:> df -f
  26.  *        Total space     Free space            Drive
  27.  *            362'496        131'072     36%      a:
  28.  *          2'060'288      1'155'072     56%      c:
  29.  *         40'607'744      8'216'576     20%      d:
  30.  *         67'051'520      5'554'176      8%      e:
  31.  *         12'976'128      7'417'856     57%      f:
  32.  *            518'912        518'912    100%      g:
  33.  *
  34.  *
  35.  *    Date:    16 January 1988
  36.  *    Author:    Urs Zurbuchen
  37.  *
  38.  *    Compile:
  39.  *        cl df.c        (for Microsoft C)
  40.  *
  41.  *    Revision history
  42.  *    When        Who        What
  43.  *    30. 4.1989    zu        Support for options -d and -f
  44.  *                    Prepared for submission to Usenet.
  45.  *
  46.  *    Last released:
  47.  *    30. 4.1989    Ver. 1.1    Usenet, comp.binaries.ibm.pc
  48.  *
  49.  *---------------------------------------------------------------------------
  50.  */
  51.  
  52. #include <stdio.h>
  53. #include <dos.h>
  54. #include <string.h>
  55. #include <process.h>
  56. #include <stdlib.h>
  57. #include <setjmp.h>
  58.  
  59.  
  60. long        zehner[3] = { 1000000, 1000, 1 };
  61. jmp_buf        jb;
  62. char        error_handler[4] = { 0xb8, 0, 0, 0xcf };
  63.  
  64. #ifdef    LINT_ARGS
  65. char    *basename( char * );
  66. int    main( int, char ** );
  67. void    print_number( long );
  68. void    print_statistics( unsigned char );
  69. void    setvector( unsigned int );
  70. void    Usage( char * );
  71. #endif
  72.  
  73.  
  74. int main( argc, argv )
  75. int    argc;
  76. char    **argv;
  77. {
  78.     union REGS    inregs, outregs;
  79.     struct SREGS    segregs;
  80.     int        drives, floppies;
  81.     int        NoFloppies = 1, NoDisks = 0;
  82.     unsigned int    olderr_offset, olderr_segment;
  83.     unsigned char    i;
  84.     void        print_statistics(), setvector();
  85.     
  86.     /* initialize for error handling */
  87.     inregs.x.ax = 0x3524;        /* get error handler vector    */
  88.     intdosx( &inregs, &outregs, &segregs );
  89.     olderr_offset = outregs.x.bx;
  90.     olderr_segment= segregs.es;
  91.     setvector( (unsigned int)error_handler );
  92.  
  93.     /* parse command line arguments */
  94.     if( argc > 1 ) {
  95.         for( i = (unsigned char) 1; (int)i < argc; i++ ) {
  96.             if( argv[i][0] == '-' ) {
  97.                 switch( argv[i][1] ) {
  98.                     case '?':
  99.                     case 'h':
  100.                     Usage( argv[0] );
  101.                     exit( -1 );
  102.                     break;
  103.                     case 'f':
  104.                     NoFloppies = 0;
  105.                     break;
  106.                     case 'd':
  107.                     NoDisks = 1;
  108.                     break;
  109.                     default:
  110.                     fprintf( stderr, "Unknown option %c\n",
  111.                         argv[i][1] );
  112.                     Usage( argv[0] );
  113.                     break;
  114.                 }
  115.             } else if( strlen( argv[i] ) == 2 && argv[i][1] == ':' ) {
  116.                 print_statistics( (unsigned char)tolower( (int)argv[i][0] ) -
  117.                           (int)'a' );
  118.                 exit( 0 );
  119.             } else {
  120.                 fprintf( stderr, "df: invalid argument %s\n",
  121.                      argv[i] );
  122.                 Usage( argv[0] );
  123.                 exit( 1 );
  124.             }
  125.         }
  126.     }
  127.     
  128.     /* determine number of logical drives in system */
  129.     inregs.h.ah = 0x19;        /* get current disk        */
  130.     intdos( &inregs, &outregs );
  131.     inregs.h.dl = outregs.h.al;
  132.     inregs.h.ah = 0x0e;        /* select disk            */
  133.     intdos( &inregs, &outregs );
  134.     drives = outregs.h.al;
  135.     /* we now have the number of logical drives. But, this number    *
  136.      * might be wrong. It is just the value of the 'lastdrive='    *
  137.      * command in config.sys which defaults to five if not specified*
  138.      * We will have to test for the drives presence anyway.        */
  139.      
  140.     /* determine number of physical floppy drives in system */
  141.     int86( 0x11, &inregs, &outregs );    /* equipment determination */
  142.     floppies = ( outregs.h.al & 0x01 ) ? ( outregs.h.al >> 6 ) +1 : 0;
  143.     
  144.     /* now print statistics */
  145.     /* - for floppies    */
  146.     if( NoFloppies == 0 )
  147.         for( i = (unsigned char) 0; (int)i < floppies; i++ )
  148.             print_statistics( i );
  149.     
  150.     /* - for harddisks    */
  151.     if( NoDisks == 0 )
  152.         for( i = (unsigned char) 2; (int)i < drives; i++)
  153.             print_statistics( i );
  154.  
  155.     /* restore vector for error handling */
  156.     inregs.x.ax = 0x2524;        /* get error handler vector    */
  157.     outregs.x.dx = olderr_offset;
  158.     segregs.ds   = olderr_segment;
  159.     intdosx( &inregs, &outregs, &segregs );
  160.  
  161.     return( 0 );
  162. }
  163.  
  164. void print_statistics( drive )
  165. unsigned char    drive;
  166. {
  167.     union REGS    iregs, oregs;
  168.     long        total, free;
  169.     static int    firsttime = 0;
  170.     void        print_number();
  171.     int        checkdrive();
  172.  
  173.     if( firsttime++ == 0 )
  174.         printf( "Total space     Free space            Drive\n" );
  175.  
  176.     /* Try to print the statistics. If we try to read an inexistent    *
  177.      * drive the operating system calls its 'fatal error' handler    *
  178.      * (via INT 24h). Because we redirected this vector we will get    *
  179.      * control again in case of an error. In such a case the program*
  180.      * just continues with the next drive.                */
  181.     if( setjmp( jb ) != 0 )
  182.         return;
  183.  
  184.     iregs.h.ah = 0x36;        /* get disk space        */
  185.     iregs.h.dl = drive +1;
  186.     intdos( &iregs, &oregs );
  187.     if( oregs.x.ax != 0xffff ) {
  188.         total = (long)oregs.x.ax * (long)oregs.x.cx * (long)oregs.x.dx;
  189.         free  = (long)oregs.x.ax * (long)oregs.x.cx * (long)oregs.x.bx;
  190.         print_number( total );
  191.         print_number( free  );
  192.         printf( "%3.1ld%%    ", free / (total / 100L) );
  193.         printf( "  %c:\n", drive + 'a' );
  194.     }
  195. }
  196.  
  197. void print_number( n )
  198. long    n;
  199. {
  200.     int    i = 0, has_printed = 0;
  201.     long    c;
  202.  
  203.     /* if the number is greater than 999'999'999 we output it as it is */
  204.     if( n > 999999999 )
  205.         printf( "%ld", n );
  206.     else
  207.         while( i < 3 ) {
  208.             if( has_printed )
  209.                 printf( "'" );
  210.             if( (c = n / zehner[i] ) >= 1L ) {
  211.                 printf( (has_printed ? "%.3ld" : "%3.1ld"), c );
  212.                 has_printed = 1;
  213.             } else
  214.                 printf( has_printed ? "000" : "    " );
  215.             n %= zehner[i++];
  216.         }
  217.     printf( "    " );
  218. }
  219.  
  220.  
  221. void setvector( func )
  222. unsigned int func;
  223. {
  224.     union REGS    inregs, outregs;
  225.     struct SREGS    segregs;
  226.  
  227.     segread( &segregs );        /* pick up segment registers    */
  228.     inregs.x.ax = 0x2524;        /* set our error handler vector    */
  229.     inregs.x.dx = func;
  230.     intdosx( &inregs, &outregs, &segregs );
  231. }
  232.  
  233.  
  234. void Usage( prog )
  235. char *prog;
  236. {
  237.     fprintf( stderr, "Usage is:\n" );
  238.     fprintf( stderr, "%s: [-? | -h] [-f | -d] [d:]\n", strlwr( basename( prog )) );
  239.     fprintf( stderr, "        -?, -h    display this message\n" );
  240.     fprintf( stderr, "        -f        check floppies, too\n" );
  241.     fprintf( stderr, "        -d        do not check harddisks\n" );
  242.     fprintf( stderr, "        d:        check only drive d:\n" );
  243.     return;
  244. }
  245.  
  246. char *basename( name )
  247. char *name;
  248. {
  249.     char    *pos;
  250.  
  251.     if( (pos = strrchr( name, '/' )) == NULL &&
  252.         (pos = strrchr( name, '\\' )) == NULL )
  253.             pos = name;
  254.     else
  255.         pos++;
  256.  
  257.     return( pos );
  258. }
  259.  
  260.  
  261.  
  262.