/* login.c

   Login logging code... */

/*
 * Copyright (c) 1995 RadioMail Corporation.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of RadioMail Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY RADIOMAIL CORPORATION AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * RADIOMAIL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software was written for RadioMail Corporation by Ted Lemon
 * under a contract with Vixie Enterprises, and is based on an earlier
 * design by Paul Vixie.
 */

#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1995 RadioMail Corporation.  All rights reserved.\n";
#endif /* not lint */

#include "osdep.h"
#include "cdefs.h"
#include "global.h"
#include <stdio.h>
#include <fcntl.h>
#include <syslog.h>
#include "mcap.h"
#include "ttio.h"

static int logged_in = 0;
static int slot;
static struct utmp utRec;

static void loginout PROTO ((void));

/* Record login in utmp and wtmp, and if necessary, tell the kernel. */

void do_login (name, ttyName)
     char *name;
     char *ttyName;
{
  struct lastlog ll;
  int fd;

  SETLOGIN (name);

  /* At this point, we have carrier, so it's time to log the login... */
  strncpy (utRec.ut_line, ttyName, UT_LINESIZE);
  strncpy (utRec.ut_name, name, UT_NAMESIZE);
  utRec.ut_host [0] = 0;

  loginout ();
}

/* Remove utmp record, add wtmp logout record... */
void do_logout ()
{
  if (logged_in)
    loginout ();
}

/* Record time in global utmp record, then write it to utmp, 
   wtmp and lastlog. */

static void loginout ()
{
  int fd;
  struct lastlog ll;

  /* Set the time... */
  time (&utRec.ut_time);

  /* If this is a login, record it in the lastlog file. */
  if (!logged_in)
    {
      /* Set the lastlog entry... */
      if ((fd = open (_PATH_LASTLOG, O_WRONLY, 0)) < 0)
	syslog (LOG_ERR, "Unable to open %s: %m", _PATH_LASTLOG);
      else
	{
	  strcpy (ll.ll_line, utRec.ut_line);
	  ll.ll_host [0] = 0;
	  ll.ll_time = utRec.ut_time;
	  
	  if (lseek (fd, (off_t)32767 * sizeof ll, SEEK_SET) < 0)
	    syslog (LOG_ERR, "Unable to seek in %s: %m", _PATH_LASTLOG);
	  else
	    {
	      if (write (fd, &ll, sizeof ll) < 0)
		syslog (LOG_ERR, "Unable to write lastlog entry: %m");
	    }
	  close (fd);
	}
    }

  /* Record both logins and logouts in the wtmp file... */
  if ((fd = open (_PATH_WTMP, O_WRONLY | O_APPEND, 0)) < 0)
    syslog (LOG_ERR, "Unable to open %s: %m", _PATH_WTMP);
  else
    {
      int status = write (fd, &utRec, sizeof utRec);
      if (status < 0)
	syslog (LOG_ERR, "Can't write wtmp record: %m");
      else if (status != sizeof utRec)
	syslog (LOG_ERR, "Short write on wtmp record.");
      close (fd);
    }

  /* Record both logins and logouts in utmp file, but if this is a
     logout, zero the ut_name entry... */
  if (logged_in)
    memset (utRec.ut_name, 0, sizeof utRec.ut_name);

  /* Get the tty slot on login (we already have it on logout)... */
  else
    {
      slot = ttyslot ();
      if (!slot)
	warn ("Unable to locate tty slot for utmp.");
    }

  /* If we found the slot, record the login or logout. */
  if (slot)
    {
      if ((fd = open (_PATH_UTMP, O_WRONLY, 0)) < 0)
	warn ("Unable to open %s: %m", _PATH_UTMP);
      else
	{
	  if (lseek (fd, slot * sizeof utRec, SEEK_SET) < 0)
	    warn ("Unable to seek to slot %d of %s: %m", slot, _PATH_UTMP);
	  else
	    {
	      int status = write (fd, &utRec, sizeof utRec);
	      if (status < 0)
		warn ("Unable to write utmp entry: %m");
	      else if (status != sizeof utRec)
		warn ("Short write on utmp entry.");
	    }
	  close (fd);
	}
    }
  if (!logged_in)
    logged_in = 1;
}
