home *** CD-ROM | disk | FTP | other *** search
/ HomeWare 14 / HOMEWARE14.bin / archive / au116_4s.arj / SCAN.CPP < prev    next >
C/C++ Source or Header  |  1994-04-17  |  10KB  |  367 lines

  1. // ASCAN.CPP                                 1          1    6666
  2. // Dave Harris                                11         11   6
  3. // Compiled using Borland C++ ver 3.1       1 1        1 1   6666
  4. // 03-03-94                                  1     ..   1   6   6
  5. //                                           11111 .. 11111  666
  6. ////////////////////////////////////////////////////////////////////////
  7.  
  8. #include "au.hpp"
  9.  
  10. #define PROGRAM "SCAN"   // Name of module
  11. /*********************************************************************/
  12.  
  13. typedef struct
  14. {
  15.     char rename_virus[FILE_SIZE];     // What to rename it to
  16.     char archives;                     // do inside arcs period
  17.     int  newer_than;
  18.     long random_num;
  19.     int  scan_version;
  20.     char recurse;
  21. } SCAN_INFO;
  22.  
  23. static int scan_process(AU *, char *, char *, char *, ARC_FILE *);
  24.  
  25. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  26. static int is_newer(AU *au, char *file_name)
  27. {
  28.     HANDLE file;
  29.     struct ftime ftime_hold;
  30.     long value;
  31.     SCAN_INFO *in = (SCAN_INFO *)au->info;
  32.  
  33.     file = au_open(au, file_name);
  34.     getftime(file, &ftime_hold);
  35.     close(file);
  36.  
  37.     if (in->scan_version == 0 || in->newer_than == 0)
  38.         return TRUE;
  39.  
  40.     value = (long)ftime_hold.ft_hour*60*30+ftime_hold.ft_min*30+
  41.             ftime_hold.ft_tsec;
  42.     value -= in->scan_version + in->random_num;
  43.     if (value < 0)
  44.         value = -value;
  45.  
  46.     if (value < in->newer_than)
  47.         return FALSE;
  48.     else
  49.         return TRUE;
  50. }
  51. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  52. int scan_one_file(AU *au, char *file_name)
  53. {
  54.     char string2[CLENGTH];
  55.  
  56.     sprintf(string2, "%s %s", au->scanner, file_name);
  57.     return execute(au, string2, au->output, NULL, au->scannerMemNeeded);
  58. }
  59. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  60. static int recurse(AU *au, char *path)
  61. {
  62.     struct ffblk ffblk;           // directory entry structure
  63.     LISTPTR file_list;
  64.     LIST *el;
  65.     int retCode = FALSE;
  66.     char holdCurDir[FLENGTH];
  67.     char curDir[FLENGTH];
  68.     char destDir[FLENGTH];
  69.     ARC_FILE arcFile;
  70.  
  71.     cd(au, path, holdCurDir);
  72.     getcwd(curDir, FLENGTH);
  73.     build_fname(destDir, curDir, TEMP_DIR);
  74.     mkdir(TEMP_DIR);
  75.  
  76.     memset(&file_list, '\0', sizeof(LISTPTR));
  77.     if (!findfirst("*.*", &ffblk, 0))
  78.     {
  79.         do
  80.         {
  81.             add_to_list(au, &file_list, ffblk.ff_name);
  82.         }  while (!findnext(&ffblk));
  83.     }
  84.  
  85.     for (el = file_list.head; el != NULL; el = el->next)
  86.     {
  87.         arc_file_init(au, &arcFile, el->data);
  88.         arc_file_deinit(au, &arcFile);
  89.         if (arcFile.type > 0)
  90.         {
  91.             if (scan_process(au, path, destDir, el->data, &arcFile) != 0)
  92.                 retCode = TRUE;
  93.         }
  94.     }
  95.     destroy_list(&file_list);
  96.     cd(au, curDir, NULL);
  97.     rmdir(TEMP_DIR);
  98.     cd(au, holdCurDir, NULL);
  99.     return retCode;
  100. }
  101. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  102. static int scan_process(AU *au, char *sourceDir, char *destDir, char *file_name,
  103.                         ARC_FILE *arcFile)
  104. {
  105.     HANDLE     file;
  106.     int      virus_found;
  107.     int      ret_code;
  108.     char    *char_ptr;
  109.     LISTPTR  paths;
  110.     LIST    *el;
  111.     SCAN_INFO *in = (SCAN_INFO *)au->info;
  112.  
  113.     if (in->archives == ON)       /* Test self extracts itself for viruses */
  114.     {                              /* and gets regular files too */
  115.         if (arcFile->type > 0)
  116.             goto noscan;
  117.     }
  118.  
  119. /* self extract or individual file **************************/
  120.  
  121.     ret_code = scan_one_file(au, file_name);
  122.  
  123.     if (ret_code == au->SC_Virus_EL || (au->SC_Virus_EL == -1 && ret_code > 0))
  124.     {
  125.         if (in->rename_virus[0] != '\0')
  126.         {
  127.             rename(file_name, fit_mask(file_name, in->rename_virus));
  128.             fix_flist(au, file_name, fit_mask(file_name, in->rename_virus));
  129.         }
  130.         add_to_bad_list(au, sourceDir, file_name, ret_code, 2);
  131.         if (arcFile->is_self)  // now lets not go and unarc (execute) it
  132.             return TRUE;
  133.     }
  134.     else if (ret_code != au->SC_NoVirus_EL || (au->SC_NoVirus_EL == -1 && ret_code != 0))
  135.         add_to_bad_list(au, sourceDir, file_name, ret_code, 4);
  136. /**************************************/
  137.  noscan:
  138.  
  139.     if (in->archives==OFF || !(arcFile->type > 0 || arcFile->is_self) )
  140.         goto around;
  141.  
  142.     memset(&paths, '\0', sizeof(LISTPTR));
  143.     unarc(au, file_name, destDir, &paths, 0, FALSE);
  144.  
  145.     add_to_list(au, &paths, destDir);
  146.  
  147.     virus_found = FALSE;
  148.     for (el = paths.head; el != NULL; el = el->next)
  149.     {
  150.         if (in->recurse == ON)
  151.         {
  152.             if (recurse(au, el->data) != 0)
  153.                 virus_found = TRUE;
  154.         }
  155.         ret_code = scan_one_file(au, el->data);
  156.         if (ret_code == au->SC_Virus_EL || (au->SC_Virus_EL == -1 && ret_code > 0))
  157.         {
  158.             virus_found = TRUE;
  159.             if (in->rename_virus[0] != '\0')
  160.             {
  161.                 rename(file_name, fit_mask(file_name, in->rename_virus));
  162.                 fix_flist(au, file_name, fit_mask(file_name, in->rename_virus));
  163.             }
  164.             add_to_bad_list(au, sourceDir, file_name, ret_code, 2);
  165.             break;
  166.         }
  167.         else if (ret_code != au->SC_NoVirus_EL || (au->SC_NoVirus_EL == -1 && ret_code != 0))
  168.             add_to_bad_list(au, sourceDir, file_name, ret_code, 4);
  169.     }
  170.     clean_paths(au, &paths);
  171.  
  172.     if (virus_found)
  173.         return TRUE;
  174.  
  175.  around:
  176.     if (in->scan_version!=0)
  177.     {
  178.         struct ftime ftime_hold;
  179.         long value = in->random_num + in->scan_version;
  180.  
  181.         file = au_open(au, file_name);
  182.         getftime(file, &ftime_hold);
  183.         ftime_hold.ft_tsec = 0;
  184.         ftime_hold.ft_hour = value / (60*30);
  185.         value-= ftime_hold.ft_hour*(60*30);
  186.         ftime_hold.ft_min = value / 30;
  187.         value-= ftime_hold.ft_min*(30);
  188.         ftime_hold.ft_tsec = value;
  189.         setftime(file,&ftime_hold);
  190.         close(file);
  191.     }
  192.     return FALSE;
  193. }
  194. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  195. static int scan(AU *au, char *file_name)
  196. {
  197.     ARC_FILE arcFile;
  198.  
  199.     check_for_key();
  200.  
  201.     if (!is_newer(au, file_name))
  202.         return 0;
  203.  
  204.     if (!au->no_extra)
  205.         au_printf(au, "@?6Scanning @?1%s@?H\n", file_name);
  206.     act_log_printf(au, "   + SCAN    : %s", file_name);
  207.  
  208.     au->number_processed++;
  209.  
  210.     arc_file_init(au, &arcFile, file_name);
  211.     arc_file_deinit(au, &arcFile);
  212.  
  213.     scan_process(au, au->source_directory, au->dest_directory, file_name,
  214.                  &arcFile);
  215.     return 0;
  216. }
  217. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  218. static void ReadCFGInfo(AU *au, HANDLE file, char *cfg_file, int *cfg_line)
  219. {
  220.     char string[200],
  221.          string2[200],
  222.          string3[200];
  223.     SCAN_INFO *in = (SCAN_INFO *)au->info;
  224.  
  225.     for(EVER)
  226.     {
  227.         if (get_file_line(au, file, string)==EOF)
  228.             break;
  229.  
  230.         split_string(string, string2);
  231.         split_string(string, string3);
  232.  
  233.         if (string2[0] == '\0')
  234.             continue;
  235.  
  236.         strcpy(au->curOpt, string2);
  237.         au->curVal = string3;
  238.         switch (toupper(string2[1]) << 8 | toupper(string2[0]))
  239.         {
  240.             case 'BE':                                          // Begin
  241.                 return;
  242.             case 'SE':                                          // Self_Extracts
  243.                 au->self_extracts = get_value(au, OFF | ON);
  244.                 break;
  245.             case 'RE':                                          // Recurse
  246.                 in->recurse = get_value(au, OFF | ON);
  247.                 break;
  248.             case 'VE':                                          // Version
  249.                 in->scan_version = atoi(string3);
  250.                 break;
  251.             case 'NE':                                          // Newer_than
  252.                 in->newer_than = atoi(string3);
  253.                 break;
  254.             case 'RA':
  255.                 in->random_num = atoi(string3);
  256.                 break;
  257.             case 'VI':
  258.                 strcpy(in->rename_virus, string3);
  259.                 break;
  260.             case 'PA':
  261.                 au->pause = get_value(au, OFF | ON);
  262.                 break;
  263.             default:
  264.                 au_invalid_cfg_option(au, string2, cfg_file, *cfg_line);
  265.         }
  266.     }
  267. }
  268. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  269. static BYTE parse_comm_line(AU *au, char option, char *cur_argv,
  270.                             PARSE_TYPE type)
  271. {
  272.     SCAN_INFO *in = (SCAN_INFO *)au->info;
  273.  
  274.     switch (type)
  275.     {
  276.     case PARSE_PARAM_OPTION:
  277.         switch (option)
  278.         {
  279.         case 'X':
  280.             au->self_extracts = get_value(au, OFF | ON);
  281.             break;
  282.         case 'A':
  283.             in->archives = get_value(au, OFF | ON);
  284.             break;
  285.         case 'R':
  286.             in->recurse = get_value(au, OFF | ON);
  287.             break;
  288.         case 'N':
  289.             in->newer_than = atoi(cur_argv);
  290.             break;
  291.         case 'V':
  292.             in->scan_version = atoi(cur_argv);
  293.             break;
  294.         case 'W':
  295.             strcpy(au->dest_directory, cur_argv);
  296.             break;
  297.         case 'P':
  298.             au->pause = get_value(au, OFF | ON);
  299.             break;
  300.         case '?':
  301.             au_standard_opt_header(au, "SCan",
  302.                "@?3-X@?Hon|off     self eXtracts\n"
  303.                "@?3-A@?Hon|off     look inside Archives\n"
  304.                "@?3-R@?Hon|off     Recurse\n"
  305.                "@?3-V@?Hn          n=Version of scanner being used\n"
  306.                "                use 0 to leave time stamp unchanged\n"
  307.                "@?3-N@?Hn          scan only if scanned more than n versions ago\n"
  308.                "@?3-P@?Hon|off     Pause after bad archive found\n"
  309.                "@?3-W@?H<dir>      Work directory\n");
  310.             exit (0);
  311.         default:
  312.              au_invalid_option(au, PROGRAM, option);
  313.         }               /* end switch */
  314.         return TRUE;
  315.     case PARSE_POST_CHECK:
  316.         if (in->random_num == 0)
  317.         {
  318.             au_printf_error(au, "Need a non-zero random number in the .cfg file");
  319.             exit(1);
  320.         }
  321.         if (in->newer_than > 10)
  322.         {
  323.             au_printf_error(au, "Newer_Than is larger than recommended!!!!!");
  324.             if (!ask_continue())
  325.                 exit(1);
  326.         }
  327.         return TRUE;
  328.     }
  329.     return FALSE;
  330. }
  331. /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/
  332. int main_scan(AU *au, int argc, char *argv[])
  333. {
  334.     SCAN_INFO *in;
  335.  
  336.     in = (SCAN_INFO *)au_malloc(au, sizeof(SCAN_INFO));
  337.     memset(in, '\0', sizeof(SCAN_INFO));
  338.     au->info = in;
  339.     in->archives=ON;
  340.  
  341.     ReadGlobalCFGInfo(au, au->cfg_file, PROGRAM, ReadCFGInfo);
  342.     generic_parse_comm_line(au, argc, argv, parse_comm_line);
  343.  
  344.     if (au->dest_directory[0] != '\0')
  345.     {
  346.         /* make sure it exists */
  347.         cd(au, au->dest_directory, au->old_dest_dir);
  348.         getcwd(au->dest_directory, FLENGTH);
  349.         cd(au, au->cur_directory);
  350.     }
  351.     else
  352.         build_fname(au->dest_directory, au->cur_directory, TEMP_DIR);
  353.  
  354.     au->unarc_paths = ON;
  355.     au->recurse = OFF;         // uses a different style of recurse
  356.  
  357.     mkdir(TEMP_DIR);
  358.     process_files(au, scan);
  359.     rmdir(TEMP_DIR);
  360.  
  361.     if (!au->no_extra)
  362.         au_printf_c(au, 15, "\nFiles Scanned = %d\n\n", au->number_processed);
  363.  
  364.     return 0;
  365. }
  366.  
  367.