[comp.sys.next] Trimmer for /usr/adm/wtmp

izumi@pinoko.berkeley.edu (Izumi Ohzawa) (06/19/91)

Here's a little more reasonable file trimmer for /usr/adm/wtmp file.
With the default monthly script (/usr/adm/monthly), the wtmp file
is wiped clean on the first of each month.  It also wipes out
/usr/adm/lastlog, which shouldn't be necessary (lastlog doesn't grow).

-------- cut here -----
/* Program:  wtmptrim -- trims the size of /usr/adm/wtmp file by keeping the  
last N entries.
* Usage:     wtmptrim [numentries]
	where numentries defaults to 2000 entries.

* Valid for 1.0, 2.0, 2.1

* Compile:    cc -O -o wtmptrim wtmptrim.c
	      strip wtmptrim

* Install wtmptrim in /usr/local/bin.
* Modify /usr/adm/monthly as below:
-----------------------------------------------------------------
*** monthly.old Tue Jun 18 18:46:43 1991
--- monthly     Tue Jun 18 18:50:05 1991
***************
*** 5,15 ****
  # commands in here, like pruning of log files
  #
  
! # Trim the lastlog
! cp -p /usr/adm/lastlog /usr/adm/lastlog.old
! cat /dev/null > /usr/adm/lastlog
  
! # Trim wtmp
! cp -p /usr/adm/wtmp /usr/adm/wtmp.old
! cat /dev/null > /usr/adm/wtmp
! 
--- 5,13 ----
  # commands in here, like pruning of log files
  #
  
! # NO NEED to trim the lastlog
! # cp -p /usr/adm/lastlog /usr/adm/lastlog.old
! # cat /dev/null > /usr/adm/lastlog
  
! # Trim wtmp to the last 2000 entries
! /usr/local/bin/wtmptrim 2000
-----------------------------------------------------------------
*/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <utmp.h>
#include <sys/stat.h>

#define DEF_ENTRIES	2000
#define MAXENTRIES	100000
#define MINENTRIES	100
#define WTMPFILE	"/usr/adm/wtmp"
#define TEMPFILE	"/usr/adm/wtmp.new"
#define WTMPOLD		"/usr/adm/wtmp.old"


void main(int argc, char *argv[])
{
int i;
int numtrim = DEF_ENTRIES;
int numcurrent, nemptyto;
FILE *fin_wtmp, *fout_wtmp;
struct stat filestat;
struct utmp s_utmp;

	if(argc > 1) {
		/* if argument is given, interpret argv[1] as numentries */
		i = atoi(argv[1]);
		if(i > MINENTRIES && i <= MAXENTRIES )
			numtrim = i;		/* defaults to DEF_ENTRIES */
	}

	if(stat(WTMPFILE, &filestat)) {
		printf("Can't get stat for file: %s\n", WTMPFILE);
		exit(1);
	}
	else {
	    numcurrent = filestat.st_size / sizeof(s_utmp);
    	    if(numcurrent <= numtrim)
		exit(0);			/* Small, no need to trim file  
*/
	    nemptyto = numcurrent - numtrim;	/* Empty this many records */
	    if ((fin_wtmp = fopen(WTMPFILE, "r")) != NULL &&
	            (fout_wtmp = fopen(TEMPFILE, "w")) != NULL) {
		for(i=0; i<nemptyto; i++)				/*  
Discard old stuff */
		    fread(&s_utmp, sizeof(s_utmp), 1, fin_wtmp);
		while(fread(&s_utmp, sizeof(s_utmp), 1, fin_wtmp))	/* Now,  
copy the rest */
		    fwrite(&s_utmp, sizeof(s_utmp), 1, fout_wtmp);
		(void) fclose(fin_wtmp);
		(void) fclose(fout_wtmp);
		(void) rename(WTMPFILE, WTMPOLD);		/* current one  
to .old */
		(void) rename(TEMPFILE, WTMPFILE);		/* trimmed one  
to wtmp file */
	    }
	    else {
	        printf("Can't open file(s): %s and/or %s\n", WTMPFILE,  
TEMPFILE);
		exit(2);
	    }
	}
	exit(0);
}

-------- cut here -----

Izumi Ohzawa             [ $@Bg_78^=;(J ]
USMail: University of California, 360 Minor Hall, Berkeley, CA 94720
Telephone: (415) 642-6440     Fax:  (415) 642-3323
Standard mail: izumi@violet.berkeley.edu
NeXTmail:      izumi@pinoko.berkeley.edu

nerd@percival.rain.com (Michael Galassi) (06/19/91)

izumi@pinoko.berkeley.edu (Izumi Ohzawa) writes:
>Here's a little more reasonable file trimmer for /usr/adm/wtmp file.
>With the default monthly script (/usr/adm/monthly), the wtmp file
>is wiped clean on the first of each month.  It also wipes out
>/usr/adm/lastlog, which shouldn't be necessary (lastlog doesn't grow).

You got it right there, whoever wrote monthly was asleep.  I use a
slightly more paranoid program which is somewhat  faster.  It only
does one read of the wtmp file and stores the part to keep in a
malloced buffer.  This works nicely as the wtmp structure is only
36 bytes so even keeping 5000 entries only consumes 176 K.

cheers,
-m

--- cut here for wtrim, watch out for .signature at the end ---
/*
** by Michael Galassi -- nerd@percival.rain.com
** this is public domain, you can even say you wrote it,
** I don't care compile with:
**	 cc -ansi -O wtrim.c -o wtrim -object -s
*/

#include <stdio.h>
#include <stdlib.h>
#include <utmp.h>
#include <sys/file.h>
#include <sys/stat.h>

#define WTMP "/usr/adm/wtmp"
#define OWTMP "/usr/adm/wtmp.old"
#define DEFTRIM 1000

void main(int argc, char *argv[])
{
	int size;
	int fd;
	struct stat st;
	struct utmp *ptr;

	if (argc == 2)
		size = atoi(argv[1]) * sizeof(struct utmp);
	else if (argc == 1)
		size = DEFTRIM * sizeof(struct utmp);
	else {
		fprintf(stderr, "usage: %s [count]\n", argv[0]);
		exit(1);
	}
	if (stat(WTMP, &st) < 0) {
		fprintf(stderr, "%s: can't stat " WTMP "\n", argv[0]);
		exit(1);
	}
	if (st.st_size <= size)		/* already OK */
		exit(0);
	if ((fd = open(WTMP, O_CREAT|O_RDWR, 0644)) < 0) {
		fprintf(stderr, "%s: can't open " WTMP "\n", argv[0]);
		exit(1);
	}
	if (lseek(fd, st.st_size - size, L_SET) != st.st_size - size) {
		fprintf(stderr, "%s: can't lseek in " WTMP "\n", argv[0]);
		close(fd);
		exit(1);
	}
	if ((ptr = (struct utmp *) malloc(size)) == (void *)NULL) {
		fprintf(stderr, "%s: can't malloc %d bytes\n", argv[0], size);
		close(fd);
		exit(1);
	}
	if (read(fd, ptr, size) != size) {
		fprintf(stderr, "%s: can't malloc %d bytes\n", argv[0], size);
		free(ptr);
		close(fd);
		exit(1);
	}
	close(fd);
	unlink(OWTMP);
	if (rename(WTMP, OWTMP) < 0) {
		fprintf(stderr, "%s: can't rename " WTMP " to " OWTMP "\n", argv[0]);
		free(ptr);
		exit(1);
	}
	if ((fd = open(WTMP, O_CREAT|O_WRONLY, 0644)) < 0) {
		fprintf(stderr, "%s: can't open new " WTMP "\n", argv[0]);
		free(ptr);
		rename(OWTMP, WTMP);
		exit(1);
	}
	if (write(fd, ptr, size) != size) {
		fprintf(stderr, "%s: can't write new " WTMP "\n", argv[0]);
		free(ptr);
		close(fd);
		unlink(WTMP);
		rename(OWTMP, WTMP);
		exit(1);
	}
	close(fd);
	free(ptr);
	exit(0);
}
-- 
Michael Galassi				| nerd@percival.rain.com
MS-DOS:  The ultimate PC virus.		| ...!tektronix!percy!nerd