home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / util / trimnews.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-04  |  8.6 KB  |  393 lines

  1. /*
  2. **  TRIMNEWS.C
  3. **
  4. **  TRIMNEWS
  5. **
  6. **  This program scans UULIB:NewsGroups then chdir's into each news group's
  7. **  directory.    The second field specifies the number of days old any numerical
  8. **  file (filename beginning with 0-9) is allowed to be before it is deleted.
  9. **
  10. **  If the second field does not exist for a given line in the NewsGroups file,
  11. **  7 days is automatically assumed.  The number of days is referenced from
  12. **  when the file was created, NOT the Date: field in the article.
  13. **
  14. **  -all may be passed as a parameter, and trimnews will delete all files,
  15. **  not just those a certain number of days (hours) old. This overrides any
  16. **  and all parameters specified in UULib:Newsgroups as well as a -h param.
  17. **
  18. **  -h <hours> may be passed as a parameter, is used if a UULib:Newsgroups
  19. **  for a newsgroup does not exists. It indicates that all files over <hours>
  20. **  old should be deleted.
  21. **
  22. **  The program is meant to be run daily from a cron entry to clear out old
  23. **  news.
  24. **
  25. **  On AmigaDOS 3.0 and above, the program waits 2 seconds between each
  26. **  newsgroup to ensure that the filesystem buffers are flushed to disk.
  27. **
  28. **  If "-d" is set when executed, some very extensive debugging information
  29. **  is printed on stdout, for AmigaDOS 2.0 and above.
  30. */
  31.  
  32. #define VERBOSE
  33.  
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <stdarg.h>
  39.  
  40. #include "config.h"
  41. #include "version.h"
  42. #include "log.h"
  43. #include "OwnDevUnit.h"
  44.  
  45. #undef NULL
  46. #define NULL 0
  47.  
  48. #include <exec/memory.h>
  49. #include <exec/libraries.h>
  50. #include <clib/exec_protos.h>
  51.  
  52. #include <dos/dos.h>
  53. #include <dos/dosextens.h>
  54. #include <dos/exall.h>
  55. #include <clib/dos_protos.h>
  56.  
  57. IDENT (".10");
  58.  
  59. extern struct DosLibrary
  60.     *DOSBase;
  61. struct Library
  62.     *OwnDevUnitBase = NULL;
  63. char
  64.     TmpBuf [256];
  65. int
  66.     countfiles = 0, /* how many files deleted            */
  67.     countbytes = 0, /* how many bytes in the files deleted        */
  68.     allfiles   = 0, /* delete ALL files, not just date-ranges   */
  69.     hours       = 0, /* delete 'x' hours instead of days         */
  70.     broken       = 0, /* ctrl-C has happened                */
  71.     debug       = 0, /* display debug information            */
  72.     dos3_0       = 0, /* running on 3.0  or above            */
  73.     dos2_0       = 0, /* running on 2.04 or above            */
  74.     nodelay    = 0; /* do not delay between dirs on 3.0+        */
  75. struct DateStamp
  76.     *ds = NULL;
  77. struct ExAllControl
  78.     *eac = NULL;
  79.  
  80. struct MyExAllBuf {
  81.     ULONG
  82.         meb_Entries;
  83.     struct ExAllData
  84.         meb_Data [100];
  85. } *ead1 = NULL, *ead2 = NULL;
  86.  
  87. const char
  88.     *FMT_Final = "Deleted %ld files containing %ld bytes";
  89.  
  90. void ScanDirectoryDeleteFiles (char *path, int days);
  91. void SetupExAll (void);
  92. void CleanupExAll (void);
  93. long dstot (long *date);
  94. void ProcessExAllBuffer (const char *path, const struct MyExAllBuf *edata,
  95.              const long tnow);
  96. void rm_file (const char *path, const char *name);
  97.  
  98. int
  99. brk (void)
  100. {
  101.     broken = 1;
  102.     return 0;
  103. }
  104.  
  105. int
  106. main (int argc, char **argv)
  107. {
  108.     FILE *fi;
  109.     char *path;
  110.     char newsgrp [128];
  111.     int days;
  112.     char *dir = GetConfigDir (UUNEWS);
  113.  
  114.     LogProgram = "TrimNews";
  115.  
  116.     if ((OwnDevUnitBase = OpenLibrary ((UBYTE *) ODU_NAME, 0)) == NULL) {
  117.         fprintf (stderr, "Couldn't open lock library\n");
  118.         exit (20);
  119.     }
  120.  
  121.     onbreak (brk);
  122.  
  123.     if (argc > 1) {
  124.         int inx = 1;
  125.         char *p;
  126.  
  127.         while (inx <= argc) {
  128.             p = argv [inx++];
  129.             if (p && *p == '-') {
  130.                 p++;
  131.                 if (strcmp (p, "all") == 0)
  132.                     allfiles = 1;
  133.                 else
  134.                 if (strcmp (p, "h") == 0) {
  135.                     hours = atoi (argv [inx++]);
  136.                 }
  137.                 else
  138.                 if (strcmp (p, "d") == 0) {
  139.                     debug = 1;
  140.                 }
  141.                 else
  142.                 if (strcmp (p, "n") == 0) {
  143.                     nodelay = 1;
  144.                 }
  145.                 else {
  146.                     fprintf (stderr, "%s: don't know option '%s'\n", argv [0], p);
  147.                     exit (30);
  148.                 }
  149.             }
  150.         }
  151.     }
  152.  
  153.     dos3_0 = DOSBase->dl_lib.lib_Version >= 39 ? 1 : 0;
  154.     dos2_0 = DOSBase->dl_lib.lib_Version >= 37 ? 1 : 0;
  155.     if (dos2_0)
  156.         SetupExAll ();
  157.  
  158.     fi = openlib ("NewsGroups");
  159.     if (!fi) {
  160.         fprintf (stderr, "Unable to open NewsGroups file\n");
  161.         exit (20);
  162.     }
  163.  
  164.     while (fgets (TmpBuf, sizeof (TmpBuf), fi) && !broken) {
  165.         switch (sscanf (TmpBuf, "%s %d", newsgrp, &days)) {
  166.             case 1:
  167.                 if (!hours)
  168.                     days = 7;
  169.                 else
  170.                     days = 0;
  171.             case 2:
  172.                 if (!days && !allfiles && !hours)
  173.                     continue;
  174.                 if (path = HandleHeirarchy (dir, newsgrp, 1)) {
  175.                     ScanDirectoryDeleteFiles (path, days);
  176.                     free (path);
  177.                 }
  178.         }
  179.     }
  180.     fclose (fi);
  181.  
  182.     if (dos2_0)
  183.         CleanupExAll ();
  184.  
  185.     ulog (-1, FMT_Final, countfiles, countbytes);
  186.     printf ("%s: ", LogProgram);
  187.     printf (FMT_Final, countfiles, countbytes);
  188.     printf ("\n");
  189.  
  190.     if (OwnDevUnitBase) {
  191.         CloseLibrary (OwnDevUnitBase);
  192.         OwnDevUnitBase = NULL;
  193.     }
  194.  
  195.     return 0;
  196. }
  197.  
  198. void
  199. ScanDirectoryDeleteFiles (char *path, int days)
  200. {
  201.     BPTR lock = NULL;
  202.     BPTR oldlock = NULL;
  203.     struct FileInfoBlock *fib = NULL;
  204.     long delete_ds [3];
  205.     long tnow;
  206.     int more;
  207.     struct MyExAllBuf *eadata, *ead;
  208.  
  209.     DateStamp ((struct DateStamp *) delete_ds);
  210.     tnow = dstot (delete_ds);
  211.     if (days)
  212.         tnow -= (days * (1440 * 60));
  213.     else
  214.         if (hours)
  215.             tnow -= (hours * 60);
  216.  
  217.     lock = Lock ((UBYTE *) path, ACCESS_READ);
  218.     if (!lock)
  219.         goto done;
  220.  
  221.     oldlock = CurrentDir (lock);
  222.  
  223.     if (dos2_0) {
  224.         eac->eac_LastKey = 0;
  225.         eac->eac_Entries = 0;
  226.         eac->eac_MatchString = NULL;
  227.         eac->eac_MatchFunc   = NULL;
  228.  
  229.         ead1->meb_Entries = 0;
  230.         ead2->meb_Entries = 0;
  231.  
  232.         ead = ead2;        /* next buffer to be filled */
  233.         eadata = ead1;        /* buffer to be deleted    */
  234.  
  235.         do {
  236.             more = ExAll (lock, &ead->meb_Data[0], sizeof (ead->meb_Data), ED_DATE, eac);
  237.             if (!more) {
  238.                 if (IoErr () != ERROR_NO_MORE_ENTRIES) {
  239.                     fprintf (stderr, "ExAll() error %ld\n", IoErr ());
  240.                     break;
  241.                 }
  242.             }
  243.  
  244.             ead->meb_Entries = eac->eac_Entries;
  245.  
  246.             ProcessExAllBuffer (path, eadata, tnow);
  247.  
  248.             if (eadata == ead1) {
  249.                 eadata = ead2;
  250.                 ead    = ead1;
  251.             }
  252.             else {
  253.                 eadata = ead1;
  254.                 ead    = ead2;
  255.             }
  256.  
  257.         } while (more);
  258.  
  259.         ProcessExAllBuffer (path, eadata, tnow);  /* get last buffer */
  260.  
  261.         if (dos3_0 && nodelay == 0)
  262.             Delay (100);    /* wait 2 seconds to flush buffers */
  263.     }
  264.     else {    /* dos 1.3 or below */
  265.         fib = malloc (sizeof (struct FileInfoBlock));
  266.         if (!fib)
  267.             goto done;
  268.  
  269.         if (!Examine (lock, fib))
  270.             goto done;
  271.  
  272.         while (ExNext (lock, fib)) {
  273.             if (isdigit ((unsigned char) fib->fib_FileName [0])) {
  274.                 if (allfiles || tnow > dstot ((long *) &fib->fib_Date)) {
  275.                     rm_file (path, fib->fib_FileName);
  276.                     countbytes += fib->fib_Size;
  277.                     countfiles += 1;
  278.                 }
  279.             }
  280.         }
  281.     }
  282.  
  283. done:
  284.     if (fib)
  285.         free (fib);
  286.     if (lock) {
  287.         lock = CurrentDir (oldlock);
  288.         UnLock (lock);
  289.     }
  290.  
  291.     return;
  292. }
  293.  
  294. long
  295. dstot (long *date)    /* days, mins, ticks */
  296. {
  297.     return ((date [0] * 1440 * 60) + (date [1] * 60) + (date [2] / 50));
  298. }
  299.  
  300. void
  301. ProcessExAllBuffer (const char *path, const struct MyExAllBuf *edata,
  302.             const long tnow)
  303. {
  304.     struct ExAllData *exdata;
  305.  
  306.     if (debug)
  307.         fprintf (stderr, "PEB enter: entries %ld, path = '%s', allfiles = %ld, tnow = %ld\n", edata->meb_Entries, path, allfiles, tnow);
  308.  
  309.     if (edata->meb_Entries) {
  310.         exdata = &edata->meb_Data[0];
  311.  
  312.         while (exdata) {
  313.             if (debug)
  314.                 fprintf (stderr, "PEB: exdata = 0x%lx, next = 0x%lx, name = '%s', type %ld, size %ld,\n     prot 0x%lx, days %ld, mins %ld, ticks %ld\n",
  315.                       exdata, exdata->ed_Next, exdata->ed_Name, exdata->ed_Type, exdata->ed_Size, exdata->ed_Prot, exdata->ed_Days, exdata->ed_Mins, exdata->ed_Ticks);
  316.             if (exdata->ed_Type == ST_FILE || exdata->ed_Type == ST_LINKFILE) {
  317.  
  318.                 ds = (struct DateStamp *) &exdata->ed_Days;
  319.                 if (isdigit (*exdata->ed_Name) &&
  320.                     (allfiles || tnow > dstot ((long *) ds))) {
  321.  
  322.                     rm_file (path, (const char *) exdata->ed_Name);
  323.                     countbytes += exdata->ed_Size;
  324.                     countfiles += 1;
  325.                   }
  326.             }
  327.  
  328.             exdata = exdata->ed_Next;
  329.         }
  330.     }
  331.  
  332.     if (debug)
  333.         fprintf (stderr, "PEB: exit\n");
  334.     return;
  335. }
  336.  
  337. void
  338. rm_file (const char *path, const char *name)
  339. {
  340.     if (debug)
  341.         fprintf (stderr, "delete %s/%s\n", path, name);
  342.  
  343.     if (!DeleteFile ((UBYTE *) name)) {  /* we are assumed to already be in directory "path" */
  344.         fprintf (stderr, "DeleteFile() error %ld\n", IoErr ());
  345.     }
  346.  
  347.     return;
  348. }
  349.  
  350. void
  351. SetupExAll (void)
  352. {
  353.     eac = AllocDosObject (DOS_EXALLCONTROL, NULL);
  354.     if (!eac) {
  355.         fprintf (stderr, "Cannot allocate ExAllControl, error %ld\n", IoErr ());
  356.         exit (30);
  357.     }
  358.     ead1 = AllocVec (sizeof (struct MyExAllBuf) + 200, MEMF_CLEAR);  /* +200 per Randell Jesup */
  359.     if (!ead1) {
  360.         FreeDosObject (DOS_EXALLCONTROL, eac);
  361.         fprintf (stderr, "Can't get memory for ExAllData\n");
  362.         exit (30);
  363.     }
  364.     ead2 = AllocVec (sizeof (struct MyExAllBuf) + 200, MEMF_CLEAR);  /* +200 per Randell Jesup */
  365.     if (!ead2) {
  366.         FreeVec (ead1);
  367.         FreeDosObject (DOS_EXALLCONTROL, eac);
  368.         fprintf (stderr, "Can't get memory for ExAllData 2\n");
  369.         exit (30);
  370.     }
  371.  
  372.     return;
  373. }
  374.  
  375. void
  376. CleanupExAll (void)
  377. {
  378.     if (eac) {
  379.         FreeDosObject (DOS_EXALLCONTROL, eac);
  380.         eac = NULL;
  381.     }
  382.     if (ead1) {
  383.         FreeVec (ead1);
  384.         ead1 = NULL;
  385.     }
  386.     if (ead2) {
  387.         FreeVec (ead2);
  388.         ead2 = NULL;
  389.     }
  390.  
  391.     return;
  392. }
  393.