home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / filutl / anywhere.arc / ANYWHERE.C next >
Text File  |  1987-05-17  |  25KB  |  792 lines

  1. /***************************************************************
  2. *                                   *
  3. *       WHERE                           *
  4. *                                   *
  5. * Where is a program to locate files on the PC hard disk.      *
  6. * It requires DOS 2.x or 3.x.                       *
  7. *                                   *
  8. * The command line syntax is:                       *
  9. * where [starting directory]filename.ext               *
  10. *                                   *
  11. * Written by Mark S. Ackerman                       *
  12. * PROGRAM IS WRITTEN IN MARK WILLIAMS  M W C 8 6  LANGUAGE     *
  13. * Copyright 1984, 1985 by Mark S. Ackerman.  Permission is     *
  14. * granted for unlimited copies if not sold or otherwise        *
  15. * exchanged for gain.                           *
  16. *  PUBLISHED IN PC TECH JOURNAL - OCT '85 - VOL 3, NO. 10      *
  17. *                                   *
  18. *  MODIFIED FOR LATTICE C VER 2.15 BY JOHN TEICHERT NOV 85     *
  19. *     Names shortened to 8 significant characters.           *
  20. *     Elimination of PTOREG() function                   *
  21. *     flag86 defined to return flags from intdosx()           *
  22. *     Use segread to set up regs for intdosx() function.       *
  23. *     Program modified to look for drive designator with colon.*
  24. *     DATE structure defined with bits high order to low order.*
  25. *     intrpt.h replaced with dos.h header file               *
  26. *     rindex() function replaced with strrchr() function.      *
  27. *                                   *
  28. *  MODIFIED FOR MICROSOFT V3 BY JOHN TEICHERT JAN 86.           *
  29. *     flag86 REDEFINED to dos_result for  intdosx() ax reg     *
  30. *     modified to use flag in REGS structure.               *
  31. *     DATE structure defined with bits low order to high order.*
  32. *     _stack will not produce large stack in ver 3.0 must use  *
  33. *         link option or exemod program.               *
  34. *                                   *
  35. *   Added Code And Became ANYWHERE  JOHN TEICHERT FEB 86       *
  36. *                                   *
  37. *    Taking advantange of V3 access to the environment      *
  38. *    string we set up the following.                *
  39. *                                   *
  40. *    1. An Environment String indicating what disk drives   *
  41. *       you want ANYWHERE to search as follows:           *
  42. *                                   *
  43. *       AWDISK=d:[;d:[;d:;...d:]]                   *
  44. *                                   *
  45. *          where d: is the drive specifier for one or more  *
  46. *          fixed disk(s).                       *
  47. *                                   *
  48. *          drive specifiers are searched in the order they  *
  49. *          are entered.                       *
  50. *                                   *
  51. *    2. The user can specify the environment string with    *
  52. *       the use of the set command in the autoexec.bat file.*
  53. *       As an example:                       *
  54. *                                   *
  55. *        set awdisks=c:;e:;d:                   *
  56. *                                   *
  57. *       would be placed into the autoexec.bat file.           *
  58. *                                   *
  59. *    With this modification the user has extended directory *
  60. *    capabilities by automatically searching all disk drives*
  61. *    listed in the environment string or isolated to a      *
  62. *    single drive by placing a drive specifier in the       *
  63. *    command line argument string.                   *
  64. *                                   *
  65. *    Be sure to use the /stack option on the link with      *
  66. *    Microsoft V3 C compiler or stack problems will result  *
  67. *    if many subdirectories.  8K seems to work well.        *
  68. *                                   *
  69. *                                   *
  70. *    Added a few little perks May 1987 - Michael L Kaufman  *
  71. *                                   *
  72. ***************************************************************/
  73.  
  74.  
  75. /***************************************************************
  76. * The C header files                           *
  77. * These identify library routines like printf() and int86x()  *
  78. ***************************************************************/
  79.  
  80. #include <stdio.h>   /* standard i/o                  */
  81. #include <dos.h>     /* functions for DOS interrupt calls     */
  82.  
  83. /***************************************************************
  84. * Structure for MS-DOS date and time fields               *
  85. * See pages 4-6 and 4-7 of the DOS 2.1 technical           *
  86. * reference manual for more information                *
  87. * This structure is used in the next structure definition      *
  88. ***************************************************************/
  89.  
  90. struct msdos_date
  91.     {
  92.     unsigned ms_sec    : 5; /* time in 2 sec. int (5 bits)*/
  93.     unsigned ms_min    : 6; /* minutes (6 bits)          */
  94.     unsigned ms_hour   : 5; /* hours (5 bits)          */
  95.     unsigned ms_day    : 5; /* day of month (5 bits)      */
  96.     unsigned ms_month  : 4; /* month (4 bits)          */
  97.     unsigned ms_year   : 7; /* year since 1980 (7 bits)   */
  98.     };
  99.  
  100. /***************************************************************
  101. * Definition of DOS Disk Transfer Area (DTA)               *
  102. ***************************************************************/
  103.  
  104. /***************************************************************
  105. * Structure filled in by MS-DOS for interrupt 21 calls           *
  106. * See page 5-46 of the DOS 2.1 technical reference           *
  107. * manual for more information                       *
  108. ***************************************************************/
  109.  
  110. struct DTA
  111.     {
  112.     char    DTA_dosinfo[21];       /* used by DOS        */
  113.     char    DTA_attr;           /* file attribute byte    */
  114.     struct msdos_date DTA_date;    /* date struct. as above */
  115.     long    DTA_size;           /* file size        */
  116.     char    DTA_filename[13];      /* file name (w/o path)    */
  117.     };
  118.  
  119.  
  120. /***************************************************************
  121. *        Definitions of constants               *
  122. ***************************************************************/
  123.  
  124. #define carry_set 0x0001 /* mask for flag register           */
  125.              /* for carry bit               */
  126. #define no_type   0x00     /* no bits set on file attribute byte */
  127. #define directory_type     0x10 /* directory file bit on file    */
  128.                   /* info word               */
  129.  
  130. #define no_more_files     18    /* DOS return code for        */
  131.                 /* no more files        */
  132.  
  133. #define end_of_string     '\0'   /* C uses a binary zero to      */
  134.                 /* signal end of string     */
  135.  
  136. #define backslash '\\'   /* the backslash character           */
  137. #define colon      ':'    /* Drive separator  JT 11/85           */
  138. #define semicolon ';'   /* Environment string drive separator   */
  139.  
  140. char *month[] = {
  141.         "Jan","Feb","Mar","Apr","May","Jun",
  142.         "Jul","Aug","Sep","Oct","Nov","Dec"
  143.         };
  144.  
  145. char *time_of_day[2] = {"AM","PM"};
  146.  
  147.  
  148. /***************************************************************
  149. *        Define the type "filename"                     *
  150. *            to be a string of 65 characters  -JT   *
  151. ***************************************************************/
  152.  
  153. typedef char filename[65];           /* Change to 65 -JT             */
  154.  
  155. /***************************************************************
  156. *                                   *
  157. * The following filename strings are used in the program:      *
  158. *                                   *
  159. *    chk_str         filename to be searched for    *
  160. *                filename in the command line)  *
  161. *    dir_string        directory name to be searched  *
  162. *    new_dstr        directory name to be searched  *
  163. *                  on next recursive call       *
  164. *    cur_str         temporary string for searching *
  165. *                  in a specific directory      *
  166. ***************************************************************/
  167.  
  168.  
  169. /***************************************************************
  170. * Definition of any forward-referenced functions           *
  171. ***************************************************************/
  172.  
  173. char *DATE();
  174. char *space();
  175.  
  176. /***************************************************************
  177. *        Global variables                   *
  178. ***************************************************************/
  179.  
  180. filename chk_str;            /* this string "remembers" user input */
  181. union    REGS    r8086;            /* structure to allow access to indiv.*/
  182.                     /*   registers for interrupts          */
  183. struct    SREGS    s8086;            /*   structure for segment registers  */
  184. char        date_str[40];        /* print output string for dates      */
  185. int        count=0;        /* Number of matches dislplayed      */
  186. char        spce[] = "                                           ";
  187. int        lastzero = 41;
  188. unsigned    dos_result;        /* Return code from DOS           */
  189.  
  190. /**
  191. *    FOLLOWING CODE COMMENTED OUT FOR V3.0 SINCE CAN'T FIND A WAY TO DO IT
  192. *    WITH A VARIABLE.
  193. **/
  194.  
  195. /*int          _stack = 8192;       Insure large stack to support */
  196. /*                       recursion in look routine     */
  197.  
  198. /***************************************************************
  199. *        MAIN() -- the beginning of the code           *
  200. ***************************************************************/
  201.  
  202. main( argc, argv, envp )
  203. int    argc;
  204. char    *argv[];
  205. char    *envp[];            /* Version 3 pointer to environ */
  206. {
  207. /**
  208. *    External    function
  209. **/
  210. char            *strrchr();    /* Lattice function which searches */
  211.                     /* for the last occurrance of the  */
  212.                     /* desired character           */
  213.  
  214. char            *strchr();    /* Lattice function which searches */
  215.                     /* for the first occurrance of the */
  216.                     /* desired character           */
  217.  
  218. filename           dir_string;    /* directory to be searched       */
  219.  
  220. char               *usr_file;    /* address of filename in       */
  221.                     /* command line argument       */
  222.                     /* (ie, the filename)           */
  223.  
  224. char *last_loc;             /* address of last backslash in    */
  225.                     /* command line argument       */
  226.  
  227. char *dos_parm;             /* address of               */
  228.                     /* command line argument       */
  229.  
  230. int  lst_dchr;                /* last character           */
  231.                     /* in directory string           */
  232.  
  233. /** added for ANYWHERE JT **/
  234. int            strcmpi();    /* Microsoft V3 function to do a     */
  235.                     /*   string compare without regard   */
  236.                     /*   to case.                 */
  237. void            strcat();    /* String concatenate function         */
  238. #define     MAXEDRV    16        /* Set max number of drives         */
  239. char            *strdup();    /* MSC string dup function         */
  240. char            *getcwd();    /* MSC ver3 function to return         */
  241.                     /* current working directory         */
  242. char            *envdup;    /* pointer to duplicate of env str   */
  243. char            *envdrv[MAXEDRV];   /* pointer to each drive         */
  244.                     /* in envdup                 */
  245. filename        env_dir_string; /* Environment directory string      */
  246. char            **cur_envp;    /* current environmnet array pointer */
  247. char            *env_stp;    /* Current environment string pointer*/
  248. char            *env_chp;    /* environment character pointer     */
  249. static    char        envid[]="AWDISK=";  /* Our environment string id     */
  250. char            *envid_p;    /* current id string ptr         */
  251. filename        dos_cwd;    /* buffer to hold cur working dir    */
  252. int            env_cnt;    /* count of number of drives         */
  253. int            envd_len;    /* length of the environment string  */
  254. int            wi;        /* A working integer             */
  255. struct    {
  256.     unsigned    drive    : 1;    /* drive specifier found in com line */
  257.     unsigned    found    : 1;    /* environment contains AWDISK=          */
  258.     unsigned    srchcwd : 1;    /* Search for current work dir         */
  259.     unsigned    addcwd    : 1;    /* Add current working directory     */
  260.     } flag;
  261.  
  262. /********************************************************
  263. *    check number of incoming arguments        *
  264. *    if incorrect, write an error message        *
  265. ********************************************************/
  266.  
  267. if (argc != 2)
  268.     {
  269.     printf( "ERR  usage is:   AW    [starting directory]filename.ext\n\n");
  270.     printf( "Environment string is: AWDISK=d: [;d: [;....d:] ]\n");
  271.     return;
  272.     }
  273.  
  274. /**    Added for Lattice C Version 2.15 JT
  275. *    Initialize the segment structure for later dos interrupt calls.
  276. **/
  277.  
  278. segread( &s8086 );        /* initialize segments for interrupt calls */
  279. dos_result = 0;         /* init interrupt return variable MSCV3.   */
  280.  
  281. /**
  282. *    dos_parm is set to the first argument in the
  283. *    command line
  284. **/
  285.  
  286. dos_parm = *(++argv);
  287.  
  288. /**
  289. *    If a drive specifier is found we do not want to go through overhead
  290. *    of environment string search.        AW - JT
  291. *    If no drive specifier is found we will extract the drive of the
  292. *        current working directory to be added to the array of environment
  293. *        drives.
  294. **/
  295. flag.srchcwd = 1;            /* Init true until command line      */
  296.                     /*     option added.             */
  297. if ( strchr( dos_parm, colon ) )
  298.     {
  299.     flag.drive = 1;            /* Set drive specifier true         */
  300.     flag.found = 0;            /* Set environment found false         */
  301.     }
  302. else
  303.     {
  304.     /**
  305.     *    Drive flag is set to zero
  306.     *    If the search current working directory flag is true then:
  307.     *        Current working directory is obtained and the drive isolated from
  308.     *        from the directory string.
  309.     **/
  310.     flag.drive = 0;
  311.     if ( flag.srchcwd )
  312.     {
  313.     getcwd(dos_cwd,sizeof(dos_cwd)-1);
  314.     env_chp = strchr( dos_cwd, colon );
  315.     *++env_chp = end_of_string;
  316.     }
  317.     }
  318. /**
  319. *   We check to see if there was a drive specifier found.  If so we
  320. +    want to continue rather than check the environment string for the
  321. *    AWDISK= parameter
  322. **/
  323. if (flag.drive)
  324.     {
  325.     /**
  326.     *    There was a drive specifier so we zero the env_cnt variable
  327.     **/
  328.     env_cnt = 0;
  329.     }
  330. else
  331.     {
  332.     /**
  333.     *    The drive specifier was  found in the DOS command argument therefore
  334.     *        the environment strings will be searched for the AWDISK= parameter
  335.     **/
  336.     cur_envp = envp;            /* init current environ pointer */
  337.     flag.found = 0;            /* init flag found false        */
  338.     /**
  339.     *        Check each environment string to see if it is the AW
  340.     *        environment string.  The envp array is terminated with
  341.     *        a NULL pointer.  The search is terminated when found is
  342.     *        true or the environment pointer is NULL.
  343.     **/
  344.     while( *cur_envp && !flag.found )
  345.     {
  346.     envid_p = envid;    /* init pointer to our environ id */
  347.     env_chp = *cur_envp;    /* init pointer to environ string */
  348.     flag.found = 1;     /* Set flag found = true to enter loop */
  349.     /**
  350.     *   Compare each character in the string to AWDISK=
  351.     **/
  352.     for ( env_cnt=0; (env_cnt<(sizeof(envid)-1)) && flag.found; env_cnt++)
  353.         {
  354.         if ( *envid_p++ != *env_chp++ )
  355.         flag.found = 0;
  356.         else
  357.         flag.found = 1;
  358.         }
  359.  
  360.     /**
  361.     *   If found true then copy string to our buffer
  362.     *   Replace ';' with 0x00
  363.     *   Count the number of drives found
  364.     *   Set addcwd true to add the current working directory
  365.     **/
  366.     if ( flag.found )
  367.         {
  368.         flag.addcwd = 1;
  369.         /**
  370.         *    Create a duplicate of the environment string
  371.         *    If it cannot be created we will probably fail but allow
  372.         *    continuation just in case
  373.         **/
  374.         if (!(envdup = strdup(env_chp)))
  375.         {
  376.         fprintf( stderr, "Memory alloc problems\n" );
  377.         env_cnt = 0;        /* zero count cause we're goin out   */
  378.         break;            /* allow current drive to continue   */
  379.         }
  380.         /**
  381.         *    Examine the environment string for a ";"
  382.         *    Replace each semicolon with a "\0" to terminate the string
  383.         *    Increment the env_cnt variable for each drive in the system
  384.         *        that the user wished to examine
  385.         *    Place the pointer to the beginning of drive in the envdrv
  386.         *        variable.
  387.         **/
  388.         envd_len = strlen(envdup);    /* get length of environment string  */
  389.         env_cnt  = 0;        /* Set count of drives to zero         */
  390.         env_stp  = envdup;        /* Set the string pointer to current */
  391.         while ( (envd_len > 0) && (env_cnt < MAXEDRV) )
  392.         {
  393.         /**
  394.         *   Look for the semicolon
  395.         **/
  396.         if (env_chp = strchr(env_stp,semicolon))
  397.             {
  398.             /**
  399.             *    We have a semicolon : See if its false
  400.             **/
  401.             if (env_chp-env_stp)
  402.             {
  403.             /**
  404.             *   There is a string so put in array
  405.             *   Decrement the length field
  406.             *   Change the value of the semi colon to a end of str
  407.             *   Set up a new pointer beyond env_stp
  408.             **/
  409.             envdrv[env_cnt++] = env_stp;
  410.             envd_len = envd_len-((env_chp-env_stp)+1);
  411.             *env_chp = end_of_string;
  412.             /**
  413.             *   Check the environment entry against the current
  414.             *    working directory.  If equal set addcwd to
  415.             *    false
  416.             **/
  417.             if ( strcmpi( dos_cwd, env_stp ) == 0 )
  418.                 flag.addcwd = 0;
  419.             env_stp = ++env_chp;
  420.             }
  421.             else
  422.             {
  423.             /**
  424.             *   There was no string just a semicolon
  425.             *   Decrement the length field
  426.             *   setup a new pointer beyond the semi-colon
  427.             **/
  428.             --envd_len;
  429.             env_stp = ++env_chp;
  430.             }
  431.             }
  432.         else
  433.             {
  434.             /**
  435.             *    There was no semi-colon so we are on the last drive
  436.             *        entry.
  437.             *    Place address in array and increment count
  438.             *    Set the remaining string length to zero to exit.
  439.             *    See if last entry matches current working directory
  440.             *        if so don't add it.
  441.             **/
  442.             envdrv[env_cnt++] = env_stp;
  443.             envd_len = 0;
  444.             if ( strcmpi( dos_cwd, env_stp ) == 0 )
  445.             flag.addcwd = 0;
  446.             if ( flag.addcwd )
  447.             {
  448.             if ( (env_cnt < MAXEDRV) && (flag.srchcwd) )
  449.                 envdrv[env_cnt++] = dos_cwd;
  450.             }
  451.             }
  452.         }
  453.         }
  454.     else
  455.         {
  456.         /**
  457.         *    This environment string is not the one we want therefore
  458.         *    Increment current environment pointer and continue
  459.         **/
  460.         cur_envp++;
  461.         }
  462.     }   /* End While */
  463.     }    /* End Else */
  464.  
  465. /**
  466. * The dos_parm is then searched for the last
  467. * occurrence of a backslash to find the end of
  468. * the directory name.
  469. **/
  470.  
  471. last_loc = strrchr(dos_parm,backslash);
  472.  
  473.  
  474. /********************************************************
  475. * If there was not a backslash (and therefore the    *
  476. *     beginning directory is the root directory)    *
  477. * begin                         *
  478. *   copy command line argument into chk_str        *
  479. *   copy root directory into dir_string         *
  480. * end                            *
  481. * else                            *
  482. * (if there was a backslash and therefore a beginning    *
  483. *     directory specified in the command line)        *
  484. * begin                         *
  485. *   set the usr_file to the next character        *
  486. *    past the backslash                *
  487. *   copy the usr_file into chk_str            *
  488. *   copy the command line argument into         *
  489. *    dir_string                    *
  490. *   terminate dir_string just after the         *
  491. *    last backslash (therefore leaving only the    *
  492. *    the directory name in the string)        *
  493. * end                            *
  494. ********************************************************/
  495.  
  496. if (last_loc == NULL)
  497.     {
  498.     /**
  499.     * Since no backslash we'll still check for a drive designator LC 2.14 -JT
  500.     **/
  501.     last_loc = strchr(dos_parm, colon);
  502.     if (last_loc == NULL)
  503.     {
  504.     strcpy(chk_str,dos_parm);
  505.     strcpy(dir_string,"\\");
  506.     }
  507.     else
  508.     {
  509.     usr_file = last_loc + 1;
  510.     strcpy(chk_str,usr_file);
  511.     strcpy(dir_string,dos_parm);
  512.     lst_dchr = usr_file - dos_parm;
  513.     dir_string[lst_dchr++] = backslash;    /* Fake path */
  514.     dir_string[lst_dchr]   = end_of_string; /* terminate directory str */
  515.     }
  516.     }
  517. else
  518.     {
  519.     usr_file = last_loc + 1;
  520.     strcpy(chk_str,usr_file);
  521.     strcpy(dir_string,dos_parm);
  522.     lst_dchr = usr_file - dos_parm;
  523.     dir_string[lst_dchr] = end_of_string;
  524.     }
  525.  
  526.  
  527. /**
  528. *   if the environment string was found concatenate environment drives
  529. *    with the directory string that was extracted.
  530. *   else look for just the directory string
  531. **/
  532.  
  533. if ( flag.found)
  534.     {
  535.     for ( wi = 0; wi < env_cnt; wi++ )
  536.     {
  537.     /**
  538.     *   Search each directory in the environment array
  539.     **/
  540.     strcpy( env_dir_string, envdrv[ wi ] );
  541.     strcat( env_dir_string, dir_string );
  542.     LOOK( env_dir_string );
  543.     }
  544.     }
  545. else
  546.     {
  547.     /**
  548.     *    There is no environment loop so look only for directory string
  549.     **/
  550.     LOOK(dir_string);
  551.     }
  552.  
  553. return;
  554.  
  555. }
  556.  
  557. /**/
  558. /*********************************************************
  559. *    LOOK is the recursive procedure in WHERE     *
  560. *    It is called once for each subdirectory      *
  561. *********************************************************/
  562.  
  563. LOOK(dir_string)
  564. char *dir_string;
  565. {
  566.  
  567. struct DTA cur_DTA;        /* used to return data from DOS  */
  568.  
  569. filename new_dstr;        /* the directory to be         */
  570.                 /* searched on the next      */
  571.                 /* call to LOOK()         */
  572.  
  573. filename cur_str;        /* temporary filename         */
  574.                 /* string for searching for     */
  575.                 /* directories             */
  576.  
  577.  
  578. /**
  579. * Form cur_str by copying dir_string and        *
  580. *    and then concatenating "*.*" to look through all   *
  581. *    files                        *
  582. **/
  583.  
  584. strcpy(cur_str,dir_string);
  585. strcat(cur_str,"*.*");
  586.  
  587. /**
  588. * Set the Disk Transfer Area in DOS to the cur_DTA    *
  589. *    structure                        *
  590. * Get the first subdirectory in this directory        *
  591. **/
  592.  
  593. SET_DTA(&cur_DTA);
  594. GET_FIRST(cur_str,directory_type);
  595.  
  596. /**
  597. * while there are more subdirectories in this directory *
  598. * begin                         *
  599. *   double check for proper directories (see text)    *
  600. *   if a directory                    *
  601. *   begin                        *
  602. *     set up the new_dstr for the            *
  603. *     next call to LOOK (see text)            *
  604. *     call LOOK                     *
  605. *     reset Disk Transfer Address (see text)        *
  606. *   end                         *
  607. *   look for next directory                *
  608. * end                            *
  609. **/
  610.  
  611. while (!(r8086.x.cflag & carry_set))
  612.     {
  613.     if (cur_DTA.DTA_attr == directory_type &&
  614.        cur_DTA.DTA_filename[0] != '.')
  615.     {
  616.     strcpy(new_dstr,dir_string);
  617.     strcat(new_dstr,cur_DTA.DTA_filename);
  618.     strcat(new_dstr,"\\");
  619.     LOOK(new_dstr);
  620.     SET_DTA(&cur_DTA);
  621.     }
  622.     GET_NEXT();
  623.     }
  624.  
  625. /********************************************************
  626. * if there are no more subdirectories in this directory *
  627. *   look for files                    *
  628. * else                            *
  629. *   print an error message                *
  630. ********************************************************/
  631.  
  632. if (r8086.x.ax == no_more_files)
  633.     GET_FILES(dir_string,&cur_DTA);
  634. else
  635.     printf("problem with looking thru %s\n",dir_string);
  636. return;
  637.  
  638. }
  639.  
  640.  
  641. /********************************************************
  642. * GET_FILES                        *
  643. * is called once per directory to look for the        *
  644. *   actual files matching the search string        *
  645. ********************************************************/
  646.  
  647. GET_FILES(dir_string,cur_DTA)
  648. char *dir_string;
  649. struct DTA *cur_DTA;
  650. {
  651.  
  652. filename cur_str;
  653.  
  654. /********************************************************
  655. * Form cur_str by copying dir_string into  *
  656. *   it and then concatenating the chk_str onto       *
  657. *   the end                        *
  658. ********************************************************/
  659.  
  660. strcpy(cur_str,dir_string);
  661. strcat(cur_str,chk_str);
  662.  
  663. /*********************************************************
  664. * Get the first file that matches cur_str     *
  665. ********************************************************/
  666.  
  667. GET_FIRST(cur_str,no_type);
  668.  
  669. /********************************************************
  670. * while there are more files that match the search    *
  671. *   string:                        *
  672. * begin                         *
  673. *   print the file information                *
  674. *   get the next file                    *
  675. * end                            *
  676. ********************************************************/
  677.  
  678. while (!(r8086.x.cflag & carry_set))
  679.     {
  680.  
  681.     /*  If we have gotten a screenful pause for a keystroke */
  682.     if (++count==24) {    
  683.     printf("\t\t<<Hit any key to continue or Q to abort>>");
  684.     count =    getch();
  685.     printf("\r\t\t\t\t\t\t\t\t\r");
  686.     if ((count == 'Q') || (count == 'q'))
  687.         exit(1);
  688.     count = 0;
  689.     }
  690.  
  691.     printf(" %10ld %s   %s%s\n", (*cur_DTA).DTA_size, 
  692.             DATE(&((*cur_DTA).DTA_date)),
  693.             dir_string, (*cur_DTA).DTA_filename);
  694.     GET_NEXT();
  695.     }
  696.  
  697. /*********************************************************
  698. * if error in looking for a file            *
  699. *    print error message and return            *
  700. ********************************************************/
  701.  
  702. if (r8086.x.ax != no_more_files)
  703.     printf("problem with looking for %s\n",cur_str);
  704.  
  705. return;
  706.  
  707. }
  708.  
  709. /********************************************************
  710. * GET_NEXT does an interrupt 21h, function 4Fh        *
  711. * Function 4fh is Get next directory entry        *
  712. ********************************************************/
  713.  
  714. GET_NEXT()
  715.  
  716. {
  717. r8086.x.ax = 0x4f00;
  718.  
  719. dos_result = int86x( 0x21, &r8086, &r8086, &s8086 );
  720.  
  721. return;
  722. }
  723.  
  724.  
  725. /********************************************************
  726. * SET_DTA does an interrupt 21h, function 1Ah        *
  727. *   The DS:DX pair is set to the address of the     *
  728. *   cur_DTA data structure                *
  729. ********************************************************/
  730.  
  731. SET_DTA(cur_DTA)
  732. struct DTA    *cur_DTA;
  733. {
  734.  
  735. r8086.x.ax = 0x1a00;
  736. r8086.x.dx = (int)cur_DTA;        /* set offset to disk transfer area */
  737.  
  738. dos_result = int86x(0x21, &r8086, &r8086, &s8086 );
  739.  
  740. return;
  741.  
  742. }
  743.  
  744. /********************************************************
  745. * GET_FIRST does an interrupt 21h, function 4Eh     *
  746. *   The CX register is set to either normal or        *
  747. *   directory type (see text)                *
  748. *   The DS:DX pair is set to the address of the     *
  749. *   search string                    *
  750. ********************************************************/
  751.  
  752. GET_FIRST(sea_str,filetype)
  753. char *sea_str;
  754. int filetype;
  755. {
  756.  
  757. r8086.x.ax = 0x4e00;                /* Set DOS function     */
  758. r8086.x.cx = filetype;                /* Set search attributes */
  759. r8086.x.dx = (int)    sea_str;          /* Set address of string */
  760.  
  761. dos_result = int86x( 0x21, &r8086, &r8086, &s8086 );
  762.  
  763. return;
  764.  
  765. }
  766.  
  767. /********************************************************
  768. * DATE takes the date field from the current DTA    *
  769. *   structure and returns a string containing the    *
  770. *   information in formatted ASCII            *
  771. ********************************************************/
  772.  
  773. char *DATE(dateptr)
  774. struct msdos_date *dateptr;
  775. {
  776.  
  777. sprintf(date_str, "%02d-%02d-%02d %02d:%02d %s",
  778.     dateptr->ms_month, dateptr->ms_day,
  779.     dateptr->ms_year+80, (dateptr->ms_hour)%12,
  780.     dateptr->ms_min, time_of_day[((dateptr->ms_hour)/12)]);
  781. return(date_str);
  782.  
  783. }
  784.  
  785. char *space(where)
  786. int where;
  787. {
  788.     spce[lastzero] = ' ';
  789.     spce[where] = '\0';
  790.     return spce;
  791. }
  792.