/* Copyright (c) 1997, 1998, 1999 Thorsten Kukuk
   Author: Thorsten Kukuk <kukuk@suse.de>

   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, 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.  */

#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif

#define _GNU_SOURCE

#include <errno.h>
#include <pwd.h>
#include <nss.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
#include "lib/compat/getopt.h"
#endif
#include <locale.h>
#include <libintl.h>
#include <string.h>
#include <rpcsvc/nis.h>
#include "nispasswd.h"

#ifndef _
#define _(String) gettext (String)
#endif

/* Print the version information.  */
static inline void
print_version (void)
{
  fprintf (stdout, "nispasswd (%s) %s\n", PACKAGE, VERSION);
  fprintf (stdout, gettext ("\
Copyright (C) %s Thorsten Kukuk.\n\
This is free software; see the source for copying conditions.  There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"), "1998");
  /* fprintf (stdout, _("Written by %s.\n"), "Thorsten Kukuk"); */
}

static inline void
print_usage (void)
{
  fputs (_("Usage: nispasswd [-ghs] [-D domainname] [username]\n"), stdout);
  fputs (_("       nispasswd [-D domainname] -a\n"), stdout);
  fputs (_("       nispasswd [-D domainname] [-d [username]]\n"), stdout);
  fputs (_("       nispasswd [-l] [-f] [-n min] [-x max] [-w warn] [-D domainname] user\n"), stdout);
}

static void
print_help (void)
{
  fputs (_("Usage: nispasswd [OPTIONS]\n"), stdout);
  fputs (_("nispasswd - change NIS+ password information\n\n"),
	 stdout);

  fputs (_("  -g             Change the gecos (finger) information\n"),
	 stdout);
  fputs (_("  -h             Change the home directory\n"), stdout);
  fputs (_("  -s             Change the login shell\n"), stdout);
  fputs (_("  -a             Show the password attributes\n"), stdout);
  fputs (_("  -d             Display password attributes\n"), stdout);
  fputs (_("  -l             Locks the password entry for \"user\"\n"),
	 stdout);
  fputs (_("  -f             Force the user to change password at next login\n"), stdout);
  fputs (_("  -n min         Set minimum field for \"user\"\n"), stdout);
  fputs (_("  -x max         Set maximum field for \"user\"\n"), stdout);
  fputs (_("  -w warn        Set warn field for \"user\"\n"), stdout);
  fputs (_("  -D domainname  Use passwd.org_dir from this domain\n"), stdout);
  fputs (_("  --help         Give this help list\n"), stdout);
  fputs (_("  --usage        Give a short usage message\n"), stdout);
  fputs (_("  --version      Print program version\n"), stdout);
}

static inline void
print_error (void)
{
  const char *program = "nispasswd";

  fprintf (stderr,
	   _("Try `%s --help' or `%s --usage' for more information.\n"),
	   program, program);
}

int
main (int argc, char *argv[])
{
  char domain[NIS_MAXNAMELEN + 1];
  int display_all = 0;
  int display_user = 0;
  int expire_now = 0;
  int change_gecos = 0;
  int change_home = 0;
  int change_shell = 0;
  int change_min = 0;
  long new_min_time = -1;
  int change_max = 0;
  long new_max_time = -1;
  int change_warn = 0;
  long new_warn_time = -1;
  int lock_user = 0;
  int result = 0;

  domain[0] = '\0';

  /* Parse program arguments */
  while (1)
    {
      int c;
      int option_index = 0;
      static struct option long_options[] =
      {
	{"version", no_argument, NULL, '\255'},
	{"usage", no_argument, NULL, '\254'},
	{"help", no_argument, NULL, '\253'},
	{NULL, 0, NULL, '\0'}
      };

      c = getopt_long (argc, argv, "adfghln:sw:x:D:", long_options,
		       &option_index);
      if (c == EOF)
	break;
      switch (c)
	{
	case 'a':
	  display_all = 1;
	  break;
	case 'd':
	  display_user = 1;
	  break;
	case 'f':
	  expire_now = 1;
	  break;
	case 'g':
	  change_gecos = 1;
	  break;
	case 'h':
	  change_home = 1;
	  break;
	case 'l':
	  lock_user = 1;
	  break;
	case 'n':
	  change_min = 1;
	  new_min_time = atol (optarg);
	  break;
	case 's':
	  change_shell = 1;
	  break;
	case 'w':
	  change_warn = 1;
	  new_warn_time = atol (optarg);
	  break;
	case 'x':
	  change_max = 1;
	  new_max_time = atol (optarg);
	  break;
	case 'D':
	  strncpy (domain, optarg, NIS_MAXNAMELEN);
	  break;
	case '\253':
	  print_help ();
	  return 0;
	case '\255':
	  print_version ();
	  return 0;
	case '\254':
	  print_usage ();
	  return 0;
	default:
	  print_error ();
	  return 2;
	}
    }

  argc -= optind;
  argv += optind;

  if (argc > 1)
    {
      fprintf (stderr, _("%s: To many arguments\n"), "nispasswd");
      print_error ();
      return 2;
    }

#if 0
  /* Change the nss lookup rules to:
     passwd: nisplus
     shadow: nisplus
     so we could use getpwent()/getspent() */
  if (__nss_configure_lookup ("passwd", "nisplus") != 0)
    fprintf (stderr,
	     _("__nss_configure_lookup (\"passwd\", \"%s\") fails: %s\n"),
	     argv[2], strerror (errno));
  if (__nss_configure_lookup ("shadow", "nisplus") != 0)
    fprintf (stderr,
	     _("__nss_configure_lookup (\"shadow\", \"%s\") fails: %s\n"),
	     argv[2], strerror (errno));
#endif

  if (display_all)
    {
      if (argc > 0 || ((display_user + expire_now + change_gecos +
			change_home + change_min + change_max +
			change_warn + change_shell + lock_user) != 0))
	{
	  print_error ();
	  return 2;
	}
      npd_display (domain, 1, NULL);
      return 0;
    }

  if (display_user)
    {
      if ((display_all + expire_now + change_gecos + change_home + change_min
	   + change_max + change_warn + change_shell + lock_user) != 0)
	{
	  print_error ();
	  return 2;
	}

      if (argc == 1)
	npd_display (domain, 0, argv[0]);
      else
	npd_display (domain, 0, NULL);
      return 0;
    }

  if (lock_user)
    {
      if (argc != 1)
	{
	  fprintf (stderr, _("%s: Wrong number of arguments\n"), "nispasswd");
	  print_error ();
	  return 2;
	}
      else
	result = npd_lock (domain, argv[0]);
    }


  if (expire_now)
    {
      /* XXX User should change the password on the next login */
      fputs ("Expire are not implemented!\n", stderr);
      return 3;
    }

  if (change_min || change_max || change_warn)
    {
      /* XXX shadow administriva */
      fputs ("-n, -w, -x are not implemented!\n", stderr);
      return 3;
    }

  if (!lock_user)
    {
      if (change_home)
	{
	  /* XXX Change home here ! */
	  fputs ("Changing home directory are not implemented!\n", stderr);
	  return 3;
	}
      else
	{
	  if (argc == 1)
	    return npd_upd_pwd (domain, argv[0], change_gecos, change_shell);
	  else
	    return npd_upd_pwd (domain, NULL, change_gecos, change_shell);
	}
    }

  return result;
}
