From: nick@kralizec.zeta.org.au (Nick Andrew)
Newsgroups: comp.sys.sun.admin
Subject: Re: how to chop wtmp
Date: 6 Nov 92 22:24:30 GMT
Organization: Kralizec Dialup Unix Sydney: +61-2-837-1183 V.32

mills@ccu.umanitoba.ca (Gary Mills) writes:

[ ... a solution to truncating wtmp ... ]

>BS=36
>...
>dd if=$LOG   of=$LOG.0 bs=$BS skip=$SK 2>/dev/null

Both solutions posted here have a common flaw ... they run dd with a very
small blocksize (36), the exact record length of the wtmp file. On a wtmp
file of any size, these scripts will take much more cpu and real time
than they should.

Try using a blocksize of 3600. It works :-)

I don't actually truncate the wtmp on my system. I split it into monthly
units, and calculate the time spent online by each of my members during
that month. I have a program to convert the file to readable ASCII, and
another to reverse the transformation. So, to get a wtmp file containing
all the month's information, I generally have to take the copy made on
the first day of the month and then make sure that no login entries are
split from one to the other.

Here are my sources:

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  readutmp.c writeutmp.c wtmp.upd
# Wrapped by root@kralizec on Sat Nov  7 09:23:34 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'readutmp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'readutmp.c'\"
else
echo shar: Extracting \"'readutmp.c'\" \(943 characters\)
sed "s/^X//" >'readutmp.c' <<'END_OF_FILE'
X/*  @(#) readutmp.c ... Read wtmp file and output a readable/editable version
X*/
X
X#include <stdio.h>
X#include <utmp.h>
X
Xextern	char	*ctime();
X
Xstruct	utmp	utmprec;
X
XFILE	*infp;
Xint	ulen;
X
Xchar	line[9],
X	name[9],
X	host[17];
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	n;
X	char	*cp;
X
X
X	line[8] = name[8] = host[16] = '\0';
X
X	if (argc != 2)
X		usage();
X
X	infp = fopen(argv[1], "r");
X	if (infp == NULL) {
X		perror("readutmp");
X		fprintf(stderr, "Unable to open wtmp\n");
X		exit(1);
X	}
X
X	ulen = sizeof(struct utmp);
X	fprintf(stderr, "ulen is %d\n", ulen);
X
X	while ((n = fread(&utmprec, 1, ulen, infp)) > 0) {
X
X		strncpy(line, utmprec.ut_line, 8);
X		strncpy(name, utmprec.ut_name, 8);
X		strncpy(host, utmprec.ut_host, 16);
X
X		printf("%-8s %-8s %-16s %lx %s",
X			line, name, host, utmprec.ut_time,
X			ctime(&utmprec.ut_time));
X	}
X
X	if (n < 0)
X		perror("readutmp");
X}
X
Xusage() {
X	fprintf(stderr, "Usage: readutmp wtmpfile >output\n");
X	exit(2);
X}
END_OF_FILE
if test 943 -ne `wc -c <'readutmp.c'`; then
    echo shar: \"'readutmp.c'\" unpacked with wrong size!
fi
# end of 'readutmp.c'
fi
if test -f 'writeutmp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'writeutmp.c'\"
else
echo shar: Extracting \"'writeutmp.c'\" \(1058 characters\)
sed "s/^X//" >'writeutmp.c' <<'END_OF_FILE'
X/* @(#) writeutmp.c ... Write a wtmp file from the readable version on the
X**	standard input.
X*/
X
X#include <stdio.h>
X#include <utmp.h>
X
Xstruct	utmp	utmprec;
XFILE	*outfp;
Xint	ulen;
X
Xchar	string[80];
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	n;
X
X	if (argc != 2)
X		usage();
X
X	outfp = fopen(argv[1], "w");
X	if (outfp == NULL) {
X		perror("writeutmp");
X		fprintf(stderr, "Unable to open wtmp\n");
X		exit(1);
X	}
X
X	ulen = sizeof(struct utmp);
X	fprintf(stderr, "ulen is %d\n", ulen);
X
X	while (fgets(string, 80, stdin) != NULL) {
X
X		getstring(utmprec.ut_line, string + 0, 8);
X		getstring(utmprec.ut_name, string + 9, 8);
X		getstring(utmprec.ut_host, string + 18, 16);
X		utmprec.ut_time = strtol(string + 35, NULL, 16);
X
X		fwrite(&utmprec, 1, ulen, outfp);
X	}
X
X	fclose(outfp);
X	exit(0);
X}
X
Xgetstring(s1, s2, len)
Xchar	*s1;
Xchar	*s2;
Xint	len;
X{
X	int	i;
X
X	for (i = 0; i < len; ++i) {
X		if (*s2 == ' ')
X			*s1 = '\0';
X		else
X			*s1 = *s2;
X		++s1;
X		++s2;
X	}
X}
X
Xusage() {
X	fprintf(stderr, "Usage: writeutmp wtmpfile <input\n");
X	exit(2);
X}
X
X/* end of writeutmp.c */
END_OF_FILE
if test 1058 -ne `wc -c <'writeutmp.c'`; then
    echo shar: \"'writeutmp.c'\" unpacked with wrong size!
fi
# end of 'writeutmp.c'
fi
if test -f 'wtmp.upd' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wtmp.upd'\"
else
echo shar: Extracting \"'wtmp.upd'\" \(1058 characters\)
sed "s/^X//" >'wtmp.upd' <<'END_OF_FILE'
X#!/bin/csh
X# Concatenate all the wtmp logs which were written since the system
X# started, and put them into /usr/adm/wtmp.user. Find which users
X# have been online for more than 40 hours.
X
Xcd /var/adm
X
X# Test if there is no wtmp file for last month
X
Xset m=`date +%m`
Xset y=`date +%y`
X@ x=$y - 1
Xif ( $m == "01" ) set lm="${x}12"
Xif ( $m == "02" ) set lm="${y}01"
Xif ( $m == "03" ) set lm="${y}02"
Xif ( $m == "04" ) set lm="${y}03"
Xif ( $m == "05" ) set lm="${y}04"
Xif ( $m == "06" ) set lm="${y}05"
Xif ( $m == "07" ) set lm="${y}06"
Xif ( $m == "08" ) set lm="${y}07"
Xif ( $m == "09" ) set lm="${y}08"
Xif ( $m == "10" ) set lm="${y}09"
Xif ( $m == "11" ) set lm="${y}10"
Xif ( $m == "12" ) set lm="${y}11"
Xset wtmpfile="wtmp.$lm"
X
Xtest -f $wtmpfile
X
Xif ( $status != 0 ) then
X#	Save it and make a new one
X	echo `date` "Moving wtmp to $wtmpfile"
X	mv wtmp $wtmpfile
X	touch wtmp
X	chmod 664 wtmp
Xelse
X	set wtmpfile="wtmp"
Xendif
X	
X/usr/etc/ac -w $wtmpfile -p | sed 's/^.//' | sort >/home/guest/usage.today
Xchmod 644 /home/guest/usage.today
X
Xexit 0
X
X# end of wtmp.upd
END_OF_FILE
if test 1058 -ne `wc -c <'wtmp.upd'`; then
    echo shar: \"'wtmp.upd'\" unpacked with wrong size!
fi
chmod +x 'wtmp.upd'
# end of 'wtmp.upd'
fi
echo shar: End of shell archive.
exit 0
-- 
Kralizec Dialup Unix (Public Access)    Data: +61-2-837-1183, 14400 24hrs 8N1
Zeta Microcomputer Software             Data: +61-2-837-1868, 2400 24hrs 8N1
P.O. Box 177, Riverstone NSW 2765       Plan: To beat Gnuchess 4.1 !