/* this is here for a quick fix of patching a "still logged in"
 * entry for a killed jmchat process that didn't have time to
 * write a logout entry to /var/log/wtmp.
 */

#include <stdio.h>
#include <stdlib.h>    /* for strncpy */

#include <unistd.h>    /* for crypt(3) */
#include <pwd.h>       /* for getpwnam(3) */
#include <sys/types.h> /* for getpwnam(3) */
#include <errno.h>  /* for errno, ENOMEM */

#include <utmp.h>

#define WTMPLOG "/var/log/wtmp"
#define WTMPLOG_test "./thewtmp"

/* partially initialize an entry right after accept(), to be
 * filled in after the rest of the info's available (at authent. time).
 */
void initlogentry (struct utmp *pentry,
		   char *fromhost, unsigned long hostaddr) {
  strncpy(pentry->ut_host, fromhost, UT_HOSTSIZE);
  pentry->ut_addr=hostaddr;
}

/* initialize an entry and write it to wtmp file fname */
void writeloginentry (struct utmp *pentry, char *username,
		      char *fname, int portnum) {
  pentry->ut_type=USER_PROCESS;
  pentry->ut_pid=getpid();
  time(&(pentry->ut_time));
  strncpy(pentry->ut_user, username, UT_NAMESIZE);

  /* time_t is long int; add bits to get a fake id. */
  {
    char *fakechar;
    int sum = portnum;

    /* now assign it to ut_line */
    sprintf (pentry->ut_line, "slforum/%d", sum);
    /* and to ut_id */
    fakechar = pentry->ut_id;  /* a-z for first char of id */
    *fakechar = (char) (((int)'a') + sum/36);
    fakechar++;  /* second char of id */
    sum %= 36;
    if (sum < 26)  /* a-z */
      *fakechar = (char) (((int)'a') + sum);
    else	   /* 0-9 */
      *fakechar = (char) (((int)'0') - 26 + sum);
  }
}

/* write an entry (initialized by writeloginentry) to wtmp file fname */
void writelogoutentry (struct utmp *pentry, char *fname) {
  FILE *wtmpf = fopen (fname, "a");
  if (wtmpf == NULL) {
    perror ("opening wtmp-style logfile");
    fprintf (stderr, "for file '%s'\n", fname );
  }
  time(&(pentry->ut_time));
  memset(pentry->ut_user,0,UT_NAMESIZE);
  fwrite (pentry, sizeof(struct utmp), 1, wtmpf );
  fclose (wtmpf);
}

void fixit (char *uname, const int portnum, char *fromhost) {
  struct utmp ent;
  initlogentry (&ent, fromhost, 0x80808080);
  writeloginentry (&ent, uname, WTMPLOG, portnum);
  writelogoutentry (&ent, WTMPLOG);
}

int main(void) {
  struct utmp ent;

  // initlogentry (&ent, "d185cf5a6.twcny.", 0x80808080);
  // writeloginentry (&ent, "adep", WTMPLOG, 734);
  // writelogoutentry (&ent, WTMPLOG);
  /*
  fixit ("aafergus", 102, "localhost");
  fixit ("jeremy", 91, "localhost");
  fixit ("jadaris", 54, "adala.smith.cis.");
  fixit ("jadaris", 146, "adala.smith.cis.");
  fixit ("jadaris", 93, "adala.smith.cis.");
   */

  fixit ("jeremy", 213, "localhost");

  return 0;
}
