Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Nov 1998 19:37:25 +1100
From:      "John Saunders" <john.saunders@scitec.com.au>
To:        "Oles' Hnatkevych" <gnut@uct.kiev.ua>
Cc:        <freebsd-questions@FreeBSD.ORG>
Subject:   RE: wtmp
Message-ID:  <004a01be0d4e$8200c010$6cb611cb@saruman.scitec.com.au>
In-Reply-To: <Pine.BSF.4.02A.9811110927380.1062-100000@gw.uct.kiev.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
This is probably what you want. I have a collection of wtmp tools
I hacked up ages ago. Maybe I should make a formal release and a
port for it? :-)

cc zapwtmp.c -o zapwtmp

If you want to test it not on your main wtmp file...

cc -DDEBUG zapwtmp.c -o zapwtmp
cp /var/log/wtmp .
last -f wtmp | head -10
./zapwtmp ttyp0 fred host.com YYYYMMDDHHMM
last -f wtmp | head -10

I would also suggest using it during a quiet time as there is
an unavoidable race condition which may cause lost entries.
Although the wtmp file will not be corrupted.

Enjoy...

/*
 * zapwtmp.c:
 *
 * Possible bugs.
 *
 * There is never any locking done on the wtmp file. I could have added file
 * locking to this program, however it would not help as the other programs
 * that write to wtmp do not have file locking either. This means there is a
 * small window of possibility that a record can get lost. However this
window
 * is much smaller than clnwtmp.c, and if used at a quiet period during the
 * day will reduce the risk to almost 0%.
 *
 * Example use.
 *
 * zapwtmp ttyp1 fred host.com 199604131014
 */

#include <unistd.h>
#include <paths.h>
#include <fcntl.h>
#include <utmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/*
 * Make a copy of your wtmp file and play around with DEBUG enabled.
 */
#ifdef DEBUG
#undef _PATH_WTMP
#define _PATH_WTMP	"wtmp"
#endif

static int convert_date(char *date_str, time_t *cvt_time);

int main(int argc, char **argv)
{
	struct utmp	wtmp;
	time_t		search_time;
	time_t		time_delta;
	int		fin, fout;
	int		searching = 0;
	size_t		length = 0;

	if (argc != 5)
	{
		fprintf(stderr, "usage: %s port user host YYYYMMDDHHMM\n", argv[0]);
		return (1);
	}

	if (! convert_date(argv[4], &search_time))
	{
		fprintf(stderr, "Invalid time \"%s\" (e.g. YYYYMMDDHHMM)\n", argv[4]);
		return (1);
	}

	if ((fin = open(_PATH_WTMP, O_RDONLY)) < 0)
	{
		perror(_PATH_WTMP);
		return (1);
	}

	if ((fout = open(_PATH_WTMP, O_WRONLY)) < 0)
	{
		perror(_PATH_WTMP);
		close(fin);
		return (1);
	}

	/*
	 * Read each wtmp record and sort based on the cutoff date.
	 */
	while (read(fin, &wtmp, sizeof(wtmp)) == sizeof(wtmp))
	{
		if (searching == 0)
		{
			time_delta = (search_time > wtmp.ut_time ?
			              search_time - wtmp.ut_time :
			              wtmp.ut_time - search_time);

			/* Zap the login record */
			if ((strncmp(wtmp.ut_line, argv[1], UT_LINESIZE) == 0) &&
			    (strncmp(wtmp.ut_name, argv[2], UT_NAMESIZE) == 0) &&
			    (strncmp(wtmp.ut_host, argv[3], UT_NAMESIZE) == 0) &&
			    (time_delta <= 60))
			{
#ifdef DEBUG
				printf("Found login record\n");
#endif
				searching = 1;
			}
			else
			{
				write(fout, &wtmp, sizeof(wtmp));
				length += sizeof(wtmp);
			}
		}
		else if (searching == 1)
		{
			/* Zap the logout record */
			if (strncmp(wtmp.ut_line, argv[1], UT_LINESIZE) == 0)
			{
#ifdef DEBUG
				printf("Found logout record\n");
#endif
				searching = 2;
			}
			else
			{
				write(fout, &wtmp, sizeof(wtmp));
				length += sizeof(wtmp);
			}
		}
		else /* searching == 2 */
		{
			write(fout, &wtmp, sizeof(wtmp));
			length += sizeof(wtmp);
		}
	}

	/*
	 * The window mentioned in the bugs section is between the above
	 * read (insde the while loop) and this call to ftruncate.
	 */
	ftruncate(fout, length);

	close(fout);
	close(fin);

	return (0);
}

/*
 * Dipy date conversion. Hopefully it will be OK if it's not provided
 * any "funny" dates.
 */
static int convert_date(char *date_str, time_t *cvt_time)
{
	char		string[5];
	long		date;
	int		year, month, day, hour, min;
	struct tm	cutdate;

	string[4] = '\0';

	string[0] = *date_str; if (*date_str) ++date_str;
	string[1] = *date_str; if (*date_str) ++date_str;
	string[2] = *date_str; if (*date_str) ++date_str;
	string[3] = *date_str; if (*date_str) ++date_str;
	year = atoi(string);
	if (year < 1900)
	{
		return (0);
	}
	year -= 1900;

	string[2] = '\0';

	string[0] = *date_str; if (*date_str) ++date_str;
	string[1] = *date_str; if (*date_str) ++date_str;
	month = atoi(string);
	if ((month < 1) || (month > 12))
	{
		return (0);
	}

	string[0] = *date_str; if (*date_str) ++date_str;
	string[1] = *date_str; if (*date_str) ++date_str;
	day = atoi(string);
	if ((day < 1) || (day > 31))
	{
		return (0);
	}

	string[0] = *date_str; if (*date_str) ++date_str;
	string[1] = *date_str; if (*date_str) ++date_str;
	hour = atoi(string);
	if (hour > 23)
	{
		return (0);
	}

	string[0] = *date_str; if (*date_str) ++date_str;
	string[1] = *date_str; if (*date_str) ++date_str;
	min = atoi(string);
	if (min > 59)
	{
		return (0);
	}

	cutdate.tm_sec   = 0;
	cutdate.tm_min   = min;
	cutdate.tm_hour  = hour;
	cutdate.tm_mday  = day;
	cutdate.tm_mon	 = month - 1;
	cutdate.tm_year  = year;
	cutdate.tm_isdst = -1;

	/*
	 * Check that mktime didn't find any problems.
	 */
	if ((*cvt_time = mktime(&cutdate)) == (time_t)(-1))
	{
		return (0);
	}

	/*
	 * If the month has changed, that means mktime detected a
	 * day that is outside the allowable days for that month.
	 * i.e. you specified the 31st of February!
	 */
	if (cutdate.tm_mon != (month - 1))
	{
		return (0);
	}

	return (1);
}

--   .   +-------------------------------------------------------+
 ,--_|\  | John Saunders    mailto:John.Saunders@scitec.com.au   |
/  Oz  \ | SCITEC LIMITED   Phone +61294289563  Fax +61294289933 |
\_,--\_/ | "By the time you make ends meet, they move the ends." |
      v  +-------------------------------------------------------+


> -----Original Message-----
> From: owner-freebsd-questions@FreeBSD.ORG
> [mailto:owner-freebsd-questions@FreeBSD.ORG]On Behalf Of Oles'
> Hnatkevych
> Sent: Wednesday, 11 November 1998 18:30
> To: Jason C. Wells
> Cc: freebsd-questions@FreeBSD.ORG
> Subject: Re: wtmp
>
>
> >
> > OK. You erased the wtmp file. You want to know if there is
> documentation.
> >
>
> No. I have the file. I just want to remove a record that user XXX
> logged in at the time A and logged out at the time B. To pretend that
> he never did.
>
>
> Best wishes,
>
>     Oles Hnatkevych, http://gnut.kiev.ua
>
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-questions" in the body of the message
>


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?004a01be0d4e$8200c010$6cb611cb>