/* makeusers.c -- Add users to the database file from reading
   the /etc/passwd file. */

/* 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 <config.h>
#include <stdio.h>
#include <ndbm.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/file.h>
#include <general.h>
#include <fingerpaths.h>
#include "recedit.h"

#define MODFIELD "Last Modified by"

main (argc, argv)
     int argc;
     char **argv;
{
  register int i, result;
  struct passwd *entry;
  datum key, info, extract_record (), extract_key ();
  FIELD_DESC *field, **Fields, **fields;
  DBM *database;
  char creation_comment[512], *current_user;

  database = dbm_open (DBMINFO, O_RDWR | O_CREAT, 0666);

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

  Fields = re_read_description_file (FORMATFILE);
  if (!Fields)
    {
      perror (FORMATFILE);
      exit (1);
    }
  
  /* Turn off priveleged fields so that anyone can originally make this
     database. */
  for (i = 0; field = Fields[i]; i++)
    {
      if (field->attributes & FieldPrivileged)
	field->attributes = field->attributes & ~FieldPrivileged;
    }

  sprintf (creation_comment, "User created by %s.", argv[0]);

  /* Get the name of the modifiying user. */
  i = getuid ();
  entry = getpwuid (i);

  if (!entry)
    current_user = savestring ("Unknown User!");
  else
    current_user = savestring (entry->pw_name);

  setpwent ();

  while (entry = getpwent ())
    {
      char *phone;
      DATE birthdate;
      char **gecos_fields ();
      char **gfields;
      int gfields_len;

      gfields = gecos_fields (entry->pw_gecos);
      for (gfields_len = 0; gfields && gfields[gfields_len]; gfields_len++);

      fields = re_copy_fields (Fields);

      if (gfields_len)
	re_set_field (fields, "Real Name", savestring (gfields[0]));

      re_set_field (fields, "Home Disk", savestring (entry->pw_dir));
      re_set_field (fields, "Login Shell", savestring (entry->pw_shell));
      re_set_field (fields, "User ID", entry->pw_uid);

      {
	struct group *grentry;

	grentry = getgrgid (entry->pw_gid);
	if (grentry)
	  re_set_field (fields, "Group", savestring (grentry->gr_name));
	else
	  re_set_field (fields, "Group", savestring ("Other"));
      }

      re_set_field (fields, "User Name", savestring (entry->pw_name));
      re_set_field (fields, "Comment", savestring (creation_comment));

      {
	char phone_hack[10];

	sprintf (phone_hack, "%d", entry->pw_uid);
	re_set_field (fields, "Phone", savestring (phone_hack));
      }

      birthdate.month = 1;
      birthdate.day = 1;
      birthdate.year = 1;
      set_birthdate_field (fields, &birthdate);

      free (gfields);

      /* Maybe we can default the email field. */
      {
	char hostname[256];

	if (gethostname (hostname, 256) != -1)
	  {
	    char *email = (char *)xmalloc
	      (3 + strlen (entry->pw_name) + strlen (hostname));
	    sprintf (email, "%s@%s", entry->pw_name, hostname);
	    re_set_field (fields, "E-Mail Address", email);
	  }
	else
	  re_set_field (fields, "E-Mail Address", savestring (entry->pw_name));
      }

      {
	FIELD_DESC *field;

	field = re_find_field (fields, MODFIELD);

	if (field)
	  {
	    char *time_string, *ctime (), mod_value[256];
	    long the_time, time ();

	    the_time = time ((long *)0);
	    time_string = ctime (&the_time);
	    time_string[strlen (time_string) - 1] = '\0';
	    
	    field->attributes = field->attributes & ~FieldPrivileged;
	    sprintf (mod_value, "%s on %s", current_user, time_string);
	    re_set_field (fields, MODFIELD, savestring (mod_value));
	  }
      }


      /* Put the new info in the database. */
      info = extract_record (fields);
      key = extract_key (fields);

      result = dbm_store (database, key, info, DBM_INSERT);
      if (result == 0)
	printf ("Added user %s...\n", entry->pw_name);

      re_free_fields (fields);
      free (info.dptr);
      free (key.dptr);
    }
  endpwent ();
  dbm_close (database);
}

/* Return a NULL terminated array of pointers to static strings.
   Each element in the returned array corresponds to a separate
   field in STRING.  STRING should be a pw->pw_gecos. */
char **
gecos_fields (string)
     char *string;
{
  register int i, count = 0;
  char *rindex (), *separators = ";,";
  char **array = (char **)NULL;
  int start, array_size = 0;
  
  start = 0;

  while (string[start])
    {
      for (i = start; string[i] && !rindex (separators, string[i]); i++);

      if (i != start)
	{
	  if (count + 1 >= array_size)
	    array = (char **)
	      xrealloc (array, (array_size += 10) * sizeof (char *));

	  array[count] = (char *)xmalloc (1 + (i - start));
	  strncpy (array[count], string + start, i - start);
	  array[count][i - start] = '\0';
	  count++;
	}

      start = i;
      if (string[i])
	start++;
    }
  return (array);
}

datum
extract_key (fields)
     FIELD_DESC **fields;
{
  datum key;

  key.dsize = re_data_length (fields, FieldKey);
  key.dptr = re_extract_data (fields, FieldKey);

  return (key);
}

datum
extract_record (fields)
     FIELD_DESC **fields;
{
  datum info;

  info.dsize = re_data_length (fields, 0);
  info.dptr = re_extract_data (fields, 0);

  return (info);
}
