home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / c / WHERE.ZIP / WHERE.C next >
Encoding:
C/C++ Source or Header  |  1988-01-02  |  14.2 KB  |  420 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. *                                   *
  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. *                                   *
  17. *        Modification Log                   *
  18. *                                   *
  19. * 12/31/86    Michael Roberts        Made program compatible *
  20. *                       with Microsoft C 4.0    *
  21. *                                                              **
  22. * 01/02/88      Karl Heuer             change strchr to strrchr *
  23. *                                   **
  24. *                                   *
  25. * 01/02/88    Ron Ahrendt           #include <string.h>     *
  26. *                                   *
  27. *                                   *
  28. ***************************************************************/
  29.  
  30.  
  31. /***************************************************************
  32. * The C header files                           *
  33. * These identify library routines like printf() and intcall()  *
  34. ***************************************************************/
  35.  
  36. #include <stdio.h>    /* standard i/o               */
  37. #include <dos.h>    /* functions for DOS interrupt calls  */
  38. #include <string.h>    /* string functions... */
  39.  
  40.  
  41. /***************************************************************
  42. * Definition of DOS Disk Transfer Area (DTA)               *
  43. ***************************************************************/
  44.  
  45. /***************************************************************
  46. * Structure for MS-DOS date and time fields               *
  47. * See pages 4-6 and 4-7 of the DOS 2.1 technical           *
  48. * reference manual for more information                *
  49. * This structure is used in the next structure definition      *
  50. ***************************************************************/
  51.  
  52. struct msdos_date
  53.     {
  54.     unsigned ms_sec    : 5; /* time in 2 sec. int (5 bits)*/
  55.     unsigned ms_min    : 6; /* minutes (6 bits)          */
  56.     unsigned ms_hour   : 5; /* hours (5 bits)          */
  57.     unsigned ms_day    : 5; /* day of month (5 bits)      */
  58.     unsigned ms_month  : 4; /* month (4 bits)          */
  59.     unsigned ms_year   : 7; /* year since 1980 (7 bits)   */
  60.     };
  61.  
  62. /***************************************************************
  63. * Structure filled in by MS-DOS for interrupt 21 calls           *
  64. * See page 5-46 of the DOS 2.1 technical reference           *
  65. * manual for more information                       *
  66. ***************************************************************/
  67.  
  68. struct DTA
  69.     {
  70.     char     DTA_dosinfo[21];    /* used by DOS          */
  71.     char     DTA_attr;         /* file attribute byte   */
  72.     struct msdos_date DTA_date;  /* date struct. as above */
  73.     long     DTA_size;         /* file size          */
  74.     char     DTA_filename[13];   /* file name (w/o path)  */
  75.     };
  76.  
  77.  
  78. /***************************************************************
  79. *        Definitions of constants               *
  80. ***************************************************************/
  81.  
  82. #define not !     /* for ease of reading (C uses a !
  83.             character for logical not's)              */
  84. #define and &     /* for ease of reading (C uses a &
  85.             character for bit-wise logical and's)     */
  86. #define carry_set 0x0001 /* mask for flag register
  87.                 for carry bit    */
  88. #define no_type   0x00     /* no bits set on file attribute byte*/
  89. #define directory_type     0x10 /* directory file bit on file
  90.                  info word    */
  91. #define no_more_files     18     /* DOS return code for
  92.                     no more files          */
  93. #define end_of_string     '\0'    /* C uses a binary zero to
  94.                       signal end of string    */
  95. #define backslash '\\'   /* the backslash character           */
  96.  
  97. char *month[] = {
  98.         "Jan","Feb","Mar","Apr","May","Jun",
  99.         "Jul","Aug","Sep","Oct","Nov","Dec"
  100.         };
  101. char *time_of_day[2] = {"AM","PM"};
  102.  
  103.  
  104. /***************************************************************
  105. *        Define the type "filename"                     *
  106. *            to be a string of 51 characters        *
  107. ***************************************************************/
  108.  
  109. typedef char filename[51];
  110.  
  111.  
  112. /***************************************************************
  113. *                                   *
  114. * The following filename strings are used in the program:      *
  115. *                                   *
  116. *    check_string        filename to be searched for    *
  117. *                filename in the command line)  *
  118. *    directory_string    directory name to be searched  *
  119. *    newdirectory_string    directory name to be searched  *
  120. *                  on next recursive call       *
  121. *    current_string        temporary string for searching *
  122. *                  in a specific directory      *
  123. ***************************************************************/
  124.  
  125. /***************************************************************
  126. * Definition of any forward-referenced functions           *
  127. ***************************************************************/
  128.  
  129. char *DATE();
  130.  
  131.  
  132. /***************************************************************
  133. *        Global variables                   *
  134. ***************************************************************/
  135.  
  136. filename check_string;    /* this string "remembers" user input */
  137. union REGS registers;    /* structure to allow access to indiv.*/
  138.             /*   registers for interrupts          */
  139. char datestring[40];    /* print output string for dates      */
  140.  
  141.  
  142. /***************************************************************
  143. *        MAIN() -- the beginning of the code           *
  144. ***************************************************************/
  145.  
  146. main(argc,argv)
  147. int argc;
  148. char *argv[];
  149.     {
  150.     filename directory_string;    /* directory to be searched   */
  151.     char *incoming_filename;    /* address of filename in
  152.                    command line argument
  153.                    (ie, the filename)          */
  154.     char *last_location;    /* address of last backslash in
  155.                    command line argument      */
  156.     char *incoming_string;    /* address of
  157.                    command line argument      */
  158.     int  last_directory_char;    /* last character
  159.                    in directory string      */
  160.  
  161. /********************************************************
  162. *    check number of incoming arguments        *
  163. *    if incorrect, write an error message        *
  164. ********************************************************/
  165.  
  166.     if (argc not= 2)
  167.     printf
  168.     ("usage is:   WHERE [starting directory]filename.ext\n\n");
  169.     else
  170.     {
  171. /********************************************************
  172. * incoming_string is set to the first argument in the    *
  173. * command line                        *
  174. * The incoming_string is then searched for the last    *
  175. * occurrence of a backslash to find the end of        *
  176. * the directory name.                    *
  177. ********************************************************/
  178.  
  179. incoming_string = *(++argv);
  180. last_location = strrchr(incoming_string,backslash);
  181.  
  182. /********************************************************
  183. * If there was not a backslash (and therefore the    *
  184. *     beginning directory is the root directory)    *
  185. * begin                         *
  186. *   copy command line argument into check_string    *
  187. *   copy root directory into directory_string        *
  188. * end                            *
  189. * else                            *
  190. * (if there was a backslash and therefore a beginning    *
  191. *     directory specified in the command line)        *
  192. * begin                         *
  193. *   set the incoming_filename to the next character    *
  194. *    past the backslash                *
  195. *   copy the incoming_filename into check_string    *
  196. *   copy the command line argument into         *
  197. *    directory_string                *
  198. *   terminate directory_string just after the        *
  199. *    last backslash (therefore leaving only the    *
  200. *    the directory name in the string)        *
  201. * end                            *
  202. ********************************************************/
  203.  
  204. if (last_location == NULL)
  205.     {
  206.     strcpy(check_string,incoming_string);
  207.     strcpy(directory_string,"\\");
  208.     }
  209. else
  210.     {
  211.     incoming_filename = last_location + 1;
  212.     strcpy(check_string,incoming_filename);
  213.     strcpy(directory_string,incoming_string);
  214.     last_directory_char = incoming_filename - incoming_string;
  215.     directory_string[last_directory_char] = end_of_string;
  216.                     }
  217. /********************************************************
  218. *        start 'er up                            *
  219. ********************************************************/
  220.  
  221. LOOK(directory_string);
  222. }
  223. return;
  224. }
  225.  
  226.  
  227. LOOK(directory_string)
  228.  
  229. /********************************************************
  230. *    LOOK is the recursive procedure in WHERE    *
  231. *    It is called once for each subdirectory     *
  232. ********************************************************/
  233.  
  234. char *directory_string;
  235.     {
  236.     struct DTA current_DTA;  /* used to return data from DOS  */
  237.     filename newdirectory_string; /* the directory to be
  238.                      searched on the next
  239.                      call to LOOK()          */
  240.     filename current_string;      /* temporary filename
  241.                      string for searching for
  242.                      directories          */
  243.  
  244. /********************************************************
  245. * Form current_string by copying directory_string and    *
  246. *    and then concatenating "*.*" to look through all   *
  247. *    files                        *
  248. ********************************************************/
  249.  
  250.     strcpy(current_string,directory_string);
  251.     strcat(current_string,"*.*");
  252.  
  253. /********************************************************
  254. * Set the Disk Transfer Area in DOS to the current_DTA    *
  255. *    structure                        *
  256. * Get the first subdirectory in this directory        *
  257. ********************************************************/
  258.  
  259.     SET_DTA(¤t_DTA);
  260.     GET_FIRST(current_string,directory_type);
  261.  
  262. /********************************************************
  263. * while there are more subdirectories in this directory *
  264. * begin                         *
  265. *   double check for proper directories (see text)    *
  266. *   if a directory                    *
  267. *   begin                        *
  268. *     set up the newdirectory_string for the        *
  269. *     next call to LOOK (see text)            *
  270. *     call LOOK                     *
  271. *     reset Disk Transfer Address (see text)        *
  272. *   end                         *
  273. *   look for next directory                *
  274. * end                            *
  275. ********************************************************/
  276.  
  277.     while (not(registers.x.cflag and carry_set))
  278.     {
  279.     if (current_DTA.DTA_attr == directory_type &&
  280.        current_DTA.DTA_filename[0] not= '.')
  281.         {
  282.         strcpy(newdirectory_string,directory_string);
  283.         strcat(newdirectory_string,current_DTA.DTA_filename);
  284.         strcat(newdirectory_string,"\\");
  285.         LOOK(newdirectory_string);
  286.         SET_DTA(¤t_DTA);
  287.         }
  288.     GET_NEXT();
  289.     }
  290.  
  291. /********************************************************
  292. * if there are no more subdirectories in this directory *
  293. *   look for files                    *
  294. * else                            *
  295. *   print an error message                *
  296. ********************************************************/
  297.  
  298.     if (registers.x.ax == no_more_files)
  299.     GET_FILES(directory_string,¤t_DTA);
  300.     else
  301.     printf("problem with looking thru %s\n",directory_string);
  302.     return;
  303.     }
  304.  
  305. GET_FILES(directory_string,current_DTA)
  306.  
  307. /********************************************************
  308. * GET_FILES                        *
  309. * is called once per directory to look for the        *
  310. *   actual files matching the search string        *
  311. ********************************************************/
  312.  
  313. char *directory_string;
  314. struct DTA *current_DTA;
  315.     {
  316.     filename current_string;
  317.  
  318. /********************************************************
  319. * Form current_string by copying directory_string into    *
  320. *   it and then concatenating the check_string onto    *
  321. *   the end                        *
  322. ********************************************************/
  323.  
  324.     strcpy(current_string,directory_string);
  325.     strcat(current_string,check_string);
  326.  
  327. /********************************************************
  328. * Get the first file that matches current_string    *
  329. ********************************************************/
  330.  
  331.     GET_FIRST(current_string,no_type);
  332.  
  333. /********************************************************
  334. * while there are more files that match the search    *
  335. *   string:                        *
  336. * begin                         *
  337. *   print the file information                *
  338. *   get the next file                    *
  339. * end                            *
  340. ********************************************************/
  341.  
  342.     while (not(registers.x.cflag and carry_set))
  343.     {
  344.     printf(" %10ld  %s  %s %s\n", (*current_DTA).DTA_size,
  345.        DATE(&((*current_DTA).DTA_date)), directory_string,
  346.        &(*current_DTA).DTA_filename);
  347.     GET_NEXT();
  348.     }
  349. /********************************************************
  350. * if error in looking for a file            *
  351. *    print error message and return            *
  352. ********************************************************/
  353.  
  354.     if (registers.x.ax not= no_more_files)
  355.     printf("problem with looking for %s\n",current_string);
  356.     return;
  357.     }
  358.  
  359.  
  360. GET_NEXT()
  361.     {
  362. /********************************************************
  363. * GET_NEXT does an interrupt 21h, function 4Fh        *
  364. ********************************************************/
  365.  
  366.     registers.x.ax = 0x4f00;
  367.     intdos(®isters,®isters);
  368.     return;
  369.     }
  370.  
  371. SET_DTA(current_DTA)
  372.     struct DTA *current_DTA;
  373.     {
  374. /********************************************************
  375. * SET_DTA does an interrupt 21h, function 1Ah        *
  376. *   The DS:DX pair is set to the address of the     *
  377. *   current_DTA data structure                *
  378. ********************************************************/
  379.     registers.x.ax = 0x1a00;
  380.     registers.x.dx = FP_OFF(current_DTA);
  381.     intdos(®isters,®isters);
  382.     return;
  383.     }
  384.  
  385. GET_FIRST(search_string,filetype)
  386.     char *search_string;
  387.     int filetype;
  388.     {
  389. /********************************************************
  390. * GET_FIRST does an interrupt 21h, function 4Eh     *
  391. *   The CX register is set to either normal or        *
  392. *   directory type (see text)                *
  393. *   The DS:DX pair is set to the address of the     *
  394. *   search string                    *
  395. ********************************************************/
  396.     registers.x.ax = 0x4e00;
  397.     registers.x.cx = filetype;
  398.     registers.x.dx = FP_OFF(search_string);
  399.     intdos(®isters,®isters);
  400.     return;
  401.     }
  402.  
  403.  
  404. char *DATE(dateptr)
  405. struct msdos_date *dateptr;
  406.     {
  407. /********************************************************
  408. * DATE takes the date field from the current DTA    *
  409. *   structure and returns a string containing the    *
  410. *   information in formatted ASCII            *
  411. ********************************************************/
  412.  
  413.     sprintf(datestring, "%02d-%02d-%2d  %02d:%02d %s",
  414.     dateptr->ms_month, dateptr->ms_day,
  415.     dateptr->ms_year+80, (dateptr->ms_hour)%12,
  416.     dateptr->ms_min, time_of_day[((dateptr->ms_hour)/12)]);
  417.     return(datestring);
  418.     }
  419.  
  420.