home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2030 / expired.c
Encoding:
C/C++ Source or Header  |  1990-12-28  |  4.2 KB  |  231 lines

  1. /*
  2.  * expired.c
  3.  * 11/6/90
  4.  * John A. Limpert (johnl@n3dmc.svr.md.us)
  5.  *
  6.  * 'smart' news expiration daemon for UNIX System V Release 3
  7.  *
  8.  * This program will expire the oldest 1/3 of news whenever
  9.  * free space is less than 10% on the news filesystem.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <sys/statfs.h>
  15. #include <sys/stat.h>
  16. #include <signal.h>
  17. #include <errno.h>
  18. #include <time.h>
  19. #include <string.h>
  20.  
  21. #ifndef SPOOL
  22. #define SPOOL    "/usr/spool/news"        /* news spool directory */
  23. #endif
  24.  
  25. #ifndef ETFILE
  26. #define ETFILE    "/usr/lib/news/expire_time"    /* expiration cutoff time */
  27. #endif
  28.  
  29. #ifndef LOGFILE
  30. #define LOGFILE    "/usr/lib/news/expired.log"    /* expired log file */
  31. #endif
  32.  
  33. #ifndef MINFREE
  34. #define MINFREE    0.1                /* desired free space */
  35. #endif
  36.  
  37. /* prototype expire command */
  38. #ifndef CMD
  39. #define CMD    "/bin/su news -c \"/usr/lib/news/expire -e%f -E%f\""
  40. #endif
  41.  
  42. /* seconds in day */
  43. #define DAY    (24L*60L*60L)
  44.  
  45. struct utimbuf {
  46.   time_t actime;    /* access time */
  47.   time_t modtime;    /* modification time */
  48. };
  49.  
  50. /* external */
  51. extern void exit();
  52. extern void perror();
  53. extern unsigned sleep();
  54. extern time_t time();
  55.  
  56. /* forward */
  57. extern time_t get_mtime();
  58. extern void log();
  59. extern void set_mtime();
  60.  
  61. /* program name */
  62. char *pname;
  63.  
  64. /*ARGSUSED*/
  65. int
  66. main(argc, argv)
  67. int argc;
  68. char **argv;
  69. {
  70.   struct statfs part_stat;
  71.   time_t delta, now, oldest_news;
  72.   double keep;
  73.   char cmdbuf[256];
  74.   int pid;
  75.   long minfree;
  76.  
  77.   pname = argv[0];
  78.  
  79.   /* ignore user signals */
  80.   (void) signal(SIGHUP, SIG_IGN);
  81.   (void) signal(SIGINT, SIG_IGN);
  82.   (void) signal(SIGQUIT, SIG_IGN);
  83.  
  84.   /* go into background */
  85.   if ((pid = fork()) < 0) {
  86.     perror(pname);
  87.     exit(1);
  88.   }
  89.   if (pid != 0)
  90.     exit(0);
  91.  
  92.   log("running...");
  93.  
  94.   for (;;) {
  95.     /* wait for exhaustion of disk space */
  96.     for (;;) {
  97.       if (statfs(SPOOL, &part_stat, sizeof(struct statfs), 0) < 0) {
  98.     perror(SPOOL);
  99.     exit(1);
  100.       }
  101.  
  102.       minfree = part_stat.f_blocks*MINFREE;
  103.  
  104.       if (part_stat.f_bfree < minfree)
  105.     break;
  106.  
  107.       (void) sleep(60);
  108.     }
  109.  
  110.     /* discard oldest 1/3 of news */
  111.     oldest_news = get_mtime(ETFILE);
  112.     now = time((time_t *) 0);
  113.     delta = now - oldest_news;
  114.     delta = (delta*2)/3;
  115.     oldest_news = now - delta;
  116.     set_mtime(ETFILE, oldest_news);
  117.     keep = ((double) delta)/((double) DAY);
  118.  
  119.     /* generate expire command */
  120.     sprintf(cmdbuf, CMD, keep, keep);
  121.  
  122.     /* update log file */
  123.     log(cmdbuf);
  124.  
  125.     /* run expire */
  126.     if (system(cmdbuf) < 0) {
  127.       perror(pname);
  128.       exit(1);
  129.     }
  130.   }
  131.   /*NOTREACHED*/
  132. }
  133.  
  134. /* get_mtime -- get modification time of specified file */
  135.  
  136. time_t
  137. get_mtime(path)
  138. char *path;
  139. {
  140.   struct stat file_stat;
  141.   struct utimbuf ut;
  142.   int fd;
  143.  
  144.   /* does file exist? */
  145.   if (stat(path, &file_stat) < 0 && errno == ENOENT) {
  146.     /* create it */
  147.     if ((fd = creat(path, 0)) < 0) {
  148.       perror(path);
  149.       exit(1);
  150.     }
  151.     if (close(fd) < 0) {
  152.       perror(path);
  153.       exit(1);
  154.     }
  155.     /* backdate two weeks */
  156.     ut.actime = ut.modtime = time((time_t *) 0) - 14L*DAY;
  157.     if (utime(path, &ut) < 0) {
  158.       perror(path);
  159.       exit(1);
  160.     }
  161.   }
  162.  
  163.   /* get inode info */
  164.   if (stat(path, &file_stat) < 0) {
  165.     perror(path);
  166.     exit(1);
  167.   }
  168.  
  169.   /* return modification time */
  170.   return file_stat.st_mtime;
  171. }
  172.  
  173. /* set_mtime -- set modification and access time of specified file */
  174.  
  175. void
  176. set_mtime(path, t)
  177. char *path;
  178. time_t t;
  179. {
  180.   struct stat file_stat;
  181.   struct utimbuf ut;
  182.   int fd;
  183.  
  184.   /* does file exist? */
  185.   if (stat(path, &file_stat) < 0 && errno == ENOENT) {
  186.     /* create it */
  187.     if ((fd = creat(path, 0)) < 0) {
  188.       perror(path);
  189.       exit(1);
  190.     }
  191.     if (close(fd) < 0) {
  192.       perror(path);
  193.       exit(1);
  194.     }
  195.   }
  196.  
  197.   /* record time in file inode */
  198.   ut.actime = ut.modtime = t;
  199.   if (utime(path, &ut) < 0) {
  200.     perror(path);
  201.     exit(1);
  202.   }
  203. }
  204.  
  205. /* log -- write time tagged string to log file */
  206.  
  207. void
  208. log(s)
  209. char *s;
  210. {
  211.   FILE *logf;
  212.   time_t t;
  213.   char *p, tbuf[32];
  214.  
  215.   /* open log file */
  216.   if ((logf = fopen(LOGFILE, "a")) == NULL) {
  217.     fprintf(stderr, "%s: can't append to %s\n", pname, LOGFILE);
  218.     exit(1);
  219.   }
  220.  
  221.   /* time in ASCII without newline */
  222.   t = time((time_t *) 0);
  223.   (void) strcpy(tbuf, ctime(&t));
  224.   if ((p = strchr(tbuf, '\n')) != NULL)
  225.       *p = '\0';
  226.  
  227.   /* append time tagged entry to log file */
  228.   fprintf(logf, "%s: %s\n", tbuf, s);
  229.   fclose(logf);
  230. }
  231.