prune.c - prunes log files
sources-request at panda.UUCP
sources-request at panda.UUCP
Sat Jan 25 00:04:13 AEST 1986
Mod.sources: Volume 3, Issue 95
Submitted by: genrad!ihnp4!infoswx!bees (Ray Davis)
John,
The following is a program I wrote to "prune" log files. The purpose
of this is to keep files that keep getting larger from getting too
large. I became annoyed at having to search and remember where these
files are, then make them smaller by hand, every time disk space gets
tight. I also didn't like the idea of having a separate cron entry for
every log file I wanted to deal with.
While prune is not extremely robust, it is very functional. It
compiles and runs as is under 4.2BSD. I have not tested it under
System * or Xenix, however I believe it should run as is or with little
modification.
Ray Davis Teknekron Infoswitch Corporation
ihnp4!infoswx!bees 1784 Firman Drive
(214)644-0570 Richardson, Texas 75081
. . . . . . . . . . . . . . . . . Clip Here . . . . . . . . . . . . . . . . .
/*
* prune - clips off the tops of a list of files described in the
* file /etc/prune_list. Designed to be run periodically
* from cron, the idea is to automatically shorten log
* files that grow forever. This file contains a list of
* files (full pathname), and the number of blocks that
* should be retained. To retain some sanity, prune will
* clip the file after the next newline. The file
* /etc/prune_list should look something like:
*
* /usr/adm/aculog 10
* /usr/adm/leo.log 5
* /usr/adm/messages 200
* /usr/adm/sup_log 5
*
* The crontab entry on infoswx for prune looks like:
*
* 0 5 * * * /etc/prune >/usr/adm/prune.log 2>&1
*
* Compile with: cc -O -o prune prune.c
*
* The following defines may be adjusted to suit your taste
* and your system block size.
*
* Ray Davis infoswx!bees 09/25/85
*/
#define PRUNELIST "/etc/prune_list"
#define BLOCKSIZE 1024
#ifdef USG /* for System III, System V, or Xenix */
#define index strchr
#endif
#define FALSE (0)
#define TRUE (~0)
#define REWIND(F) (lseek(F,0,0))
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <stdio.h>
extern int errno;
extern char *index();
char tempfile[] = "/usr/tmp/prune:XXXXXX";
main(argc, argv)
int argc;
char **argv;
{
int pfd,
tfd,
cfd,
nblocks,
new_line_found,
bytes_read,
nlbytes;
char file[128],
block[BLOCKSIZE+1],
*nl;
long nbytes;
FILE *pstream;
struct stat cstat;
block[BLOCKSIZE] = '\0';
/* open prune list */
if ((pfd = open(PRUNELIST, O_RDONLY)) < 0)
errabort(*argv, "open", PRUNELIST, TRUE);
pstream = fdopen(pfd, "r");
/* create unique tempfile */
mktemp(tempfile);
/* while read each filename & #blocks */
while ((fscanf(pstream, "%s%d", file, &nblocks)) != EOF) {
fprintf(stderr, "pruning %s to %d blocks\n", file, nblocks);
/* open filename */
if ((cfd = open(file, O_RDWR)) < 0) {
errabort(*argv, "open", file, FALSE);
continue;
}
/* seek #blocks from the end of file */
nbytes = - (nblocks * BLOCKSIZE);
if ((fstat(cfd, &cstat)) < 0) {
errabort(*argv, "fstat", file, FALSE);
} else {
if (cstat.st_size <= -(nbytes)) {
fprintf(stderr, "%s: %s: not large enough to prune\n", *argv, file);
} else {
if ((lseek(cfd, nbytes, 2)) < 0) {
fprintf(stderr, "%s: %s: error on seek\n", *argv, file);
} else {
/* open tempfile */
if ((tfd = open(tempfile, O_CREAT|O_RDWR|O_TRUNC, 0600)) < 0)
errabort(*argv, "open", tempfile, TRUE);
/* copy to tempfile */
new_line_found = FALSE;
while ((bytes_read = read(cfd, block, BLOCKSIZE)) > 0) {
if (new_line_found) {
if ((write(tfd, block, bytes_read)) != bytes_read)
errabort(*argv, "write", tempfile, FALSE);
} else {
if ((nl = index(block, '\n')) == NULL) {
nl = block;
} else {
nl++;
new_line_found = TRUE;
}
nlbytes = bytes_read - (nl - block);
if ((write(tfd, nl, nlbytes)) != nlbytes)
errabort(*argv, "write", tempfile, FALSE);
}
}
if (bytes_read < 0) {
errabort(*argv, "read", file, FALSE);
} else {
/* re-open filename to truncate */
close(cfd);
if ((cfd = open(file, O_RDWR|O_TRUNC)) < 0) {
errabort(*argv, "re-open", file, FALSE);
continue;
}
/* overwrite file with tempfile */
REWIND(tfd);
while ((bytes_read = read(tfd, block, BLOCKSIZE)) > 0) {
if ((write(cfd, block, bytes_read)) != bytes_read)
errabort(*argv, "write", file, FALSE);
}
if (bytes_read < 0)
errabort(*argv, "read", tempfile, FALSE);
}
}
}
}
close(cfd);
close(tfd);
}
/* remove tempfile */
unlink(tempfile);
exit(0);
}
errabort(program, function, filename, should_exit)
char *program,
*function,
*filename;
int should_exit;
{
char errbuff[128];
sprintf(errbuff, "%s: %s(%s)", program, function, filename);
perror(errbuff);
if (should_exit)
exit(errno);
}
/* end of prune.c */
More information about the Mod.sources
mailing list