home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / kill2.zip / kill2src.zip / kill.c < prev    next >
C/C++ Source or Header  |  1992-12-21  |  14KB  |  513 lines

  1. /*************************************************************************/
  2. /* Kill2 file maintenance utility copyright (c) 1992 by M. Kimes         */
  3. /* all rights reserved                                                   */
  4. /* Free for use in non-commercial environments                           */
  5. /* $10.00 for commercial use to the author                               */
  6. /*************************************************************************/
  7.  
  8. #define INCL_DOS
  9.  
  10. #include <os2.h>
  11. #include <io.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <stdarg.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18. #include <share.h>
  19. #include <time.h>
  20. #include <malloc.h>
  21.  
  22. typedef struct __filelist__ {
  23.   char                *filename;
  24.   struct __filelist__ *next;
  25. } FILELIST;
  26.  
  27. #define JUSTLIST  1
  28. #define JUSTTOUCH 2
  29. #define RECURSE   4
  30.  
  31. int majversion = 0,minversion = 2;
  32. int redirected;
  33.  
  34. extern void sendhelp (void);
  35. extern int _fastcall wildcard (char *fstr,char *fcard);
  36. extern int _fastcall oldenough (char *filename,ULONG days);
  37. extern int _fastcall unixsetftime (int handle,time_t t);
  38. extern struct __filelist2__ *msortl(struct __filelist2__ *p);
  39. extern time_t _fastcall dosfile_2_unix (struct _ftime *ft,struct _fdate *fd);
  40.  
  41.  
  42.  
  43. FILELIST * _fastcall add_to_excemptlist (USHORT newest,FILELIST *ehead,
  44.                                          FILELIST *khead) {
  45.  
  46.   /* add newest files to exempt list */
  47.  
  48.   FILELIST *info,*nhead = ehead,*nlast;
  49.   struct __filelist2__ {
  50.     char   *filename;
  51.     time_t filedate;
  52.     struct __filelist2__ *next;
  53.   } *tinfo = NULL,*tlast = NULL,*thead = NULL;
  54.   USHORT numfiles = 0;
  55.   FILEFINDBUF f;
  56.   int search_handle,num_matches;
  57.  
  58.   nlast = nhead;
  59.   while(nlast) nlast = nlast->next;
  60.  
  61.   while(khead) {
  62.     search_handle = -1;
  63.     num_matches = 1;
  64.     if(!DosFindFirst(khead->filename,&search_handle,0,&f,
  65.        sizeof(FILEFINDBUF),&num_matches,0L)) {
  66.       while(num_matches == 1) {
  67.         tinfo = malloc(sizeof(struct __filelist2__));
  68.         if(!tinfo) {
  69.           fprintf(stderr,"\n **Out of memory\n");
  70.           exit(6);
  71.         }
  72.         tinfo->filename = strdup(f.achName);
  73.         if(!tinfo->filename) {
  74.           free(tinfo);
  75.           fprintf(stderr,"\n **Out of memory\n");
  76.           exit(6);
  77.         }
  78.         tinfo->filedate = dosfile_2_unix(&f.ftimeLastWrite,&f.fdateLastWrite);
  79.         if(!thead) {
  80.           thead = tinfo;
  81.         }
  82.         else tlast->next = tinfo;
  83.         tlast = tinfo;
  84.         tinfo->next = NULL;
  85.         numfiles++;
  86.         if(DosFindNext(search_handle,&f,sizeof(FILEFINDBUF),&num_matches)) break;
  87.       }
  88.       DosFindClose(search_handle);
  89.     }
  90.     khead = khead->next;
  91.   }
  92.   if(numfiles > newest) {
  93.     thead = msortl(thead);
  94.     while(numfiles > newest && thead) {
  95.       tinfo = thead;
  96.       thead = thead->next;
  97.       free(tinfo->filename);
  98.       free(tinfo);
  99.       numfiles--;
  100.     }
  101.   }
  102.   fprintf(stderr,"-A%u Excluded:\n",newest);
  103.   while(thead) {
  104.     tinfo = thead;
  105.     thead = thead->next;
  106.     info = malloc(sizeof(FILELIST));
  107.     if(!info) {
  108.       fprintf(stderr,"\n **Out of memory\n");
  109.       exit(6);
  110.     }
  111.     info->filename = strdup(tinfo->filename);
  112.     if(!info->filename) {
  113.       free(info);
  114.       fprintf(stderr,"\n **Out of memory\n");
  115.       exit(6);
  116.     }
  117.     if(!nhead) {
  118.       nhead = info;
  119.     }
  120.     else nlast->next = info;
  121.     nlast = info;
  122.     info->next = NULL;
  123.     free(tinfo->filename);
  124.     free(tinfo);
  125.     fprintf(stderr," %s\n",info->filename);
  126.   }
  127.   return nhead;
  128. }
  129.  
  130.  
  131.  
  132. int _fastcall wildcard_list (char *filename,FILELIST *exclude) {
  133.  
  134.   FILELIST *info;
  135.   int      ret = 0; /* match if no excludes */
  136.  
  137.   info = exclude;
  138.   while(info) {
  139.     if(info->filename && wildcard(filename,info->filename)) {
  140.       ret = 1;
  141.       break;
  142.     }
  143.     info = info->next;
  144.   }
  145.   return ret;
  146. }
  147.  
  148.  
  149.  
  150. long unlink_allf (FILELIST *exclude,ULONG days,int flags,char *string,...) {
  151.  
  152.   /* wildcard delete */
  153.  
  154.   FILEFINDBUF *f;
  155.   int          search_handle,num_matches;
  156.   long         numunlinked = 0L;
  157.   char         *p,*ss,*str,*s,*filepart;
  158.   va_list      ap;
  159.   time_t       curtime;
  160.  
  161.   curtime = time(NULL);
  162.  
  163.   s = malloc(1028);
  164.   if(!s) return 0L;
  165.  
  166.   va_start(ap,string);
  167.   vsprintf(s,string,ap);
  168.   va_end(ap);
  169.  
  170.   if(!*s) {
  171.     free(s);
  172.     return 0L;
  173.   }
  174.   p = s;
  175.   while((p = strchr(p,'/')) != NULL) *p = '\\'; /* / = \\ */
  176.  
  177.   str = strdup(s);
  178.   if(!str) {
  179.     free(s);
  180.     return 0L;
  181.   }
  182.  
  183.   p = s;
  184.   p = strrchr(s,'\\');           /* strip s to just path */
  185.   if(!p) p = strrchr(s,':');
  186.   if(p) {
  187.     p++;
  188.     *p = 0;
  189.   }
  190.   else *s = 0;
  191.  
  192.   filepart = str;
  193.   filepart = strrchr(str,'\\');           /* find file portion of str */
  194.   if(!filepart) filepart = strrchr(str,':');
  195.   if(filepart) {
  196.     filepart++;
  197.   }
  198.   else filepart = str;
  199.  
  200.   ss = (char *)malloc(1027);
  201.   f = (FILEFINDBUF *)malloc(sizeof(FILEFINDBUF));
  202.   if(!ss || !f) {
  203.     if(ss) free(ss);
  204.     if(f) free(f);
  205.     free(str);
  206.     free(s);
  207.     return 0L;
  208.   }
  209.  
  210.   search_handle = -1;
  211.   num_matches = 1;
  212.  
  213.   if(!DosFindFirst(str,&search_handle,(FILE_DIRECTORY * ((flags & RECURSE) != 0)),
  214.      f,sizeof(FILEFINDBUF),&num_matches,0L)) {
  215.  
  216.     strcpy(ss,s);
  217.     p = &ss[strlen(ss)];
  218.  
  219.     while(num_matches == 1) {
  220.       if(f->attrFile & FILE_DIRECTORY) {
  221.         if(*f->achName != '.') {
  222.           if(stackavail() > 2048) {
  223.             fprintf(stderr,"   [-=> %s%s\\%s]\n",s,f->achName,filepart);
  224.             numunlinked += unlink_allf(exclude,days,flags,"%s%s\\%s",s,f->achName,filepart);
  225.             fprintf(stderr,"   [<=- %s%s]\n",s,filepart);
  226.           }
  227.           else fprintf(stderr," **Warning:  insufficient stack for further recursion\n");
  228.         }
  229.       }
  230.       else {
  231.         if(!wildcard_list(f->achName,exclude)) {
  232.           strcpy(p,f->achName);
  233.           if(oldenough(ss,days)) {
  234.             if(!(flags & JUSTLIST) && !(flags & JUSTTOUCH)) {
  235.               unlink(ss);
  236.               fprintf(stderr," Unlinked");
  237.             }
  238.             else if(flags & JUSTTOUCH) {
  239.  
  240.               int handle;
  241.  
  242.               handle = sopen(ss,O_RDWR | O_BINARY,SH_DENYNO);
  243.               if(handle != -1) {
  244.  
  245.                 int error;
  246.  
  247.                 if((error = unixsetftime(handle,curtime)) == 0)
  248.                   fprintf(stderr," Touched");
  249.                 else
  250.                   fprintf(stderr," Couldn't touch: error #%d.",error);
  251.                 close(handle);
  252.               }
  253.               else 
  254.                 fprintf(stderr," Couldn't touch: no read/write access.");
  255.             }
  256.             fprintf(stderr," ");
  257.             printf("%s\n",ss);
  258.             if(redirected)
  259.               fprintf(stderr,"%s\n",ss);
  260.             numunlinked++;
  261.           }
  262.         }
  263.       }
  264.       if(DosFindNext(search_handle,f,sizeof(FILEFINDBUF),&num_matches)) break;
  265.     }
  266.     DosFindClose(search_handle);
  267.   }
  268.  
  269.   free(f);
  270.   free(ss);
  271.   free(str);
  272.   free(s);
  273.   return numunlinked;
  274. }
  275.  
  276.  
  277.  
  278. int main (int argc,char *argv[]) {
  279.  
  280.   int      flags = JUSTLIST,help = 0;
  281.   USHORT   newest = 0;
  282.   FILE     *fp;
  283.   FILELIST *ehead = NULL,*elast = NULL,*khead = NULL,*klast = NULL,*info;
  284.   ULONG    days = 0L,numdead = 0L;
  285.   char     s[1027];
  286.  
  287.  
  288.   {
  289.     USHORT info,devhead;
  290.  
  291.     DosQHandType(fileno(stdout),&info,&devhead);
  292.     if(((info & 255) == 1) && (devhead & 2)) redirected = 0;
  293.     else redirected = 1;
  294.   }
  295.  
  296.   fprintf(stderr,"\n");
  297.   if(argc < 2) help = 1;
  298.  
  299.   while(argc > 1) {
  300.     switch(toupper(*argv[argc - 1])) {
  301.       case '-':
  302.       case '/':
  303.         switch(toupper(argv[argc - 1][1])) {
  304.           case 'E': /* file pattern to exclude */
  305.             if(argv[argc - 1][2] == '@' && argv[argc - 1][3] != '@') {
  306.               fprintf(stderr,"Loading exclude list \"%s\"\n",&argv[argc - 1][3]);
  307.               fp = fopen(&argv[argc - 1][3],"rt");
  308.               if(fp) {
  309.                 while(!feof(fp) && fgets(s,1027,fp)) {
  310.                   info = malloc(sizeof(FILELIST));
  311.                   if(!info) {
  312.                     fprintf(stderr,"\n **Out of memory\n");
  313.                     return 2;
  314.                   }
  315.                   while(s[strlen(s) - 1] == '\n' || s[strlen(s) - 1] == ' ')
  316.                     s[strlen(s) - 1] = 0; /* strip lf, trailing spaces */
  317.                   while(*s == ' ') memmove(s,&s[1],strlen(s));  /* leading spaces */
  318.                   if(!*s) continue;
  319.                   info->filename = strdup(s);
  320.                   if(!info->filename) {
  321.                     fprintf(stderr,"\n **Out of memory\n");
  322.                     return 2;
  323.                   }
  324.                   info->next = NULL;
  325.                   if(!ehead) {
  326.                     ehead = info;
  327.                   }
  328.                   else elast->next = info;
  329.                   elast = info;
  330. #ifdef DEBUG
  331.                   fprintf(stderr,"EXCLUDE: \"%s\"\n",info->filename);
  332. #endif
  333.                 }
  334.                 fclose(fp);
  335.               }
  336.               else {
  337.                 fprintf(stderr,"\n **Couldn't load exclude files from \"%s\"!\n",&argv[argc - 1][3]);
  338.                 return 5;
  339.               }
  340.             }
  341.             else {
  342.               info = malloc(sizeof(FILELIST));
  343.               if(!info) {
  344.                 fprintf(stderr,"\n **Out of memory\n");
  345.                 return 2;
  346.               }
  347.               info->filename = strdup(&argv[argc - 1][2 + (argv[argc - 1][2] == '@')]);
  348.               if(!info->filename) {
  349.                 fprintf(stderr,"\n **Out of memory\n");
  350.                 return 2;
  351.               }
  352.               info->next = NULL;
  353.               if(!ehead) {
  354.                 ehead = info;
  355.               }
  356.               else elast->next = info;
  357.               elast = info;
  358. #ifdef DEBUG
  359.               fprintf(stderr,"EXCLUDE: \"%s\"\n",info->filename);
  360. #endif
  361.             }
  362.             break;
  363.  
  364.           case 'L':
  365.             flags |= JUSTLIST;
  366. #ifdef DEBUG
  367.             fprintf(stderr,"LISTing\n");
  368. #endif
  369.             break;
  370.  
  371.           case 'A':
  372.             newest = atoi(&argv[argc - 1][2]);
  373. #ifdef DEBUG
  374.             fprintf(stderr,"NEWest %u\n",newest);
  375. #endif
  376.             if(!newest) {
  377.               fprintf(stderr,"\n **Error in -A# argument; 0 given\n");
  378.               return 8;
  379.             }
  380.             break;
  381.  
  382.           case '?':
  383.           case 'H':
  384.             help = 1;
  385. #ifdef DEBUG
  386.             fprintf(stderr,"HELPing\n");
  387. #endif
  388.             break;
  389.  
  390.           case 'T':
  391.             flags |= JUSTTOUCH;
  392. #ifdef DEBUG
  393.             fprintf(stderr,"TOUCHing\n");
  394. #endif
  395.             break;
  396.  
  397.           case 'K':     /* KILL! */
  398.             flags &= (~(JUSTLIST | JUSTTOUCH));
  399. #ifdef DEBUG
  400.             fprintf(stderr,"KILLing\n");
  401. #endif
  402.             break;
  403.  
  404.           case 'D':
  405.             days = atol(&argv[argc - 1][2]);
  406.             fprintf(stderr,"Processing files %lu day%s old or older\n",days,&"s"[days == 1L]);
  407.             break;
  408.  
  409.           case 'R':
  410.             flags |= RECURSE;
  411. #ifdef DEBUG
  412.             fprintf(stderr,"RECURSE\n");
  413. #endif
  414.             break;
  415.  
  416.           case '-':
  417.             memmove(argv[argc - 1],&argv[argc - 1][1],strlen(argv[argc - 1]));
  418.             goto DashInterrupt;
  419.  
  420.           default:
  421.             fprintf(stderr,"\n **Unknown switch %s\n",argv[argc - 1]);
  422.             return 3;
  423.         }
  424.         break;
  425.  
  426.       default:    /* file pattern to kill */
  427. DashInterrupt:
  428.         if(*argv[argc - 1] == '@' && argv[argc - 1][1] != '@') {
  429.           fprintf(stderr,"Loading kill list \"%s\"\n",&argv[argc - 1][1]);
  430.           fp = fopen(&argv[argc - 1][1],"rt");
  431.           if(fp) {
  432.             while(!feof(fp) && fgets(s,1027,fp)) {
  433.               info = malloc(sizeof(FILELIST));
  434.               if(!info) {
  435.                 fprintf(stderr,"\n **Out of memory\n");
  436.                 return 2;
  437.               }
  438.               while(s[strlen(s) - 1] == '\n' || s[strlen(s) - 1] == ' ')
  439.                 s[strlen(s) - 1] = 0; /* strip lf, trailing spaces */
  440.               while(*s == ' ') memmove(s,&s[1],strlen(s));  /* leading spaces */
  441.               if(!*s) continue;
  442.               info->filename = strdup(s);
  443.               if(!info->filename) {
  444.                 fprintf(stderr,"\n **Out of memory\n");
  445.                 return 2;
  446.               }
  447.               info->next = NULL;
  448.               if(!khead) {
  449.                 khead = info;
  450.               }
  451.               else klast->next = info;
  452.               klast = info;
  453. #ifdef DEBUG
  454.               fprintf(stderr,"KILL: \"%s\"\n",info->filename);
  455. #endif
  456.             }
  457.             fclose(fp);
  458.           }
  459.           else fprintf(stderr," **Warning:  couldn't open \"%s\"\n",&argv[argc - 1][1]);
  460.         }
  461.         else {
  462.           info = malloc(sizeof(FILELIST));
  463.           if(!info) {
  464.             fprintf(stderr,"\n **Out of memory\n");
  465.             return 2;
  466.           }
  467.           info->filename = strdup(&argv[argc - 1][(*argv[argc - 1] == '@')]);
  468.           if(!info->filename) {
  469.             fprintf(stderr,"\n **Out of memory\n");
  470.             return 2;
  471.           }
  472.           info->next = NULL;
  473.           if(!khead) {
  474.             khead = info;
  475.           }
  476.           else klast->next = info;
  477.           klast = info;
  478. #ifdef DEBUG
  479.           fprintf(stderr,"KILL: \"%s\"\n",info->filename);
  480. #endif
  481.         }
  482.         break;
  483.     }
  484.     argc--;
  485.   }
  486.  
  487.   if(help) {
  488.     sendhelp();
  489.     return 1;
  490.   }
  491.   else {
  492.     if(newest && khead) {
  493.       flags &= (~RECURSE); /* no recursion w/ newest option */
  494.       info = add_to_excemptlist(newest,ehead,khead);
  495.       if(!ehead) ehead = info;
  496.     }
  497.     fprintf(stderr,"\nKILL2 v%d.%02d copyright (c) 1992 by M. Kimes -- all rights reserved\n",majversion,minversion);
  498.     if(!khead) {
  499.       fprintf(stderr,"\n **Nothing to do\n");
  500.       return 4;
  501.     }
  502.     info = khead;
  503.     while(info) {
  504.       fprintf(stderr,"    [%s]\n",info->filename);
  505.       numdead += unlink_allf(ehead,days,flags,info->filename);
  506.       info = info->next;
  507.     }
  508.     fprintf(stderr,"\nKILL2 processed %lu file%s\n",numdead,&"s"[numdead == 1L]);
  509.   }
  510.   return 0;
  511. }
  512.  
  513.