/* dbminfo.c -- How to store and retrieve information about users using
   gdbm (or ndbm). */

/* Copyright (C) 1988,1990 Free Software Foundation, Inc.

   This file is part of GNU Finger.

   GNU Finger 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 1, or (at your
   option) any later version.

   GNU Finger 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 GNU Finger; see the file COPYING.  If not, write to the
   Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */

#include <stdio.h>
#include <config.h>
#include <pwd.h>
#include <ndbm.h>
#include <fingerpaths.h>
#include <general.h>
#include <packet.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include "recedit.h"

/* Location of the lastlog file.  This is for regular fingering. */
#define LASTLOG_FILE "/usr/adm/lastlog"

#if defined (LASTLOG_FILE)
#include <lastlog.h>
#endif

/* Print out information about the user in ENTRY on STREAM.
   Display info for the local machine if LOCALFLAG is nonzero. */
display_long_info (entry, stream, localflag)
  struct passwd *entry;
  FILE *stream;
  int localflag;
{
  FINGER_PACKET **packets;
  register int i;
  int packets_output = 0;
  DBM *database;
  datum key, info;
  FIELD_DESC **fields;
  struct stat finfo;
  char *path_concat ();


  localflag = 1;

  if (localflag)
    packets = get_finger_data (1);
  else
    packets = NULL;

  /* Get the format of the data. */
  fields = re_read_description_file (FORMATFILE);

  if (!fields)
    exit (1);

  database = dbm_open (DBMINFO, O_RDONLY, 0666);

  if (!database)
    {
      fprintf (stream, "Cannot access database `%s'.\n", DBMINFO);
      return;
    }

  key.dsize = 1 + strlen (entry->pw_name);
  key.dptr = savestring (entry->pw_name);

  info = dbm_fetch (database, key);
  dbm_close (database);
  free (key.dptr);

  if (!info.dptr)
    {
      fprintf (stream, "No info found for user `%s'.\n", entry->pw_name);
    }
  else
    {
      re_extract_fields (info.dptr, fields);
      re_print_fields (fields, stream);
      fprintf ("\n", stream);
    }
  re_free_fields (fields);

  if (packets)
    {
      for (i = 0; packets[i]; i++)
	if (strcmp (entry->pw_name, packets[i]->name) == 0)
	  {
	    print_packet (packets[i], stream);
	    packets_output++;
	  }
    }

#if defined (LASTLOG_FILE)
  /* If the user is not currently logged in, get the last known
     login time. */
  if (packets_output == 0)
    {
      struct lastlog logent;
      int file;

      if ((file = open (LASTLOG_FILE, O_RDONLY)) >= 0)
	{
	  if ((lseek (file, (long) (entry->pw_uid * sizeof (logent)), L_SET) != -1) &&
	      (read (file, &logent, sizeof (logent)) == sizeof (logent)))
	    {
	      fprintf (stream, "Last login on %s ",
		       logent.ll_line[0] ? logent.ll_line : "(no tty)");
	      if (logent.ll_host[0])
		fprintf (stream, "from %s, ", logent.ll_host);
	      fprintf (stream, "on %s", ctime (&(logent.ll_time)));
	    }
	  close (file);
	}
    }
#endif

  /* Check the user's mail file. */
  {
    char *mail_file = path_concat (MAILDIR, entry->pw_name);

    if (stat (mail_file, &finfo) < 0 || finfo.st_size == 0)
      fprintf (stream, "No mail.\n");
    else
      {
	if (finfo.st_atime < finfo.st_mtime)
	  {
	    char *idle_time_string (), *temp_string;
	    
	    fprintf (stream, "New mail since %s", ctime (&finfo.st_mtime));
	    temp_string =
	      idle_time_string ((time_t)time ((time_t *)0) - finfo.st_atime);
	    fprintf (stream, "Has not read mail for %s.\n", temp_string);
	    free (temp_string);
	  }
	else
	  {
	    fprintf (stream, "No unread mail.\n");
	  }
      }
    free (mail_file);
  }

  /* Maybe do the .plan file. */
  {
    char *plan_file = path_concat (entry->pw_dir, ".plan");
    FILE *istream = fopen (plan_file, "r");
    char buff[256];

    if (istream)
      {
	fprintf (stream, "Plan:\n");
	while (istream && fgets (buff, 256, istream))
	  fprintf (stream, "%s", buff);
	fclose (istream);
      }
    else
      fprintf (stream, "No plan.\n");

    free (plan_file);
  }
  fflush (stream);
}
