home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 201_01 / fdires.c < prev    next >
Text File  |  1979-12-31  |  14KB  |  534 lines

  1.  
  2. /****************************************************************************/
  3. /*                                        */
  4. /*     FDIRES.C   Version 1.3  3/6/86               Brian Irvine        */
  5. /*                                        */
  6. /*      Released to the Public Domain for use without profit            */
  7. /*                                        */
  8. /****************************************************************************/
  9. /*                                        */
  10. /* fdires.c - Program to demonstrate use of stayres.c in creating a        */
  11. /*          terminate-and-stay-resident program in DeSmet C.            */
  12. /*                                        */
  13. /*          This program demonstrates the techniques used to create a     */
  14. /*          program which will terminate but remain resident as part        */
  15. /*          of DOS.  The program is a sorted directory displayer which    */
  16. /*          will show a sorted and formatted listing of files on the        */
  17. /*          current directory.  It is supplied mainly to demonstrate        */
  18. /*          the techniques involved in creating TSR programs.         */
  19. /*                                        */
  20. /*          The program is activated with the Alt F-10 key.  This will    */
  21. /*          display a sorted listing of the files on the current        */
  22. /*          directory.  The display will remain until a key is pressed.   */
  23. /*          If the Ctrl F-10 key is pressed, the program will be        */
  24. /*          removed from memory and you will be returned to DOS.        */
  25. /*          Do NOT exit this way if you are running FDIRES from within    */
  26. /*          an application program.  You will bomb the computer when        */
  27. /*          you try to return to your application.  Pressing any key        */
  28. /*          other than Ctrl F-10 will return you to your application.     */
  29. /*                                        */
  30. /*          The program must be linked with the other module in this        */
  31. /*          library using the -s option of bind with a stack allowance    */
  32. /*          of 0x1000 (4096 decimal).  This should be more than        */
  33. /*          adequate for 99% of all applications.                */
  34. /*                                        */
  35. /*          This code is based in part on a set of routines written by    */
  36. /*          Lane Ferris et al which are available on the Borland SIG on   */
  37. /*          Compuserve.                            */
  38. /*                                        */
  39. /*           Brian Irvine                            */
  40. /*           3379 St Marys Place                        */
  41. /*           Santa Clara, CA 95051                        */
  42. /*           [71016,544]                            */
  43. /*                                        */
  44. /****************************************************************************/
  45. /*                                        */
  46. /* Revisions:                                    */
  47. /*     version 1.0 - 10/85                            */
  48. /*     Initial release                                */
  49. /*                                        */
  50. /*     version 1.20 - 3/3/86                            */
  51. /*     Added code to remove program from memory.                */
  52. /*     New version of resident code                        */
  53. /*                                        */
  54. /*     version 1.30 - 3/6/86                            */
  55. /*     Added code to check for program already in memory            */
  56. /*                                        */
  57. /****************************************************************************/
  58.  
  59. #include   <stdio.h>
  60.  
  61. #define    KILL_CHAR       255
  62. #define    MAX_DIRS       1000
  63.  
  64. #define    KB_INT       0x16
  65. #define    DOS_INT       0x21
  66. #define    GET_DRV       0x19
  67.  
  68. #define    FILE_NOT_FOUND  2           /* DOS function error codes */
  69. #define    INVALID_DRIVE   15
  70. #define    NO_MORE_FILES   18
  71.  
  72. struct {
  73.     char   reserved[21];           /* disk transfer area */
  74.     char   attribute;
  75.     int    time;
  76.     int    date;
  77.     long   file_size;
  78.     char   name[13];
  79.     } dta;
  80.  
  81. struct dir_entry{               /* directory entry */
  82.     char    e_attribute;
  83.     int    e_time;
  84.     int    e_date;
  85.     long    e_file_size;
  86.     char    e_name[13];
  87.     } entry[MAX_DIRS];           /* enough room for 1000 entries */
  88.  
  89. long   free_space;
  90. long   total_space;
  91. int    entries = 0;
  92. int    _rax, _rbx, _rcx, _rdx,       /* variables to hold register values */
  93.           _rsi, _rdi, _rds, _res;
  94. int    row, column;           /* cursor position - must be global */
  95.  
  96. extern char    _carryf;
  97.  
  98. char   label [12];
  99. char   pathname [65];
  100. char   buffer [65];
  101. static char   save_screen[4000];      /* save the screen here */
  102. long   get_free ();
  103.  
  104. extern unsigned old_kbint_off;
  105. extern unsigned old_kbint_seg;
  106. extern int     check_dupe();   /* the code to prevent loading program twice */
  107. extern void    stayres();      /* the code to terminate and stay resident */
  108.  
  109.  
  110. /*----- Main ---------------------------------------------------------------*/
  111. /*                                        */
  112. /*     In this application all we have to do is call the tsr code.  Other   */
  113. /*     initialization can be performed here before fencing ourselves off.   */
  114. /*                                        */
  115. /*--------------------------------------------------------------------------*/
  116.  
  117. main ()
  118. {
  119.  
  120.    /* first thing is to check to see if program is already loaded */
  121.  
  122.    if ( check_dupe () )
  123.        puts("\nFDIRES is already in memory.\n\n");
  124.    else
  125.        stayres ();
  126.  
  127. }
  128.  
  129. /*----- Main program entry point -------------------------------------------*/
  130.  
  131. fdir ()
  132. {
  133.  
  134.    char    ch;
  135.    int       n, stat, curr_drv;
  136.    int       mode;
  137.    unsigned    screen_seg;
  138.  
  139.    /* get the video mode */
  140.  
  141.    mode = get_mode ();
  142.  
  143.    /* save the user's screen and cursor position */
  144.  
  145.    find_cursor ();
  146.    if ( mode == 7 )
  147.        screen_seg = 0xB000;
  148.    else
  149.        screen_seg = 0xB800;
  150.    _lmove ( 4000, 0, screen_seg, save_screen, _showds() );
  151.    scr_clr ();
  152.    scr_rowcol (0,0);
  153.  
  154.    entries = 0;
  155.    _setmem (buffer, 65, '\0' );        /* initialize buffers explicitly each */
  156.    _setmem (pathname, 65, '\0' );      /* time through because it changes */
  157.    if ( get_path () == ERR )
  158.        {
  159.        puts ("Invalid drive specifier.\n");
  160.        exit(1);
  161.        }
  162.  
  163. /*     Now construct the path name using current drive                */
  164.  
  165.    curr_drv = get_curr_drv ();
  166.    buffer[0] = curr_drv + 'A';
  167.    buffer[1] = ':';
  168.    if ( strlen ( pathname ) == 0 )
  169.        buffer[2] = '\0';
  170.    else
  171.        {
  172.        buffer[2] = '\\';
  173.        buffer[3] = '\0';
  174.        }
  175.  
  176.    strcat ( buffer, pathname );
  177.    strcpy ( pathname, buffer );
  178.    n = ( 80 - strlen ( pathname ) - 14 ) / 2;
  179.    strncpy ( buffer, "                                ", n);
  180.    strcat ( buffer, "Directory of " );
  181.    strcat ( buffer, pathname );
  182.    printf ( "%s\n\n", buffer );
  183.    set_dta ();
  184.  
  185. /*     Get the first matching directory entry                    */
  186.  
  187.    if ( get_first () )
  188.        {
  189.        puts ("File not found.\n");
  190.        exit (1);
  191.        }
  192.  
  193. /*     Now collect all the other matching names                 */
  194.  
  195.    while ( ( stat = get_next () ) != NO_MORE_FILES )
  196.        ;
  197.    free_space = get_free ();
  198.    sort_files ();
  199.    print_files ();
  200.  
  201.    /* now put everything back where it was */
  202.  
  203.    puts ("\nPress any key to continue...");
  204.    while ( ( ch = scr_csts() ) == 0 )
  205.        ;
  206.    if ( ch == KILL_CHAR )      /* if we want to get rid of the program then */
  207.        {
  208.        purge();            /* reset the keyboard vector and free memory */
  209.        exit(0);
  210.        }
  211.    else
  212.        {
  213.        _lmove ( 4000, save_screen, _showds(), 0, screen_seg );
  214.        scr_rowcol ( row, column );
  215.        }
  216.  
  217.  
  218. }
  219.  
  220.  
  221.  
  222. /*----- Kill the resident program ------------------------------------------*/
  223.  
  224. void   purge ()
  225. {
  226.  
  227. unsigned   psp, envptr;
  228.  
  229.    psp = _showcs() - 0x10;
  230.    _lmove(2, 0x2C, psp, &envptr, _showds());
  231.  
  232.    puts ("\n\nFDIRES terminated. Urghhh...\n\n");
  233.  
  234. /* reset the keyboard interrupt service vector */
  235.  
  236.    _rds = old_kbint_seg;
  237.    _rdx = old_kbint_off;
  238.    _rax = 0x2500 + KB_INT;
  239.    _doint ( DOS_INT );
  240.  
  241. /* free up the program memory */
  242.  
  243.    _rax = 0x4900;
  244.    _res = psp;               /* point to beginning of PSP for EXE file */
  245.    _doint ( DOS_INT );
  246.  
  247. /* free up the environment area */
  248.  
  249.    _rax = 0x4900;
  250.    _res = envptr;           /* point to environment area */
  251.    _doint ( DOS_INT );
  252.  
  253. }
  254.  
  255.  
  256. /*----- Get the current drive number ---------------------------------------*/
  257.  
  258. int    get_curr_drv ()
  259. {
  260.  
  261.    return ( _os ( GET_DRV, 0 ) );
  262.  
  263. }
  264.  
  265.  
  266.  
  267. /*----- Get path name of current directory ---------------------------------*/
  268.  
  269. int    get_path ()
  270. {
  271.  
  272.    _rax = 0x4700;
  273.    _rdx = 0;
  274.    _rsi = &pathname[0];
  275.    _rds = _showds();
  276.    _doint ( DOS_INT );
  277.    if ( _carryf )
  278.        return ERR;
  279.  
  280. }
  281.  
  282.  
  283.  
  284. /*----- Give the DTA address to DOS ----------------------------------------*/
  285.  
  286. void   set_dta ()
  287. {
  288.  
  289.    _rax = 0x1A00;
  290.    _rdx = &dta;
  291.    _rds = _showds();
  292.    _doint ( DOS_INT );
  293.  
  294. }
  295.  
  296.  
  297.  
  298. /*----- Get the first matching directory entry -----------------------------*/
  299.  
  300. int    get_first ()
  301. {
  302.  
  303.    strcat ( pathname,"\\*.*" );    /* look for all files */
  304.    _rax = 0x4E00;
  305.    _rdx = &pathname;
  306.    _rcx = 0xFF;            /* attribute = all */
  307.    _doint ( DOS_INT );
  308.    if ( _carryf )           /* if there's an error */
  309.        return  ( _rax );       /* send back the code */
  310.    _move ( 22, &dta.attribute, &entry[entries++] );    /* else move data to array */
  311.    return ( 0 );
  312.  
  313. }
  314.  
  315.  
  316.  
  317. /*----- Get next matching directory entry ----------------------------------*/
  318.  
  319. void   get_next ()
  320. {
  321.  
  322.    _rax = 0x4F00;
  323.    _doint ( DOS_INT );
  324.    if ( _carryf )
  325.        return  ( _rax );
  326.    _move ( 22, &dta.attribute, &entry[entries++] );
  327.    return ( 0 );
  328.  
  329. }
  330.  
  331.  
  332. /*----- Get free space left on disk ----------------------------------------*/
  333.  
  334. long   get_free ()
  335. {
  336.  
  337.    _rdx = 0;
  338.    _rax = 0x3600;
  339.    _doint ( DOS_INT );
  340.    total_space = ((long) ( (long)_rax * (long)_rdx * (long)_rcx ));
  341.    return ((long) ( (long)_rax * (long)_rbx * (long)_rcx ));
  342.  
  343. }
  344.  
  345.  
  346.  
  347. /*----- Comparison routine for qsort() -------------------------------------*/
  348.  
  349. int    compare ( first, second )
  350. struct dir_entry *first, *second;
  351. {
  352.  
  353.    return ( strcmp (first -> e_name, second -> e_name ) );
  354.  
  355. }
  356.  
  357.  
  358.  
  359. /*----- Sort the directory entries by name ---------------------------------*/
  360.  
  361. void   sort_files ()
  362. {
  363.  
  364.    qsort ( entry, entries, 22, compare );
  365.  
  366. }
  367.  
  368.  
  369.  
  370. /*----- Get the cursor location --------------------------------------------*/
  371.  
  372.  
  373. void   find_cursor()
  374. {
  375.    _rax = 0x0300;
  376.    _rbx = 0;
  377.    _doint(0x10);
  378.    row = _rdx >> 8;
  379.    column = _rdx & 0x00FF;
  380.  
  381. }
  382.  
  383.  
  384. /*----- Get the current video mode -----------------------------------------*/
  385.  
  386. int    get_mode ()
  387. {
  388.    _rax = 0x0F00;
  389.    _doint ( 0x10 );
  390.    return ( _rax & 0x00FF );
  391.  
  392. }
  393.  
  394.  
  395. /*----- Print the directory entries and free space -------------------------*/
  396. /*                           this code needs to be redone */
  397.  
  398. void   print_files ()
  399. {
  400.    int i, middle, count, pm, dir, hour;
  401.    struct dir_entry *next;
  402.    char    namebuf[20];
  403.    char    extbuf [4];
  404.    char    *buf, *dirln;
  405.  
  406.    pm = hour = count = 0;
  407.    next = &entry;
  408.    middle = (entries + 1)/2;
  409.    puts ("───────────────────────────────────────┬───────────────────────────────────────\n");
  410.    puts ("Filename Ext   Size     Date     Time  │ Filename Ext   Size     Date     Time \n");
  411.    puts ("───────────────────────────────────────┼───────────────────────────────────────\n");
  412.    for ( count = 0; count < middle; count++ )
  413.        {
  414.        buf = &namebuf;
  415.        dirln = &entry[count].e_name;
  416.        *buf = '\0';
  417.        dir = FALSE;
  418.        if ( entry[count].e_attribute & 0x10 )
  419.        dir = TRUE;
  420.        while ( *dirln && (*dirln != '.'))
  421.        *buf++ = *dirln++;
  422.        *buf = '\0';
  423.        buf = &extbuf;
  424.        *buf = '\0';
  425.        if ( *dirln )
  426.        dirln++;
  427.        strcat( extbuf, dirln );
  428.        hour = ( entry[count].e_time >> 11 ) & 0x001F;
  429.        pm = FALSE;
  430.        if ( hour > 12 )
  431.        {
  432.        hour -= 12;
  433.        pm = TRUE;
  434.        }
  435.        if ( hour == 0 )
  436.        hour = 12;
  437.        if ( dir )
  438.        {
  439.        if ( strlen ( namebuf ) == 0 )
  440.            strcpy ( namebuf, "." );
  441.        else
  442.            ;
  443.        printf ("%-8s %-3s  [Dir]   %2d-%02d-%02d  %2d:%02d%1c │",
  444.            namebuf,
  445.            extbuf,
  446.            (entry[count].e_date >> 5) & 0x000F,
  447.            (entry[count].e_date & 0x001F),
  448.            (entry[count].e_date >> 9) + 80,
  449.            hour,
  450.            (entry[count].e_time >> 5) & 0x003F,
  451.            (pm) ? 'p' : 'a');
  452.        }
  453.        else
  454.        printf ("%-8s %-3s  %6D  %2d-%02d-%02d  %2d:%02d%1c │" ,
  455.            namebuf,
  456.            extbuf,
  457.            entry [count].e_file_size,
  458.            (entry[count].e_date >> 5) & 0x000F,
  459.            (entry[count].e_date & 0x001F),
  460.            (entry[count].e_date >> 9) + 80,
  461.            hour,
  462.            (entry[count].e_time >> 5) & 0x003F,
  463.            (pm) ? 'p' : 'a');
  464.        if ( (count + middle) < entries )
  465.        {
  466.        buf = &namebuf;
  467.        dirln = &entry[count + middle].e_name;
  468.        *buf = '\0';
  469.        dir = FALSE;
  470.        if ( entry[count+middle].e_attribute & 0x10 )
  471.            dir = TRUE;
  472.        while ( *dirln && (*dirln != '.'))
  473.            *buf++ = *dirln++;
  474.        *buf = '\0';
  475.        buf = &extbuf;
  476.        *buf = '\0';
  477.        if ( *dirln )
  478.            dirln++;
  479.        strcat( extbuf, dirln );
  480.        hour = ( entry[count + middle].e_time >> 11 ) & 0x001F;
  481.        pm = 0;
  482.        if ( hour > 12 )
  483.            {
  484.            hour -= 12;
  485.            pm = 1;
  486.            }
  487.        if ( hour == 0 )
  488.            hour = 12;
  489.        if ( dir )
  490.            {
  491.            if ( strlen ( namebuf ) == 0 )
  492.            strcpy ( namebuf, "." );
  493.            else
  494.            ;
  495.            printf (" %-8s %-3s  [Dir]   %2d-%02d-%02d  %2d:%02d%1c\n",
  496.                namebuf,
  497.                extbuf,
  498.                (entry[count+middle].e_date >> 5) & 0x000F,
  499.                (entry[count+middle].e_date & 0x001F),
  500.                (entry[count+middle].e_date >> 9) + 80,
  501.                hour,
  502.                (entry[count+middle].e_time >> 5) & 0x003F,
  503.                (pm) ? 'p' : 'a');
  504.            }
  505.        else
  506.            printf (" %-8s %-3s  %6D  %2d-%02d-%02d  %2d:%02d%1c\n" ,
  507.                namebuf,
  508.                extbuf,
  509.                entry [count+middle].e_file_size,
  510.                (entry[count+middle].e_date >> 5) & 0x000F,
  511.                (entry[count+middle].e_date & 0x001F),
  512.                (entry[count+middle].e_date >> 9) + 80,
  513.                hour,
  514.                (entry[count+middle].e_time >> 5) & 0x003F,
  515.                (pm) ? 'p' : 'a');
  516.        }
  517.        else
  518.        puts ("\n" );
  519.        if ( ( (count + 1) % 17 ) == 0 )
  520.        {
  521.        puts ("─────────────────────────── Press any key to continue ─────────────────────────\n");
  522.        while ( !scr_csts () )
  523.            ;
  524.        }
  525.        }
  526.    puts ("───────────────────────────────────────┼───────────────────────────────────────\n");
  527.    printf (" %3d directory %s                 │", entries, (entries > 1) ? "entries" : "entry  " );
  528.    printf ("  %D bytes free         %3d%% used\n", free_space, 100 * (total_space - free_space) / total_space );
  529.    puts ("───────────────────────────────────────┴───────────────────────────────────────\n");
  530.  
  531. }
  532.  
  533.  
  534.