/* PIPServer - A deamon for finger protocol v2
 *
 * Copyright (C) 1999 Michael Baumer <baumi@vis.ethz.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* Functions for compatibility with the GNU Finger site daemon 
 *
 * This is intended to allow a site to run GNU Finger
 * and the PFinger in parallel. 
 *
 * The same effect could be achieved with the PFinger site daemon
 * but would require all clients to install the PFinger in.fingerd.
 * Using of this compatibility mode allows to succesively install
 * the PFinger in.fingerd.
 */

#include <config.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

#include "finger.h"
#include "flock.h"
#include "log.h"

/* copied from GNU Finger */

/* Length of the informative items that are returned in a FINGER_PACKET. */
#define USERNAME_LEN 16
#define TTYNAME_LEN 32
#define TTYLOC_LEN 128
#define WHAT_LEN 16

/* What a packet of finger information from a client looks like.  Note that
   times are stored in 32 bits of SECONDS.  Absolute time values are stored
   as seconds since 1970. */
typedef struct {
  char name[USERNAME_LEN];
  char real_name[REALNAME_LEN];
  char host[HOSTNAME_LEN];
  time_t login_time;
  time_t idle_time;
  char ttyname[TTYNAME_LEN];
  char ttyloc[TTYLOC_LEN];
  char what[WHAT_LEN];
} FINGER_PACKET;

/* end copy */

/* read the gnufinger packets
 *
 * similiar to read_utmp()
 */
login_info * gnufinger_read_utmp(login_info *loginlist, int sorted)
{
  FINGER_PACKET packet;
  int fd;
  int nread;
  login_info *current, *tmp;
  login_info first;
  char hostdatafile[strlen(config.gnufingerdir) + 32];
  time_t idlemax;

  /* todo: make this an option */
  idlemax = 600; /* 10min */

  sprintf(hostdatafile, "%s/hostdata", config.gnufingerdir);

  if ((fd = open(hostdatafile, O_RDONLY))<0) {
    log(LOG_ERR, "GNU Finger mode, but could not open hostdata file: %m");
    return NULL;
  }

  /* request a lock */
  if (flock (fd, LOCK_SH) < 0) {
    log(LOG_ERR, "GNU Finger mode: Lock set failed: %m");
    return NULL;
  }

  current = &first;
  current->next = loginlist;
  while (current->next) 
    current = current->next;
  
  /* read the packets */
  while ((nread = read(fd, &packet, sizeof(packet))) == sizeof(packet)) {

    /* Ignore host information packets and root account */
    if ((!strlen(packet.name)) || (!strcmp(packet.name, "root")))
      continue;

    if (sorted) {
      /* check if we already have that user */
      tmp = first.next;
      while(tmp) {
	if (!strcmp(tmp->login_user, packet.name)) {
	  
	  /* check for smallest idle time */
	  if (tmp->idle_time > packet.idle_time) {
	    tmp->idle_time = packet.idle_time;
	    strcpy(tmp->hostname, packet.host);
	  }	   
	  
	  /* check for the earliest login time */
	  if (tmp->login_time > packet.login_time)
	    tmp->login_time = packet.login_time;
	  
	  break;
	}
	tmp = tmp->next;
      }
      if (tmp) 
	continue;
    }

    /* make login info */
 
    /* we use .login_time, .idle_time and .name */
    
    current->next = (login_info *)malloc(sizeof(login_info));
    current=current->next;
    current->next = NULL;
    current->login_time = packet.login_time;
    current->idle_time = packet.idle_time;
    strncpy(current->login_user, packet.name, UT_NAMESIZE);
    strncpy(current->realname, packet.real_name, REALNAME_LEN);
    current->realname[REALNAME_LEN - 1] = '\0';
    strncpy(current->hostname, packet.host, HOSTNAME_LEN);
    current->hostname[HOSTNAME_LEN - 1] = '\0';
    current->login_user[UT_NAMESIZE - 1] = '\0';
    if (current->idle_time < idlemax) 
      strcpy(current->status, "active");
    else
      strcpy(current->status, "idle");
     
  }
  close (fd);
  
  return(first.next);
}


syntax highlighted by Code2HTML, v. 0.9.1