Why is wtmp so big?

john donahue gumby at ucrmath.UCR.EDU
Wed Dec 6 19:13:47 AEST 1989


In article <413 at tabbs.UUCP> aris at tabbs.UUCP (Aris Stathakis) writes:
>From article <1226 at ispi.UUCP>, by jbayer at ispi.UUCP (Jonathan Bayer):
>} rfarris at serene.UUCP (Rick Farris) writes:
>} 
>}>Is this a "log" file, composed of numerous /etc/utmp entries?  Can I
>}>truncate it by copying /etc/utmp to it?  Can I delete it altogether,
>}>and let it recreate itself?
>} 
>} If you delete it then it will not be recreated.  You can truncate it by
>} either copying /etc/utmp to it, or by copying /dev/null to it.
>
>Is there perhaps any program out there ther truncates the /etc/wtmp
>file to the 100 most recent entries?  
>
>Since it is a binary file, this is no trivial task.
>
>Thanks in advance.
>
>Aris
>
>-- 
>Aris Stathakis | Bang: ..!uunet!ddsw1!olsa99!tabbs!aris or aris at tabbs.UUCP
>         - Gimme a beer and money sandwich....  Hold the bread -
>                                                  - Waldo (D.R.) Dobbs

Well, I thought about this for a bit and then decided it would be a useful
utility to have on my own system. Thus, I sat down and wrote it tonight.
It was a pretty fun program to write and I think it works pretty well.
Perhaps, if I get feedback saying that it works and there's no problems
I'll submit it to alt.sources or something since someone else out there
might want to play with it. Let me know what you think and REMEMBER:
don't look at the source code now, take it, and then set your TAB width
to *4* within "vi" or whatever and THEN look at it (Sorry, I like that
size of TAB)! =)

Cheers!

-- John Donahue

--
INET: gumby at ucrmath.ucr.edu
UUCP: {ucsd, uci, ucdavis}!ucrmath!gumby

"Consequences, schmonsequences, as long as I'm rich" -- Daffy Duck
--
Here's the code:

/*
** wsize.c - Utility program to truncate the /etc/wtmp log file.
**
** NOTE: To properly view this source, set your TAB width to 4!
**
** This program will, if needed, truncate the /etc/wtmp file to the desired
** length of records. By default, this value is 1000, but may be defined by
** passing the numeric argument during program execution.
**
** The reason this default value is 1000 is that the utmp structure itself
** is VERY small (36 bytes on my system) and a 36K file is trivial when
** most wtmp files usually get to be several hundred thousand before we
** get around to truncating them! Also, I'm not an expert, but "weird"
** things may happen if you delete recent wtmp records, it's best to keep
** the last 1000 or so IMHO.
**
** To compile: cc wsize.c -o wsize
** su to root: chown bin wsize
**             chgrp bin wsize
**             chmod 700 wsize
**             mv wsize /etc
**
** Written By: John Donahue (alchemy!gumby at ucrmath.ucr.edu) on 05-Dec-89
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include <utmp.h>

#define	PASS	struct passwd
#define	STAT	struct stat
#define	UTMP	struct utmp
#define TMPNAM	"/tmp/wtmp"

/*
** WSIZE
*/

main (argc, argv)

int		argc;				/* Argument counter from command line		*/
char	*argv[];			/* Arguments from command line (strings)	*/

{
	int		fs, ft;			/* File descriptors (source, target)		*/
	int		wsize;			/* Desired size of /etc/wtmp file			*/
	long	begin;			/* Where to begin copying (lseek value)		*/
	PASS	*pwuser;		/* Structure containing passwd entry		*/
	PASS	*getpwnam ();	/* System call to get passwd entry by login	*/
	STAT	filestat;		/* File statistics structure				*/
	UTMP	temp;			/* Temporary utmp structure					*/

/*
** If argument counter equals two, then assume that argument is the desired
** length (in utmp records) of the eventual /etc/wtmp file.
*/

	if (argc == 2)
		wsize = atoi (argv[1]);
	else
		wsize = 1000;

/*
** If UID and GID of login "bin" cannot be discerned, then abort program
** as these are necessary arguments for "chown ()" system call later.
*/

	if ((pwuser = getpwnam ("bin")) == (PASS *) 0) {
		fprintf (stderr, "%s: Cannot locate user \"bin\".\n", argv[0]);
		exit (1);
	}

/*
** Determine existance and size of current /etc/wtmp file. If it doesn't
** exist, abort program (accounting is not kept on system). If it does,
** make sure there is work to be done (current size is greater than
** desired size).
*/

	if (stat ("/etc/wtmp", &filestat)) {
		fprintf (stderr, "%s: \"/etc/wtmp\" not present!\n", argv[0]);
		exit (1);
	}

	if (filestat.st_size < (wsize * sizeof (UTMP))) {
		fprintf (stderr, "%s: \"/etc/wtmp\" too small! (Current size: %d records)\n", argv[0], filestat.st_size / sizeof (UTMP));
		exit (1);
	}

/*
** Attempt to open both the existing /etc/wtmp file and a temporary file in
** the /tmp directory.
*/

	if ((fs = open ("/etc/wtmp", O_RDONLY)) == -1) {
		fprintf (stderr, "%s: Could not open \"/etc/wtmp!\"\n", argv[0]);
		exit (1);
	}

	if ((ft = open (TMPNAM, O_WRONLY | O_CREAT, 0644)) == -1) {
		fprintf (stderr, "%s: Could not open \"%s!\"\n", argv[0], TMPNAM);
		close (fs);
		exit (1);
	}

/*
** Seek to appropriate location within /etc/wtmp file so that copying may
** begin.
*/

	begin = filestat.st_size - (wsize * sizeof (UTMP));

	if (lseek (fs, begin, 0) == -1) {
		fprintf (stderr, "%s: Could not seek \"/etc/wtmp!\"\n", argv[0]);
		close (fs);
		close (ft);
		unlink (TMPNAM);
		exit (1);
	}

/*
** Copy each record, one at a time, from /etc/wtmp to TMPNAM using successive
** read () and write () system calls.
*/

	while (read (fs, &temp, sizeof (UTMP)) > 0)
		write (ft, &temp, sizeof (UTMP));

/*
** Close both files and "rename".
*/

	close (fs);
	close (ft);

	if (unlink ("/etc/wtmp")) {
		fprintf (stderr, "%s: Could not unlink \"/etc/wtmp!\"\n", argv[0]);
		unlink (TMPNAM);
		exit (1);
	}

	if (link (TMPNAM, "/etc/wtmp")) {
		fprintf (stderr, "%s: Panic! Original wtmp removed, cannot link new!\n", argv[0]);
		fprintf (stderr, "%s: New wtmp filename is \"%s\", link manually if possible.\n", argv[0], TMPNAM);
		exit (1);
	}
	unlink (TMPNAM);

/*
** In case "umask" ruined the intended permissions for the /etc/wtmp file,
** let's set them correctly to make sure. Additionally, the new file may
** be owned by root (since it is assumed that this is going to be executed
** only by root) so let's give it the proper owner and group of "bin".
*/

	chmod ("/etc/wtmp", 00644);
	chown ("/etc/wtmp", pwuser->pw_uid, pwuser->pw_gid);

/*
** Inform user that truncation was successful.
*/

	fprintf (stderr, "%s: \"/etc/wtmp\" successfully truncated to last %d records.\n", argv[0], wsize);
	exit (0);
}

/*
** End of wsize.c
*/



More information about the Comp.unix.xenix mailing list