Blame nss/getent.c

Packit 6c4009
/* Copyright (c) 1998-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* getent: get entries from administrative database.  */
Packit 6c4009
Packit 6c4009
#include <aliases.h>
Packit 6c4009
#include <argp.h>
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <error.h>
Packit 6c4009
#include <grp.h>
Packit 6c4009
#include <gshadow.h>
Packit 6c4009
#include <libintl.h>
Packit 6c4009
#include <locale.h>
Packit 6c4009
#include <mcheck.h>
Packit 6c4009
#include <netdb.h>
Packit 6c4009
#include <pwd.h>
Packit 6c4009
#include <shadow.h>
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <arpa/inet.h>
Packit 6c4009
#include <arpa/nameser.h>
Packit 6c4009
#include <netinet/ether.h>
Packit 6c4009
#include <netinet/in.h>
Packit 6c4009
#include <sys/socket.h>
Packit 6c4009
#include <scratch_buffer.h>
Packit 6c4009
Packit 6c4009
/* Get libc version number.  */
Packit 6c4009
#include <version.h>
Packit 6c4009
Packit 6c4009
#define PACKAGE _libc_intl_domainname
Packit 6c4009
Packit 6c4009
/* Name and version of program.  */
Packit 6c4009
static void print_version (FILE *stream, struct argp_state *state);
Packit 6c4009
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
Packit 6c4009
Packit 6c4009
/* Short description of parameters.  */
Packit 6c4009
static const char args_doc[] = N_("database [key ...]");
Packit 6c4009
Packit 6c4009
/* Supported options. */
Packit 6c4009
static const struct argp_option args_options[] =
Packit 6c4009
  {
Packit 6c4009
    { "service", 's', N_("CONFIG"), 0, N_("Service configuration to be used") },
Packit 6c4009
    { "no-idn", 'i', NULL, 0, N_("disable IDN encoding") },
Packit 6c4009
    { NULL, 0, NULL, 0, NULL },
Packit 6c4009
  };
Packit 6c4009
Packit 6c4009
/* Short description of program.  */
Packit 6c4009
static const char doc[] = N_("Get entries from administrative database.");
Packit 6c4009
Packit 6c4009
/* Prototype for option handler.  */
Packit 6c4009
static error_t parse_option (int key, char *arg, struct argp_state *state);
Packit 6c4009
Packit 6c4009
/* Function to print some extra text in the help message.  */
Packit 6c4009
static char *more_help (int key, const char *text, void *input);
Packit 6c4009
Packit 6c4009
/* Data structure to communicate with argp functions.  */
Packit 6c4009
static struct argp argp =
Packit 6c4009
  {
Packit 6c4009
    args_options, parse_option, args_doc, doc, NULL, more_help
Packit 6c4009
  };
Packit 6c4009
Packit 6c4009
/* Additional getaddrinfo flags for IDN encoding.  */
Packit 6c4009
static int idn_flags = AI_IDN | AI_CANONIDN;
Packit 6c4009
Packit 6c4009
/* Print the version information.  */
Packit 6c4009
static void
Packit 6c4009
print_version (FILE *stream, struct argp_state *state)
Packit 6c4009
{
Packit 6c4009
  fprintf (stream, "getent %s%s\n", PKGVERSION, VERSION);
Packit 6c4009
  fprintf (stream, gettext ("\
Packit 6c4009
Copyright (C) %s Free Software Foundation, Inc.\n\
Packit 6c4009
This is free software; see the source for copying conditions.  There is NO\n\
Packit 6c4009
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Packit 6c4009
"), "2018");
Packit 6c4009
  fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for aliases */
Packit 6c4009
static void
Packit 6c4009
print_aliases (struct aliasent *alias)
Packit 6c4009
{
Packit 6c4009
  unsigned int i = 0;
Packit 6c4009
Packit 6c4009
  printf ("%s: ", alias->alias_name);
Packit 6c4009
  for  (i = strlen (alias->alias_name); i < 14; ++i)
Packit 6c4009
    fputs_unlocked (" ", stdout);
Packit 6c4009
Packit 6c4009
  for (i = 0; i < alias->alias_members_len; ++i)
Packit 6c4009
    printf ("%s%s",
Packit 6c4009
	    alias->alias_members [i],
Packit 6c4009
	    i + 1 == alias->alias_members_len ? "\n" : ", ");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
aliases_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct aliasent *alias;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      setaliasent ();
Packit 6c4009
      while ((alias = getaliasent ()) != NULL)
Packit 6c4009
	print_aliases (alias);
Packit 6c4009
      endaliasent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      alias = getaliasbyname (key[i]);
Packit 6c4009
Packit 6c4009
      if (alias == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_aliases (alias);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for ethers */
Packit 6c4009
static int
Packit 6c4009
ethers_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      fprintf (stderr, _("Enumeration not supported on %s\n"), "ethers");
Packit 6c4009
      return 3;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      struct ether_addr *ethp, eth;
Packit 6c4009
      char buffer [1024], *p;
Packit 6c4009
Packit 6c4009
      ethp = ether_aton (key[i]);
Packit 6c4009
      if (ethp != NULL)
Packit 6c4009
	{
Packit 6c4009
	  if (ether_ntohost (buffer, ethp))
Packit 6c4009
	    {
Packit 6c4009
	      result = 2;
Packit 6c4009
	      continue;
Packit 6c4009
	    }
Packit 6c4009
	  p = buffer;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  if (ether_hostton (key[i], &eth))
Packit 6c4009
	    {
Packit 6c4009
	      result = 2;
Packit 6c4009
	      continue;
Packit 6c4009
	    }
Packit 6c4009
	  p = key[i];
Packit 6c4009
	  ethp = ð
Packit 6c4009
	}
Packit 6c4009
      printf ("%s %s\n", ether_ntoa (ethp), p);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for group */
Packit 6c4009
static void
Packit 6c4009
print_group (struct group *grp)
Packit 6c4009
{
Packit 6c4009
  if (putgrent (grp, stdout) != 0)
Packit 6c4009
    fprintf (stderr, "error writing group entry: %m\n");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
group_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct group *grp;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      setgrent ();
Packit 6c4009
      while ((grp = getgrent ()) != NULL)
Packit 6c4009
	print_group (grp);
Packit 6c4009
      endgrent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      errno = 0;
Packit 6c4009
      char *ep;
Packit 6c4009
      gid_t arg_gid = strtoul(key[i], &ep, 10);
Packit 6c4009
Packit 6c4009
      if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
Packit 6c4009
	/* Valid numeric gid.  */
Packit 6c4009
	grp = getgrgid (arg_gid);
Packit 6c4009
      else
Packit 6c4009
	grp = getgrnam (key[i]);
Packit 6c4009
Packit 6c4009
      if (grp == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_group (grp);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for gshadow */
Packit 6c4009
static void
Packit 6c4009
print_gshadow (struct sgrp *sg)
Packit 6c4009
{
Packit 6c4009
  if (putsgent (sg, stdout) != 0)
Packit 6c4009
    fprintf (stderr, "error writing gshadow entry: %m\n");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
gshadow_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      struct sgrp *sg;
Packit 6c4009
Packit 6c4009
      setsgent ();
Packit 6c4009
      while ((sg = getsgent ()) != NULL)
Packit 6c4009
	print_gshadow (sg);
Packit 6c4009
      endsgent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      struct sgrp *sg;
Packit 6c4009
Packit 6c4009
      sg = getsgnam (key[i]);
Packit 6c4009
Packit 6c4009
      if (sg == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_gshadow (sg);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for hosts */
Packit 6c4009
static void
Packit 6c4009
print_hosts (struct hostent *host)
Packit 6c4009
{
Packit 6c4009
  unsigned int cnt;
Packit 6c4009
Packit 6c4009
  for (cnt = 0; host->h_addr_list[cnt] != NULL; ++cnt)
Packit 6c4009
    {
Packit 6c4009
      char buf[INET6_ADDRSTRLEN];
Packit 6c4009
      const char *ip = inet_ntop (host->h_addrtype, host->h_addr_list[cnt],
Packit 6c4009
				  buf, sizeof (buf));
Packit 6c4009
Packit 6c4009
      printf ("%-15s %s", ip, host->h_name);
Packit 6c4009
Packit 6c4009
      unsigned int i;
Packit 6c4009
      for (i = 0; host->h_aliases[i] != NULL; ++i)
Packit 6c4009
	{
Packit 6c4009
	  putchar_unlocked (' ');
Packit 6c4009
	  fputs_unlocked (host->h_aliases[i], stdout);
Packit 6c4009
	}
Packit 6c4009
      putchar_unlocked ('\n');
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
hosts_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct hostent *host;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      sethostent (0);
Packit 6c4009
      while ((host = gethostent ()) != NULL)
Packit 6c4009
	print_hosts (host);
Packit 6c4009
      endhostent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      struct hostent *host = NULL;
Packit 6c4009
      char addr[IN6ADDRSZ];
Packit 6c4009
Packit 6c4009
      if (inet_pton (AF_INET6, key[i], &addr) > 0)
Packit 6c4009
	host = gethostbyaddr (addr, IN6ADDRSZ, AF_INET6);
Packit 6c4009
      else if (inet_pton (AF_INET, key[i], &addr) > 0)
Packit 6c4009
	host = gethostbyaddr (addr, INADDRSZ, AF_INET);
Packit 6c4009
      else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
Packit 6c4009
	host = gethostbyname2 (key[i], AF_INET);
Packit 6c4009
Packit 6c4009
      if (host == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_hosts (host);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for hosts, but using getaddrinfo */
Packit 6c4009
static int
Packit 6c4009
ahosts_keys_int (int af, int xflags, int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct hostent *host;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      sethostent (0);
Packit 6c4009
      while ((host = gethostent ()) != NULL)
Packit 6c4009
	print_hosts (host);
Packit 6c4009
      endhostent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  struct addrinfo hint;
Packit 6c4009
  memset (&hint, '\0', sizeof (hint));
Packit 6c4009
  hint.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME
Packit 6c4009
		   | idn_flags | xflags);
Packit 6c4009
  hint.ai_family = af;
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      struct addrinfo *res;
Packit 6c4009
Packit 6c4009
      if (getaddrinfo (key[i], NULL, &hint, &res) != 0)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  struct addrinfo *runp = res;
Packit 6c4009
Packit 6c4009
	  while (runp != NULL)
Packit 6c4009
	    {
Packit 6c4009
	      char sockbuf[20];
Packit 6c4009
	      const char *sockstr;
Packit 6c4009
	      if (runp->ai_socktype == SOCK_STREAM)
Packit 6c4009
		sockstr = "STREAM";
Packit 6c4009
	      else if (runp->ai_socktype == SOCK_DGRAM)
Packit 6c4009
		sockstr = "DGRAM";
Packit 6c4009
	      else if (runp->ai_socktype == SOCK_RAW)
Packit 6c4009
		sockstr = "RAW";
Packit 6c4009
#ifdef SOCK_SEQPACKET
Packit 6c4009
	      else if (runp->ai_socktype == SOCK_SEQPACKET)
Packit 6c4009
		sockstr = "SEQPACKET";
Packit 6c4009
#endif
Packit 6c4009
#ifdef SOCK_RDM
Packit 6c4009
	      else if (runp->ai_socktype == SOCK_RDM)
Packit 6c4009
		sockstr = "RDM";
Packit 6c4009
#endif
Packit 6c4009
#ifdef SOCK_DCCP
Packit 6c4009
	      else if (runp->ai_socktype == SOCK_DCCP)
Packit 6c4009
		sockstr = "DCCP";
Packit 6c4009
#endif
Packit 6c4009
#ifdef SOCK_PACKET
Packit 6c4009
	      else if (runp->ai_socktype == SOCK_PACKET)
Packit 6c4009
		sockstr = "PACKET";
Packit 6c4009
#endif
Packit 6c4009
	      else
Packit 6c4009
		{
Packit 6c4009
		  snprintf (sockbuf, sizeof (sockbuf), "%d",
Packit 6c4009
			    runp->ai_socktype);
Packit 6c4009
		  sockstr = sockbuf;
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      char buf[INET6_ADDRSTRLEN];
Packit 6c4009
	      printf ("%-15s %-6s %s\n",
Packit 6c4009
		      inet_ntop (runp->ai_family,
Packit 6c4009
				 runp->ai_family == AF_INET
Packit 6c4009
				 ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
Packit 6c4009
				 : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
Packit 6c4009
				 buf, sizeof (buf)),
Packit 6c4009
		      sockstr,
Packit 6c4009
		      runp->ai_canonname ?: "");
Packit 6c4009
Packit 6c4009
	      runp = runp->ai_next;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  freeaddrinfo (res);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
ahosts_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  return ahosts_keys_int (AF_UNSPEC, 0, number, key);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
ahostsv4_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  return ahosts_keys_int (AF_INET, 0, number, key);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
ahostsv6_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  return ahosts_keys_int (AF_INET6, AI_V4MAPPED, number, key);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for netgroup */
Packit 6c4009
static int
Packit 6c4009
netgroup_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      fprintf (stderr, _("Enumeration not supported on %s\n"), "netgroup");
Packit 6c4009
      return 3;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (number == 4)
Packit 6c4009
    {
Packit 6c4009
      char *host = strcmp (key[1], "*") == 0 ? NULL : key[1];
Packit 6c4009
      char *user = strcmp (key[2], "*") == 0 ? NULL : key[2];
Packit 6c4009
      char *domain = strcmp (key[3], "*") == 0 ? NULL : key[3];
Packit 6c4009
Packit 6c4009
      printf ("%-21s (%s,%s,%s) = %d\n",
Packit 6c4009
	      key[0], host ?: "", user ?: "", domain ?: "",
Packit 6c4009
	      innetgr (key[0], host, user, domain));
Packit 6c4009
    }
Packit 6c4009
  else if (number == 1)
Packit 6c4009
    {
Packit 6c4009
      if (!setnetgrent (key[0]))
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  char *p[3];
Packit 6c4009
Packit 6c4009
	  printf ("%-21s", key[0]);
Packit 6c4009
Packit 6c4009
	  while (getnetgrent (p, p + 1, p + 2))
Packit 6c4009
	    printf (" (%s,%s,%s)", p[0] ?: " ", p[1] ?: "", p[2] ?: "");
Packit 6c4009
	  putchar_unlocked ('\n');
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  endnetgrent ();
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define DYNARRAY_STRUCT gid_list
Packit 6c4009
#define DYNARRAY_ELEMENT gid_t
Packit 6c4009
#define DYNARRAY_PREFIX gid_list_
Packit 6c4009
#define DYNARRAY_INITIAL_SIZE 10
Packit 6c4009
#include <malloc/dynarray-skeleton.c>
Packit 6c4009
Packit 6c4009
/* This is for initgroups */
Packit 6c4009
static int
Packit 6c4009
initgroups_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      fprintf (stderr, _("Enumeration not supported on %s\n"), "initgroups");
Packit 6c4009
      return 3;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  struct gid_list list;
Packit 6c4009
  gid_list_init (&list);
Packit 6c4009
  if (!gid_list_resize (&list, 10))
Packit 6c4009
    {
Packit 6c4009
      fprintf (stderr, _("Could not allocate group list: %m\n"));
Packit 6c4009
      return 3;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (int i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      int no = gid_list_size (&list);
Packit 6c4009
      int n;
Packit 6c4009
      while ((n = getgrouplist (key[i], -1, gid_list_begin (&list), &no)) == -1
Packit 6c4009
	     && no > gid_list_size (&list))
Packit 6c4009
	{
Packit 6c4009
	  if (!gid_list_resize (&list, no))
Packit 6c4009
	    {
Packit 6c4009
	      fprintf (stderr, _("Could not allocate group list: %m\n"));
Packit 6c4009
	      return 3;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (n == -1)
Packit 6c4009
	{
Packit 6c4009
	  gid_list_free (&list);
Packit 6c4009
	  return 1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      const gid_t *grps = gid_list_begin (&list);
Packit 6c4009
      printf ("%-21s", key[i]);
Packit 6c4009
      for (int j = 0; j < n; ++j)
Packit 6c4009
	if (grps[j] != -1)
Packit 6c4009
	  printf (" %ld", (long int) grps[j]);
Packit 6c4009
      putchar_unlocked ('\n');
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  gid_list_free (&list);
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for networks */
Packit 6c4009
static void
Packit 6c4009
print_networks (struct netent *net)
Packit 6c4009
{
Packit 6c4009
  unsigned int i;
Packit 6c4009
  struct in_addr ip;
Packit 6c4009
  ip.s_addr = htonl (net->n_net);
Packit 6c4009
Packit 6c4009
  printf ("%-21s %s", net->n_name, inet_ntoa (ip));
Packit 6c4009
Packit 6c4009
  i = 0;
Packit 6c4009
  while (net->n_aliases[i] != NULL)
Packit 6c4009
    {
Packit 6c4009
      putchar_unlocked (' ');
Packit 6c4009
      fputs_unlocked (net->n_aliases[i], stdout);
Packit 6c4009
      ++i;
Packit 6c4009
    }
Packit 6c4009
  putchar_unlocked ('\n');
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
networks_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct netent *net;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      setnetent (0);
Packit 6c4009
      while ((net = getnetent ()) != NULL)
Packit 6c4009
	print_networks (net);
Packit 6c4009
      endnetent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      if (isdigit (key[i][0]))
Packit 6c4009
	net = getnetbyaddr (ntohl (inet_addr (key[i])), AF_UNSPEC);
Packit 6c4009
      else
Packit 6c4009
	net = getnetbyname (key[i]);
Packit 6c4009
Packit 6c4009
      if (net == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_networks (net);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Now is all for passwd */
Packit 6c4009
static void
Packit 6c4009
print_passwd (struct passwd *pwd)
Packit 6c4009
{
Packit 6c4009
  if (putpwent (pwd, stdout) != 0)
Packit 6c4009
    fprintf (stderr, "error writing passwd entry: %m\n");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
passwd_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct passwd *pwd;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      setpwent ();
Packit 6c4009
      while ((pwd = getpwent ()) != NULL)
Packit 6c4009
	print_passwd (pwd);
Packit 6c4009
      endpwent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      errno = 0;
Packit 6c4009
      char *ep;
Packit 6c4009
      uid_t arg_uid = strtoul(key[i], &ep, 10);
Packit 6c4009
Packit 6c4009
      if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
Packit 6c4009
	/* Valid numeric uid.  */
Packit 6c4009
	pwd = getpwuid (arg_uid);
Packit 6c4009
      else
Packit 6c4009
	pwd = getpwnam (key[i]);
Packit 6c4009
Packit 6c4009
      if (pwd == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_passwd (pwd);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for protocols */
Packit 6c4009
static void
Packit 6c4009
print_protocols (struct protoent *proto)
Packit 6c4009
{
Packit 6c4009
  unsigned int i;
Packit 6c4009
Packit 6c4009
  printf ("%-21s %d", proto->p_name, proto->p_proto);
Packit 6c4009
Packit 6c4009
  i = 0;
Packit 6c4009
  while (proto->p_aliases[i] != NULL)
Packit 6c4009
    {
Packit 6c4009
      putchar_unlocked (' ');
Packit 6c4009
      fputs_unlocked (proto->p_aliases[i], stdout);
Packit 6c4009
      ++i;
Packit 6c4009
    }
Packit 6c4009
  putchar_unlocked ('\n');
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
protocols_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct protoent *proto;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      setprotoent (0);
Packit 6c4009
      while ((proto = getprotoent ()) != NULL)
Packit 6c4009
	print_protocols (proto);
Packit 6c4009
      endprotoent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      if (isdigit (key[i][0]))
Packit 6c4009
	proto = getprotobynumber (atol (key[i]));
Packit 6c4009
      else
Packit 6c4009
	proto = getprotobyname (key[i]);
Packit 6c4009
Packit 6c4009
      if (proto == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_protocols (proto);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#if HAVE_SUNRPC
Packit 6c4009
/* Now is all for rpc */
Packit 6c4009
static void
Packit 6c4009
print_rpc (struct rpcent *rpc)
Packit 6c4009
{
Packit 6c4009
  int i;
Packit 6c4009
Packit 6c4009
  printf ("%-15s %d%s",
Packit 6c4009
	  rpc->r_name, rpc->r_number, rpc->r_aliases[0] ? " " : "");
Packit 6c4009
Packit 6c4009
  for (i = 0; rpc->r_aliases[i]; ++i)
Packit 6c4009
    printf (" %s", rpc->r_aliases[i]);
Packit 6c4009
  putchar_unlocked ('\n');
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
rpc_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct rpcent *rpc;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      setrpcent (0);
Packit 6c4009
      while ((rpc = getrpcent ()) != NULL)
Packit 6c4009
	print_rpc (rpc);
Packit 6c4009
      endrpcent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      if (isdigit (key[i][0]))
Packit 6c4009
	rpc = getrpcbynumber (atol (key[i]));
Packit 6c4009
      else
Packit 6c4009
	rpc = getrpcbyname (key[i]);
Packit 6c4009
Packit 6c4009
      if (rpc == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_rpc (rpc);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* for services */
Packit 6c4009
static void
Packit 6c4009
print_services (struct servent *serv)
Packit 6c4009
{
Packit 6c4009
  unsigned int i;
Packit 6c4009
Packit 6c4009
  printf ("%-21s %d/%s", serv->s_name, ntohs (serv->s_port), serv->s_proto);
Packit 6c4009
Packit 6c4009
  i = 0;
Packit 6c4009
  while (serv->s_aliases[i] != NULL)
Packit 6c4009
    {
Packit 6c4009
      putchar_unlocked (' ');
Packit 6c4009
      fputs_unlocked (serv->s_aliases[i], stdout);
Packit 6c4009
      ++i;
Packit 6c4009
    }
Packit 6c4009
  putchar_unlocked ('\n');
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
services_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
  struct servent *serv;
Packit 6c4009
Packit 6c4009
  if (!number)
Packit 6c4009
    {
Packit 6c4009
      setservent (0);
Packit 6c4009
      while ((serv = getservent ()) != NULL)
Packit 6c4009
	print_services (serv);
Packit 6c4009
      endservent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      struct servent *serv;
Packit 6c4009
      char *proto = strchr (key[i], '/');
Packit 6c4009
Packit 6c4009
      if (proto != NULL)
Packit 6c4009
	*proto++ = '\0';
Packit 6c4009
Packit 6c4009
      char *endptr;
Packit 6c4009
      long port = strtol (key[i], &endptr, 10);
Packit 6c4009
Packit 6c4009
      if (isdigit (key[i][0]) && *endptr == '\0'
Packit 6c4009
	  && 0 <= port && port <= 65535)
Packit 6c4009
	serv = getservbyport (htons (port), proto);
Packit 6c4009
      else
Packit 6c4009
	serv = getservbyname (key[i], proto);
Packit 6c4009
Packit 6c4009
      if (serv == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_services (serv);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is for shadow */
Packit 6c4009
static void
Packit 6c4009
print_shadow (struct spwd *sp)
Packit 6c4009
{
Packit 6c4009
  if (putspent (sp, stdout) != 0)
Packit 6c4009
    fprintf (stderr, "error writing shadow entry: %m\n");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
shadow_keys (int number, char *key[])
Packit 6c4009
{
Packit 6c4009
  int result = 0;
Packit 6c4009
  int i;
Packit 6c4009
Packit 6c4009
  if (number == 0)
Packit 6c4009
    {
Packit 6c4009
      struct spwd *sp;
Packit 6c4009
Packit 6c4009
      setspent ();
Packit 6c4009
      while ((sp = getspent ()) != NULL)
Packit 6c4009
	print_shadow (sp);
Packit 6c4009
      endspent ();
Packit 6c4009
      return result;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < number; ++i)
Packit 6c4009
    {
Packit 6c4009
      struct spwd *sp;
Packit 6c4009
Packit 6c4009
      sp = getspnam (key[i]);
Packit 6c4009
Packit 6c4009
      if (sp == NULL)
Packit 6c4009
	result = 2;
Packit 6c4009
      else
Packit 6c4009
	print_shadow (sp);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
struct
Packit 6c4009
  {
Packit 6c4009
    const char *name;
Packit 6c4009
    int (*func) (int number, char *key[]);
Packit 6c4009
  } databases[] =
Packit 6c4009
  {
Packit 6c4009
#define D(name) { #name, name ## _keys },
Packit 6c4009
D(ahosts)
Packit 6c4009
D(ahostsv4)
Packit 6c4009
D(ahostsv6)
Packit 6c4009
D(aliases)
Packit 6c4009
D(ethers)
Packit 6c4009
D(group)
Packit 6c4009
D(gshadow)
Packit 6c4009
D(hosts)
Packit 6c4009
D(initgroups)
Packit 6c4009
D(netgroup)
Packit 6c4009
D(networks)
Packit 6c4009
D(passwd)
Packit 6c4009
D(protocols)
Packit 6c4009
#if HAVE_SUNRPC
Packit 6c4009
D(rpc)
Packit 6c4009
#endif
Packit 6c4009
D(services)
Packit 6c4009
D(shadow)
Packit 6c4009
#undef D
Packit 6c4009
    { NULL, NULL }
Packit 6c4009
  };
Packit 6c4009
Packit 6c4009
/* Handle arguments found by argp. */
Packit 6c4009
static error_t
Packit 6c4009
parse_option (int key, char *arg, struct argp_state *state)
Packit 6c4009
{
Packit 6c4009
  char *endp;
Packit 6c4009
  switch (key)
Packit 6c4009
    {
Packit 6c4009
    case 's':
Packit 6c4009
      endp = strchr (arg, ':');
Packit 6c4009
      if (endp == NULL)
Packit 6c4009
	/* No specific database, change them all.  */
Packit 6c4009
	for (int i = 0; databases[i].name != NULL; ++i)
Packit 6c4009
	  __nss_configure_lookup (databases[i].name, arg);
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  int i;
Packit 6c4009
	  for (i = 0; databases[i].name != NULL; ++i)
Packit 6c4009
	    if (strncmp (databases[i].name, arg, endp - arg) == 0)
Packit 6c4009
	      {
Packit 6c4009
		__nss_configure_lookup (databases[i].name, endp + 1);
Packit 6c4009
		break;
Packit 6c4009
	      }
Packit 6c4009
	  if (databases[i].name == NULL)
Packit 6c4009
	    error (EXIT_FAILURE, 0, gettext ("Unknown database name"));
Packit 6c4009
	}
Packit 6c4009
      break;
Packit 6c4009
Packit 6c4009
    case 'i':
Packit 6c4009
      idn_flags = 0;
Packit 6c4009
      break;
Packit 6c4009
Packit 6c4009
    default:
Packit 6c4009
      return ARGP_ERR_UNKNOWN;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static char *
Packit 6c4009
more_help (int key, const char *text, void *input)
Packit 6c4009
{
Packit 6c4009
  switch (key)
Packit 6c4009
    {
Packit 6c4009
      size_t len;
Packit 6c4009
      char *doc;
Packit 6c4009
      FILE *fp;
Packit 6c4009
Packit 6c4009
    case ARGP_KEY_HELP_EXTRA:
Packit 6c4009
      /* We print some extra information.  */
Packit 6c4009
      fp = open_memstream (&doc, &len;;
Packit 6c4009
      if (fp != NULL)
Packit 6c4009
	{
Packit 6c4009
	  fputs_unlocked (_("Supported databases:\n"), fp);
Packit 6c4009
Packit 6c4009
	  for (int i = 0, col = 0; databases[i].name != NULL; ++i)
Packit 6c4009
	    {
Packit 6c4009
	      len = strlen (databases[i].name);
Packit 6c4009
	      if (i != 0)
Packit 6c4009
		{
Packit 6c4009
		  if (col + len > 72)
Packit 6c4009
		    {
Packit 6c4009
		      col = 0;
Packit 6c4009
		      fputc_unlocked ('\n', fp);
Packit 6c4009
		    }
Packit 6c4009
		  else
Packit 6c4009
		    fputc_unlocked (' ', fp);
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      fputs_unlocked (databases[i].name, fp);
Packit 6c4009
	      col += len + 1;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  fputs ("\n\n", fp);
Packit 6c4009
Packit 6c4009
	  fprintf (fp, gettext ("\
Packit 6c4009
For bug reporting instructions, please see:\n\
Packit 6c4009
%s.\n"), REPORT_BUGS_TO);
Packit 6c4009
Packit 6c4009
	  if (fclose (fp) == 0)
Packit 6c4009
	    return doc;
Packit 6c4009
	}
Packit 6c4009
      break;
Packit 6c4009
Packit 6c4009
    default:
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
  return (char *) text;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* the main function */
Packit 6c4009
int
Packit 6c4009
main (int argc, char *argv[])
Packit 6c4009
{
Packit 6c4009
  /* Debugging support.  */
Packit 6c4009
  mtrace ();
Packit 6c4009
Packit 6c4009
  /* Set locale via LC_ALL.  */
Packit 6c4009
  setlocale (LC_ALL, "");
Packit 6c4009
  /* Set the text message domain.  */
Packit 6c4009
  textdomain (PACKAGE);
Packit 6c4009
Packit 6c4009
  /* Parse and process arguments.  */
Packit 6c4009
  int remaining;
Packit 6c4009
  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit 6c4009
Packit 6c4009
  if ((argc - remaining) < 1)
Packit 6c4009
    {
Packit 6c4009
      error (0, 0, gettext ("wrong number of arguments"));
Packit 6c4009
      argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (int i = 0; databases[i].name; ++i)
Packit 6c4009
    if (argv[remaining][0] == databases[i].name[0]
Packit 6c4009
	&& !strcmp (argv[remaining], databases[i].name))
Packit 6c4009
      return databases[i].func (argc - remaining - 1, &argv[remaining + 1]);
Packit 6c4009
Packit 6c4009
  fprintf (stderr, _("Unknown database: %s\n"), argv[remaining]);
Packit 6c4009
  argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
Packit 6c4009
  return 1;
Packit 6c4009
}