home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume03 / prune < prev    next >
Encoding:
Internet Message Format  |  1988-09-11  |  4.9 KB

  1. From: genrad!ihnp4!infoswx!bees (Ray Davis)
  2. Subject: prune.c - prunes log files
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 3, Issue 95
  7. Submitted by: genrad!ihnp4!infoswx!bees (Ray Davis)
  8.  
  9.  
  10. John,
  11.  
  12. The following is a program I wrote to "prune" log files.  The purpose
  13. of this is to keep files that keep getting larger from getting too
  14. large.  I became annoyed at having to search and remember where these
  15. files are, then make them smaller by hand, every time disk space gets
  16. tight.  I also didn't like the idea of having a separate cron entry for
  17. every log file I wanted to deal with.
  18.  
  19. While prune is not extremely robust, it is very functional.  It
  20. compiles and runs as is under 4.2BSD.  I have not tested it under
  21. System * or Xenix, however I believe it should run as is or with little
  22. modification.
  23.  
  24.     Ray Davis        Teknekron Infoswitch Corporation
  25.     ihnp4!infoswx!bees    1784 Firman Drive
  26.     (214)644-0570        Richardson, Texas   75081
  27.  
  28. . . . . . . . . . . . . . . . . . Clip Here . . . . . . . . . . . . . . . . .
  29. /*
  30.  *    prune - clips off the tops of a list of files described in the
  31.  *        file /etc/prune_list. Designed to be run periodically
  32.  *        from cron, the idea is to automatically shorten log
  33.  *        files that grow forever. This file contains a list of
  34.  *        files (full pathname), and the number of blocks that
  35.  *        should be retained.  To retain some sanity, prune will
  36.  *        clip the file after the next newline. The file
  37.  *        /etc/prune_list should look something like:
  38.  *
  39.  *            /usr/adm/aculog        10
  40.  *            /usr/adm/leo.log    5
  41.  *            /usr/adm/messages    200
  42.  *            /usr/adm/sup_log    5
  43.  *
  44.  *        The crontab entry on infoswx for prune looks like:
  45.  *
  46.  *            0 5 * * * /etc/prune >/usr/adm/prune.log 2>&1
  47.  *
  48.  *        Compile with:  cc -O -o prune prune.c
  49.  *
  50.  *        The following defines may be adjusted to suit your taste
  51.  *        and your system block size.
  52.  *
  53.  *    Ray Davis  infoswx!bees  09/25/85
  54.  */
  55.  
  56. #define    PRUNELIST    "/etc/prune_list"
  57. #define    BLOCKSIZE    1024
  58.  
  59. #ifdef USG    /* for System III, System V, or Xenix */
  60. #define    index        strchr
  61. #endif
  62.  
  63. #define    FALSE        (0)
  64. #define    TRUE        (~0)
  65. #define    REWIND(F)    (lseek(F,0,0))
  66.  
  67. #include    <sys/types.h>
  68. #include    <sys/stat.h>
  69. #include    <sys/file.h>
  70. #include    <stdio.h>
  71.  
  72. extern    int    errno;
  73. extern    char    *index();
  74. char    tempfile[] = "/usr/tmp/prune:XXXXXX";
  75.  
  76. main(argc, argv)
  77. int    argc;
  78. char    **argv;
  79. {
  80.     int    pfd,
  81.         tfd,
  82.         cfd,
  83.         nblocks,
  84.         new_line_found,
  85.         bytes_read,
  86.         nlbytes;
  87.     char    file[128],
  88.         block[BLOCKSIZE+1],
  89.         *nl;
  90.     long    nbytes;
  91.     FILE    *pstream;
  92.     struct    stat    cstat;
  93.  
  94.     block[BLOCKSIZE] = '\0';
  95.  
  96.     /* open prune list */
  97.     if ((pfd = open(PRUNELIST, O_RDONLY)) < 0)
  98.         errabort(*argv, "open", PRUNELIST, TRUE);
  99.     pstream = fdopen(pfd, "r");
  100.  
  101.     /* create unique tempfile */
  102.     mktemp(tempfile);
  103.  
  104.     /* while read each filename & #blocks */
  105.     while ((fscanf(pstream, "%s%d", file, &nblocks)) != EOF) {
  106.         fprintf(stderr, "pruning %s to %d blocks\n", file, nblocks);
  107.         /* open filename */
  108.         if ((cfd = open(file, O_RDWR)) < 0) {
  109.             errabort(*argv, "open", file, FALSE);
  110.             continue;
  111.         }
  112.         /* seek #blocks from the end of file */
  113.         nbytes = - (nblocks * BLOCKSIZE);
  114.         if ((fstat(cfd, &cstat)) < 0) {
  115.             errabort(*argv, "fstat", file, FALSE);
  116.         } else {
  117.             if (cstat.st_size <= -(nbytes)) {
  118.                 fprintf(stderr, "%s: %s: not large enough to prune\n", *argv, file);
  119.             } else {
  120.                 if ((lseek(cfd, nbytes, 2)) < 0) {
  121.                     fprintf(stderr, "%s: %s: error on seek\n", *argv, file);
  122.                 } else {
  123.                     /* open tempfile */
  124.                     if ((tfd = open(tempfile, O_CREAT|O_RDWR|O_TRUNC, 0600)) < 0)
  125.                         errabort(*argv, "open", tempfile, TRUE);
  126.                     /* copy to tempfile */
  127.                     new_line_found = FALSE;
  128.                     while ((bytes_read = read(cfd, block, BLOCKSIZE)) > 0) {
  129.                         if (new_line_found) {
  130.                             if ((write(tfd, block, bytes_read)) != bytes_read)
  131.                                 errabort(*argv, "write", tempfile, FALSE);
  132.                         } else {
  133.                             if ((nl = index(block, '\n')) == NULL) {
  134.                                 nl = block;
  135.                             } else {
  136.                                 nl++;
  137.                                 new_line_found = TRUE;
  138.                             }
  139.                             nlbytes = bytes_read - (nl - block);
  140.                             if ((write(tfd, nl, nlbytes)) != nlbytes)
  141.                                 errabort(*argv, "write", tempfile, FALSE);
  142.                         }
  143.                     }
  144.                     if (bytes_read < 0) {
  145.                         errabort(*argv, "read", file, FALSE);
  146.                     } else {
  147.                         /* re-open filename to truncate */
  148.                         close(cfd);
  149.                         if ((cfd = open(file, O_RDWR|O_TRUNC)) < 0) {
  150.                             errabort(*argv, "re-open", file, FALSE);
  151.                             continue;
  152.                         }
  153.                         /* overwrite file with tempfile */
  154.                         REWIND(tfd);
  155.                         while ((bytes_read = read(tfd, block, BLOCKSIZE)) > 0) {
  156.                             if ((write(cfd, block, bytes_read)) != bytes_read)
  157.                                 errabort(*argv, "write", file, FALSE);
  158.                         }
  159.                         if (bytes_read < 0)
  160.                             errabort(*argv, "read", tempfile, FALSE);
  161.                     }
  162.                 }
  163.             }
  164.         }
  165.         close(cfd);
  166.         close(tfd);
  167.     }
  168.     /* remove tempfile */
  169.     unlink(tempfile);
  170.     exit(0);
  171. }
  172.  
  173. errabort(program, function, filename, should_exit)
  174. char    *program,
  175.     *function,
  176.     *filename;
  177. int    should_exit;
  178. {
  179.     char    errbuff[128];
  180.  
  181.     sprintf(errbuff, "%s: %s(%s)", program, function, filename);
  182.     perror(errbuff);
  183.     if (should_exit)
  184.         exit(errno);
  185. }
  186. /* end of prune.c */
  187.  
  188.