/* mkpasswd.c -- Make a password file from the info in DBMINFO. */

/* 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 <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <ndbm.h>
#include <fingerpaths.h>
#include "recedit.h"

/* Name of this program. */
char *progname;

FIELD_DESC **Fields;

main (argc, argv)
     int argc;
     char **argv;
{
  DBM *database;
  FIELD_DESC *field;

  database = dbm_open (DBMINFO, O_RDONLY, 0666);

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

  Fields = re_read_description_file (FORMATFILE);

  if (!Fields)
    {
      fprintf (stderr, "%s: Cannot read description file %s.\n",
	       progname, FORMATFILE);
      exit (1);
    }

  make_password_file (database, stdout);

  dbm_close (database);
}

/* Let's sort these fields by user number. */
make_password_file (database, stream)
     DBM *database;
     FILE *stream;
{
  register int i;
  FIELD_DESC **fields;
  int uid_compare ();
  FIELD_DESC ***records;
  int records_index, records_size;
  datum info, key;
  int uid, gid;
  char *user, *real_name, *home_dir, *login_shell;

  records_index = records_size = 0;

  /* Build the list of records. */
  for (key = dbm_firstkey (database); key.dptr != NULL;
       key = dbm_nextkey (database))
    {
      info = dbm_fetch (database, key);

      if (!info.dptr)
	continue;

      fields = re_copy_fields (Fields);
      re_extract_fields (info.dptr, fields);

      if (records_index >= records_size)
	{
	  if (!records)
	    records = (FIELD_DESC ***)
	      xmalloc ((records_size = 100) * sizeof (FIELD_DESC **));
	  else
	    records = (FIELD_DESC ***)
	      xrealloc (records, (records_size += 100) * sizeof (FIELD_DESC **));
	}
      records[records_index] = fields;
      records_index++;
      records[records_index] = (FIELD_DESC **)NULL;
    }

  /* Sort these records. */
  qsort (records, records_index, sizeof (FIELD_DESC **), uid_compare);

  /* Now print them out, one by one. */
  for (i = 0; fields = records[i]; i++)
    {
      user = *(char **)re_get_field_value (fields, "User Name");
      real_name = *(char **)re_get_field_value (fields, "Real Name");
      home_dir = *(char **)re_get_field_value (fields, "Home Dir");
      login_shell = *(char **)re_get_field_value (fields, "Login Shell");
      uid = *(int *)re_get_field_value (fields, "User ID");
      gid = *(int *)re_get_field_value (fields, "Group ID");

      fprintf (stream, "%s::%d:%d:%s:%s:%s\n",
	       user, uid, gid, real_name, home_dir, login_shell);
      fflush (stream);
      re_free_fields (fields);
    }
  free (records);
}

int
uid_compare (fields1, fields2)
     FIELD_DESC ***fields1, ***fields2;
{
  int uid1, uid2;

  uid1 = *(int *)re_get_field_value (*fields1, "User ID");
  uid2 = *(int *)re_get_field_value (*fields2, "User ID");

  return (uid1 > uid2);
}
