home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / directry / fff320 / fff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-09  |  13.5 KB  |  512 lines

  1. /*---------------------------------------------------------------------------*/
  2. /*      FFF.COM - Fast-File-Find, a fully public domain program to search
  3.  *                   for files on one or more disks (functionally similar to
  4.  *                   the familiar "WHERE" program.  FFF will also search inside
  5.  *                   of ZIP, ARC, PKA, and ZOO archives to the first level.
  6.  *
  7.  *      Version:  3.2.0
  8.  *      Date:     January 12, 1990
  9.  *      Author:   Don A. Williams
  10.  *
  11.             *********************  NOTICE  ************************
  12.             *  Contrary to the current trend in MS-DOS  software  *
  13.             *  this  program,  for whatever it is worth,  is NOT  *
  14.             *  copyrighted (with the exception  of  the  runtime  *
  15.             *  library  from  the C compiler)!  The program,  in  *
  16.             *  whole or in part,  may  be  used  freely  in  any  *
  17.             *  fashion or environment desired.  If you find this  *
  18.             *  program  to  be  useful  to you,  do NOT send any  *
  19.             *  contribution to the author;  in the words of Rick  *
  20.             *  Conn,   'Enjoy!'   However,   if   you  make  any  *
  21.             *  improvements,  I would enjoy receiving a copy  of  *
  22.             *  the  modified source.  I can be reached,  usually  *
  23.             *  within 24  hours,  by  messages  on  any  of  the  *
  24.             *  following Phoenix, AZ systems:                     *
  25.             *                                                     *
  26.             *     The Tool Shop BBS       [PCBOARD] [PC-Pursuit]  *
  27.             *         (602) 279-2673   1200/2400/9600 bps         *
  28.             *     Technoids Anonymous     [PCBOARD]               *
  29.             *         (602) 899-4876   300/1200/2400 bps          *
  30.             *         (602) 899-5233                              *
  31.             *         (602) 786-9131                              *
  32.             *     Inn On The Park         [PCBOARD]               *
  33.             *         (602) 957-0631   1200/2400/9600 bps         *
  34.             *     Pascalaholics Anonymous [WBBS]                  *
  35.             *         (602) 484-9356   1200/2400 bps              *
  36.             *                                                     *
  37.             *  or:                                                *
  38.             *     GEnie, mail address: DON-WILL                   *
  39.             *     CompuServ:           75410,543                  *
  40.             *                                                     *
  41.             *  Every  effort  has  been  made to avoid error and  *
  42.             *  moderately extensive testing has  been  performed  *
  43.             *  on  this  program,  however,  the author does not  *
  44.             *  warrant it to be fit for any  purpose  or  to  be  *
  45.             *  free  from  error and disclaims any liability for  *
  46.             *  actual or any other damage arising from  the  use  *
  47.             *  of this program.                                   *
  48.             *******************************************************
  49. */
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <ctype.h>
  55. #include <dos.h>
  56. #include <dir.h>
  57. #include <io.h>
  58.  
  59. #define MAIN
  60.  
  61. #define ON  1
  62. #define OFF 0
  63.  
  64. #define VERSION "Version 3.2.0"
  65. #define VER_DATE "January 12, 1990"
  66.  
  67. #include "fff.h"
  68. #include "queue.h"
  69. #include "arc.h"
  70. #include "zip.h"
  71. #include "zoo.h"
  72.  
  73. void WalkTree (QUE_DEF *Q);
  74. int SearchQ (char *Str, QUE_DEF *Q);
  75. int Match (char *Str, char *Pat);
  76. void GetPath (QUE_DEF *Q, char *Arg);
  77. void PrtVerbose (char *Path, char *Name, DOS_FILE_TIME Time, DOS_FILE_DATE Date,
  78.                  long Size);
  79. void Usage (void);
  80. void ChkPage (void);
  81.  
  82. void GetCurrentDisk (int *CurDisk);
  83. int GetCurrentDirectory (int Disk, char *CurDir);
  84. void ErrorExit (char *Format, ...);
  85. void GetProgName (char *Name, char *argv);
  86.  
  87. char Path[65];
  88. char Temp[66];
  89. char Pattern[66];
  90. char CurDir[65];
  91. unsigned long Position;
  92. char ProgName[9];
  93.  
  94. int Spaced     = 0;
  95. int Lnno       = 1;
  96. int TotalFiles = 0;
  97. int TotalMatch = 0;
  98.  
  99. ARC_TYPE ArcType;
  100.  
  101. struct Archives {
  102.     char Ext[4];
  103.     ARC_TYPE Type;
  104.     } Arcs[6] = {
  105.         {"ARC", arc},
  106.         {"LZH", lzh},
  107.         {"PAK", arc},
  108.         {"ZIP", zip},
  109.         {"ZOO", zoo},
  110.         {"", none}
  111.         };
  112.  
  113. int S[6][3] = {
  114.     {0, 0, 0},                /* Dummy          */
  115.     {0, 0, 0},                /* Arc File Stats */
  116.     {0, 0, 0},                /* Zip File Stats */
  117.     {0, 0, 0},                /* Zoo File Stats */
  118.     {0, 0, 0},                /* Pak File Stats */
  119.     {0, 0, 0}                /* Lzh File Stats */
  120.     };
  121.  
  122. /*---  Option Switches  --- */
  123.  
  124. int ArcSwt       = 1;                /* Search inside of archives - default ON    */
  125. int PageSwt    = 0;                /* Paginate output - default OFF            */
  126. int VerboseSwt = 0;                /* Verbose out put - default OFF            */
  127. int QuietSwt   = 0;                /* Supress stats   - default OFF            */
  128. int DateSwt    = 0;                /* Change date formaat - default OFF        */
  129.  
  130.  
  131. /*---  End Option Switches  --- */
  132.  
  133. char *Legend[] = {
  134.     "NONE", "ARC", "ZIP", "ZOO", "PAK", "LZH", ""
  135.     };
  136.  
  137. char Devices[16] = "";
  138.  
  139.  void
  140. main (int argc, char *argv[]) {
  141.     QUE_DEF Paths, PatQue;
  142.     QUE_ENTRY *t;
  143.     int CurDisk, i, j;
  144.     char *p;
  145.  
  146.     GetProgName(ProgName, argv[0]);
  147.     fprintf(stderr, "%s: FastFileFind - %s: %s\n", ProgName, VERSION, VER_DATE);
  148.     InitQueue(&Paths); InitQueue(&PatQue);
  149.     GetCurrentDisk(&CurDisk);
  150.     CurDir[0] = (char) (CurDisk + 'A'); CurDir[1] = ':'; CurDir[2] = '\\';
  151.     GetCurrentDirectory(0, CurDir+3);
  152.     strupr(CurDir);
  153.     strcpy(Path, "C:\\");
  154.     p = getenv("FFF");
  155.     if (p != NULL) {
  156.         while (*p != '\0') {
  157.             if (*p == ' ' || *p == '\t') ++p;
  158.             else if (*p == '-') switch(tolower(*(++p))) {
  159.                 case 'a':
  160.                     ArcSwt ^= ON;
  161.                     ++p;
  162.                     break;
  163.                 case 'v':
  164.                     VerboseSwt ^= ON;
  165.                     ++p;
  166.                     break;
  167.                 case 'p':
  168.                     PageSwt ^= ON;
  169.                     ++p;
  170.                     break;
  171.                 case 'q':
  172.                     QuietSwt ^= ON;
  173.                     break;
  174.                 case 'f':
  175.                     DateSwt ^= ON;
  176.                     break;
  177.                 }
  178.             else {
  179.                 i = strcspn(p, " :-");
  180.                 strncpy(Devices, p, i); Devices[i] = '\0';
  181.                 p += i;
  182.                 }
  183.             }
  184.         }
  185.  
  186.     if (Devices[0] == '\0') {
  187.         Devices[0] = CurDisk + 'A';
  188.         Devices[1] = '\0';
  189.         }
  190.     if (argc < 2) Usage();
  191.     for (i=1; i < argc; ++i) {
  192.         if (argv[i][0] == '-') {
  193.             switch( tolower(argv[i][1]) ) {
  194.                 case 'a':
  195.                     ArcSwt ^= ON;
  196.                     break;
  197.                 case 'v':
  198.                     VerboseSwt ^= ON;
  199.                     break;
  200.                 case 'p':
  201.                     PageSwt ^= ON;
  202.                     break;
  203.                 case 'q':
  204.                     QuietSwt ^= ON;
  205.                     break;
  206.                 case 'f':
  207.                     DateSwt ^= ON;
  208.                     break;
  209.                 default:
  210.                     fprintf(stderr, "Invalid argument: %c\n", argv[i][1]);
  211.                     Usage();
  212.                     break;
  213.                 }
  214.             continue;
  215.             }
  216.         else if ( (p = strrchr(argv[i], '\\')) != NULL ) {
  217.             strcpy(Pattern, p+1);
  218.             strupr(Pattern);
  219.             Enque(&PatQue, Pattern);
  220.             *(p+1) = '\0';
  221.             }
  222.         else if ( (p = strchr(argv[i], ':')) != NULL ) {
  223.             strcpy(Pattern , p+1);
  224.             strupr(Pattern);
  225.             Enque(&PatQue, Pattern);
  226.             *(p+1) = '\0';
  227.             }
  228.         else {
  229.             strcpy(Pattern, argv[i]);
  230.             strupr(Pattern);
  231.             Enque(&PatQue, Pattern);
  232.             if ( (p = Devices) != NULL) {
  233.                 while ( (*p != '\0') && (*p != ':') ) {
  234.                     Path[0] = toupper(*p++); Path[1] = ':';
  235.                     Path[2] = '\\'; Path[3] = '\0';
  236.                     Enque(&Paths, Path);
  237.                     }
  238.                 }
  239.             else {
  240.                 Path[0] = (char) (CurDisk + 'A'); Path[1] = ':'; Path[2] = '\\';
  241.                 Path[3] = '\0';
  242.                 Enque(&Paths, Path);
  243.                 }
  244.             continue;
  245.             }
  246.         GetPath(&Paths, argv[i]);
  247.         }
  248.     for (t = Paths.Head; t != NULL; t = t->Next) {
  249.         strcpy(Path, t->Body);
  250.         WalkTree(&PatQue);
  251.         }
  252.     if (!QuietSwt) {
  253.         if (!Spaced) printf("\n");
  254.         printf("Total Files = %6d  Total Matched Files = %d\n", TotalFiles, TotalMatch);
  255.         for (i=0; Legend[i][0] != '\0'; ++i) {
  256.             if (S[i][0] != 0) {
  257.                 printf("\n%s Files  = %6d  ", Legend[i], S[i][0]);
  258.                 if (ArcSwt) printf("%sed Files = %6d %s Matches = %4d",
  259.                                     Legend[i], S[i][1], Legend[i],
  260.                                     S[i][2]);
  261.                 }
  262.             }
  263.         printf("\n");
  264.         }
  265.     }
  266.  
  267.  void
  268. WalkTree (QUE_DEF *Q) {
  269.     extern int VerboseSwt, Spaced;
  270.     extern struct Archives Arcs[6];
  271.  
  272.     int Status, Reply, i;
  273.     QUE_DEF Direc;
  274.     QUE_ENTRY *t, *u;
  275.     char *p;
  276.     struct ffblk DirBlk;
  277.     DOS_FILE_TIME Time;
  278.     DOS_FILE_DATE Date;
  279.  
  280.     InitQueue(&Direc);
  281.     strcat(Path, "*.*");
  282.     Status = findfirst(Path, &DirBlk, 0xFF);
  283.     *(strrchr(Path, '\\')+1) = '\0';
  284.     while (!Status) {
  285.         if ( (DirBlk.ff_attrib & FA_LABEL) != 0) {
  286.             Status = findnext(&DirBlk);
  287.             continue;
  288.             }
  289.         if ( (DirBlk.ff_attrib & FA_DIREC) != 0) {
  290.             if (DirBlk.ff_name[0] != '.') {
  291.                 Enque(&Direc, DirBlk.ff_name);
  292.                 }
  293.             }
  294.         else {
  295.             ++TotalFiles;
  296.             if ( SearchQ(DirBlk.ff_name, Q) ) {
  297.                 ++TotalMatch;
  298.                 if (PageSwt) ChkPage();
  299.                 if (VerboseSwt) {
  300.                     fputs("  ", stdout);
  301.                     Time.u = DirBlk.ff_ftime;
  302.                     Date.u = DirBlk.ff_fdate;
  303.                     PrtVerbose(Path, DirBlk.ff_name, Time, Date,
  304.                                DirBlk.ff_fsize);
  305.                     }
  306.                 else {
  307.                     fputs(Path, stdout);
  308.                     puts(DirBlk.ff_name);
  309.                     }
  310.                 ++Lnno;
  311.                 Spaced = 0;
  312.                 }
  313.             if ( (p = strchr(DirBlk.ff_name, '.')) != NULL ) {
  314.                 for (i=0; Arcs[i].Ext[0] != '\0' && stricmp(p+1, Arcs[i].Ext); ++i);
  315.                 ArcType = Arcs[i].Type;
  316.                 switch (ArcType) {
  317.                     case arc:
  318.                     case pak:
  319.                         ++S[ArcType][0];
  320.                         if (ArcSwt) {
  321.                             strcat(Path, DirBlk.ff_name);
  322.                             DoArc(Path);
  323.                             *(strrchr(Path, '\\') + 1) = '\0';
  324.                             }
  325.                         break;
  326.                     case zip:
  327.                         ++S[ArcType][0];
  328.                         if (ArcSwt) {
  329.                             strcat(Path, DirBlk.ff_name);
  330.                             DoZip(Path);
  331.                             *(strrchr(Path, '\\') + 1) = '\0';
  332.                             }
  333.                         break;
  334.                     case zoo:
  335.                         ++S[ArcType][0];
  336.                         if (ArcSwt) {
  337.                             strcat(Path, DirBlk.ff_name);
  338.                             DoZOO(Path);
  339.                             *(strrchr(Path, '\\') + 1) = '\0';
  340.                             }
  341.                         break;
  342.                     case lzh:
  343.                         ++S[ArcType][0];
  344.                         if (ArcSwt) {
  345.                             strcat(Path, DirBlk.ff_name);
  346.                             DoLzh(Path);
  347.                             *(strrchr(Path, '\\') + 1) = '\0';
  348.                             }
  349.                         break;
  350.                     }
  351.                 }
  352.             }
  353.         Status = findnext(&DirBlk);
  354.         }
  355.     p = strrchr(Path,'\\') + 1;
  356.     for (t=Direc.Head; t != NULL; ) {
  357.         *p = '\0';
  358.         strcat(Path, t->Body); strcat(Path, "\\");
  359.         WalkTree(Q);
  360.         u = t->Next;
  361.         free(t->Body);
  362.         free(t);
  363.         t = u;
  364.         }
  365.     }
  366.  
  367.  int
  368. SearchQ (char *Str, QUE_DEF *Q) {
  369.     QUE_ENTRY *t;
  370.     int Result;
  371.  
  372.     for (t=Q->Head; t != NULL; t = t->Next) {
  373.         if ( (Result = Match(Str, t->Body)) != 0) return(Result);
  374.         }
  375.     return(0);
  376.     }
  377.  
  378.  int
  379. Match (char *Str, char *Pat) {
  380.  
  381.     while (*Str != '\0') {
  382.         if (*Pat == '*') {
  383.             if ( *(++Pat) == '\0') return(1);
  384.             else {
  385.                 while (*Str != *Pat && *Str != '\0') ++Str;
  386.                 if (*Str == '\0') {
  387.                     if (*Pat == '.' && ( *(Pat+1) == '\0' || *(Pat+1) == '*') ) return(1);
  388.                     else return(0);
  389.                     }
  390.                 }
  391.             }
  392.         if (*Pat == '?') {
  393.             ++Pat; ++Str;
  394.             }
  395.         if (*Str != *Pat) return(0);
  396.         ++Pat; ++Str;
  397.         }
  398.     if ( (*Pat == '\0') || !strcmp(Pat, ".*") || !strcmp(Pat, "*") ) return(1);
  399.     else return(0);
  400.     }
  401.  
  402.  
  403.  void
  404. GetPath (QUE_DEF *Q, char *Arg) {
  405.     char *p, Temp[65];
  406.     int i, j;
  407.  
  408.     if ( (p = strchr(Arg, ':')) != NULL) {
  409.         if ( (i = p - Arg) > 1) {
  410.             for (j=0; j < i; ++j) {
  411.                 Temp[0] = Arg[j];
  412.                 Temp[1] = '\0';
  413.                 strcat(Temp, p);
  414.                 if (Temp[strlen(Temp)-1] != '\\') strcat(Temp, "\\");
  415.                 strupr(Temp);
  416.                 if (Enque(Q, Temp) == NULL)
  417.                     ErrorExit("Insufficient memory for Path List.\n");
  418.                 }
  419.             }
  420.         else {
  421.             strcpy(Temp, Arg);
  422.             if (Temp[strlen(Temp)-1] != '\\') strcat(Temp, "\\");
  423.             strupr(Temp);
  424.             if (Enque(Q, Temp) == NULL)
  425.                 ErrorExit("Insufficient memory for Path List.\n");
  426.             }
  427.         }
  428.     else {
  429.         Temp[0] = CurDir[0]; Temp[1] = ':'; Temp[2] = '\0';
  430.         strcat(Temp, Arg);
  431.         if (Temp[strlen(Temp)-1] != '\\') strcat(Temp, "\\");
  432.         strupr(Temp);
  433.         if (Enque(Q, Temp) == NULL)
  434.             ErrorExit("Insufficient memory for Path List.\n");
  435.         }
  436.     }
  437.  
  438.  void
  439. ErrorExit (char *Format, ...) {
  440.     va_list ArgPtr;
  441.     extern char ProgName[];
  442.     extern int errno;
  443.  
  444.     fprintf(stderr, "%s: ", ProgName);
  445.     va_start(ArgPtr, Format);
  446.     vfprintf(stderr, Format, ArgPtr);
  447.     va_end(ArgPtr);
  448.     if (errno) perror("    ");
  449.     fprintf(stderr, "\n");
  450.     exit(1);
  451.     }
  452.  
  453.  void
  454. GetProgName (char *Name, char *argv) {
  455.     char *p, *p1;
  456.  
  457.     if ( (p = strrchr(argv, '\\')) != NULL) ++p;
  458.     else p = argv;
  459.     if ( (p1 = strchr(p, '.')) != NULL) *p1 = '\0';
  460.     strcpy(Name, p);
  461.     }
  462.  
  463.  void
  464. PrtVerbose (char *Path, char *Name, DOS_FILE_TIME Time, DOS_FILE_DATE Date,
  465.             long Size) {
  466.     extern int DateSwt;
  467.     static char *MonTab[] = {
  468.         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  469.         "Oct", "Nov", "Dec"
  470.         };
  471.  
  472.     if (DateSwt) {
  473.         printf("%-13s   %02d/%02d/%02d   %02u:%02u %8ld   %s\n", Name,
  474.                 Date.b.Year + 80, Date.b.Month, Date.b.Day, Time.b.Hour,
  475.                 Time.b.Minute, Size, Path);
  476.         }
  477.     else {
  478.         printf("%-13s   %02u %s %02u   %02u:%02u %8ld   %s\n", Name, Date.b.Day,
  479.                MonTab[Date.b.Month - 1], Date.b.Year + 80, Time.b.Hour,
  480.                Time.b.Minute, Size, Path);
  481.         }
  482.     }
  483.  
  484.  void
  485. Usage (void) {
  486.     fprintf(stderr, "USAGE: %s [device(s):[path]pattern [options]\n", ProgName);
  487.     fprintf(stderr, "\nOptions:\n\n");
  488.     fprintf(stderr, "    -a Suppress searching inside of archive files.\n");
  489.     fprintf(stderr, "    -v Display Date/Time and File Size as well as name\n");
  490.     fprintf(stderr, "       and path for all matched files.\n");
  491.     fprintf(stderr, "    -f Modify the date in the Verbose output for sorting\n");
  492.     fprintf(stderr, "       YY/MM/DD form\n");
  493.     fprintf(stderr, "    -p Paginate output every 23 lines\n");
  494.     fprintf(stderr, "    -q Supress the printing of the statistics on files\n");
  495.     fprintf(stderr, "       searched and matched\n");
  496.     exit(1);
  497.     }
  498.  
  499.  
  500.  void
  501. ChkPage (void) {
  502.     int Reply;
  503.  
  504.     if (Lnno >= 24) {
  505.         clreol();
  506.         printf("More?...");
  507.         Reply = tolower( getche() );
  508.         if ( (Reply == 'n') || (Reply == 0x03) ) exit(1);
  509.         printf("\r"); clreol();
  510.         Lnno = 1;
  511.         }
  512.     }