Home | History | Annotate | Line # | Download | only in getent
getent.c revision 1.16
      1  1.16     lukem /*	$NetBSD: getent.c,v 1.16 2009/04/12 10:27:08 lukem Exp $	*/
      2   1.1     lukem 
      3   1.1     lukem /*-
      4   1.8     lukem  * Copyright (c) 2004-2006 The NetBSD Foundation, Inc.
      5   1.1     lukem  * All rights reserved.
      6   1.1     lukem  *
      7   1.1     lukem  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1     lukem  * by Luke Mewburn.
      9   1.1     lukem  *
     10   1.1     lukem  * Redistribution and use in source and binary forms, with or without
     11   1.1     lukem  * modification, are permitted provided that the following conditions
     12   1.1     lukem  * are met:
     13   1.1     lukem  * 1. Redistributions of source code must retain the above copyright
     14   1.1     lukem  *    notice, this list of conditions and the following disclaimer.
     15   1.1     lukem  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1     lukem  *    notice, this list of conditions and the following disclaimer in the
     17   1.1     lukem  *    documentation and/or other materials provided with the distribution.
     18   1.1     lukem  *
     19   1.1     lukem  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1     lukem  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1     lukem  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1     lukem  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1     lukem  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1     lukem  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1     lukem  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1     lukem  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1     lukem  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1     lukem  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1     lukem  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1     lukem  */
     31   1.1     lukem 
     32   1.1     lukem #include <sys/cdefs.h>
     33   1.1     lukem #ifndef lint
     34  1.16     lukem __RCSID("$NetBSD: getent.c,v 1.16 2009/04/12 10:27:08 lukem Exp $");
     35   1.1     lukem #endif /* not lint */
     36   1.1     lukem 
     37   1.1     lukem #include <sys/socket.h>
     38   1.1     lukem 
     39   1.1     lukem #include <assert.h>
     40   1.1     lukem #include <ctype.h>
     41   1.1     lukem #include <errno.h>
     42   1.1     lukem #include <grp.h>
     43   1.1     lukem #include <limits.h>
     44   1.1     lukem #include <netdb.h>
     45  1.14      tron #include <netgroup.h>
     46   1.1     lukem #include <pwd.h>
     47   1.1     lukem #include <stdio.h>
     48   1.5     lukem #include <stdarg.h>
     49  1.14      tron #include <stdbool.h>
     50   1.1     lukem #include <stdlib.h>
     51   1.1     lukem #include <string.h>
     52   1.1     lukem #include <unistd.h>
     53  1.10  christos #include <paths.h>
     54  1.10  christos #include <err.h>
     55   1.1     lukem 
     56   1.1     lukem #include <arpa/inet.h>
     57   1.1     lukem #include <arpa/nameser.h>
     58   1.1     lukem 
     59   1.7  ginsbach #include <net/if.h>
     60   1.7  ginsbach #include <net/if_ether.h>
     61   1.7  ginsbach 
     62   1.1     lukem #include <netinet/in.h>		/* for INET6_ADDRSTRLEN */
     63   1.1     lukem 
     64   1.6  ginsbach #include <rpc/rpcent.h>
     65   1.6  ginsbach 
     66  1.10  christos #include <disktab.h>
     67  1.10  christos 
     68  1.10  christos static int	usage(void) __attribute__((__noreturn__));
     69   1.1     lukem static int	parsenum(const char *, unsigned long *);
     70  1.10  christos static int	disktab(int, char *[]);
     71  1.12  christos static int	gettytab(int, char *[]);
     72   1.7  ginsbach static int	ethers(int, char *[]);
     73   1.1     lukem static int	group(int, char *[]);
     74   1.1     lukem static int	hosts(int, char *[]);
     75  1.14      tron static int	netgroup(int, char *[]);
     76   1.2     lukem static int	networks(int, char *[]);
     77   1.1     lukem static int	passwd(int, char *[]);
     78  1.10  christos static int	printcap(int, char *[]);
     79   1.3     lukem static int	protocols(int, char *[]);
     80   1.6  ginsbach static int	rpc(int, char *[]);
     81   1.4     lukem static int	services(int, char *[]);
     82   1.1     lukem static int	shells(int, char *[]);
     83  1.10  christos static int	termcap(int, char *[]);
     84   1.1     lukem 
     85   1.1     lukem enum {
     86   1.1     lukem 	RV_OK		= 0,
     87   1.1     lukem 	RV_USAGE	= 1,
     88   1.1     lukem 	RV_NOTFOUND	= 2,
     89  1.10  christos 	RV_NOENUM	= 3
     90   1.1     lukem };
     91   1.1     lukem 
     92   1.5     lukem static struct getentdb {
     93   1.5     lukem 	const char	*name;
     94   1.5     lukem 	int		(*callback)(int, char *[]);
     95   1.5     lukem } databases[] = {
     96  1.10  christos 	{	"disktab",	disktab,	},
     97   1.7  ginsbach 	{	"ethers",	ethers,		},
     98  1.12  christos 	{	"gettytab",	gettytab,	},
     99   1.5     lukem 	{	"group",	group,		},
    100   1.5     lukem 	{	"hosts",	hosts,		},
    101  1.14      tron 	{	"netgroup",	netgroup,	},
    102   1.5     lukem 	{	"networks",	networks,	},
    103   1.5     lukem 	{	"passwd",	passwd,		},
    104  1.15      yamt 	{	"printcap",	printcap,	},
    105   1.5     lukem 	{	"protocols",	protocols,	},
    106   1.6  ginsbach 	{	"rpc",		rpc,		},
    107   1.5     lukem 	{	"services",	services,	},
    108   1.5     lukem 	{	"shells",	shells,		},
    109  1.10  christos 	{	"termcap",	termcap,	},
    110   1.5     lukem 
    111   1.5     lukem 	{	NULL,		NULL,		},
    112   1.5     lukem };
    113   1.5     lukem 
    114   1.5     lukem 
    115   1.1     lukem int
    116   1.1     lukem main(int argc, char *argv[])
    117   1.1     lukem {
    118   1.5     lukem 	struct getentdb	*curdb;
    119   1.1     lukem 
    120   1.1     lukem 	setprogname(argv[0]);
    121   1.1     lukem 
    122   1.1     lukem 	if (argc < 2)
    123   1.1     lukem 		usage();
    124  1.10  christos 	for (curdb = databases; curdb->name != NULL; curdb++)
    125  1.10  christos 		if (strcmp(curdb->name, argv[1]) == 0)
    126  1.10  christos 			return (*curdb->callback)(argc, argv);
    127  1.10  christos 
    128  1.10  christos 	warn("Unknown database `%s'", argv[1]);
    129   1.1     lukem 	usage();
    130   1.1     lukem 	/* NOTREACHED */
    131   1.1     lukem }
    132   1.1     lukem 
    133   1.1     lukem static int
    134   1.1     lukem usage(void)
    135   1.1     lukem {
    136   1.5     lukem 	struct getentdb	*curdb;
    137   1.1     lukem 
    138  1.10  christos 	(void)fprintf(stderr, "Usage: %s database [key ...]\n",
    139   1.1     lukem 	    getprogname());
    140  1.10  christos 	(void)fprintf(stderr, "       database may be one of:\n\t");
    141  1.10  christos 	for (curdb = databases; curdb->name != NULL; curdb++)
    142  1.10  christos 		(void)fprintf(stderr, " %s", curdb->name);
    143  1.10  christos 	(void)fprintf(stderr, "\n");
    144   1.1     lukem 	exit(RV_USAGE);
    145   1.1     lukem 	/* NOTREACHED */
    146   1.1     lukem }
    147   1.1     lukem 
    148   1.1     lukem static int
    149   1.1     lukem parsenum(const char *word, unsigned long *result)
    150   1.1     lukem {
    151   1.1     lukem 	unsigned long	num;
    152   1.1     lukem 	char		*ep;
    153   1.1     lukem 
    154   1.1     lukem 	assert(word != NULL);
    155   1.1     lukem 	assert(result != NULL);
    156   1.1     lukem 
    157   1.1     lukem 	if (!isdigit((unsigned char)word[0]))
    158   1.1     lukem 		return 0;
    159   1.1     lukem 	errno = 0;
    160   1.1     lukem 	num = strtoul(word, &ep, 10);
    161   1.1     lukem 	if (num == ULONG_MAX && errno == ERANGE)
    162   1.1     lukem 		return 0;
    163   1.1     lukem 	if (*ep != '\0')
    164   1.1     lukem 		return 0;
    165   1.1     lukem 	*result = num;
    166   1.1     lukem 	return 1;
    167   1.1     lukem }
    168   1.1     lukem 
    169   1.5     lukem /*
    170   1.5     lukem  * printfmtstrings --
    171   1.5     lukem  *	vprintf(format, ...),
    172   1.5     lukem  *	then the aliases (beginning with prefix, separated by sep),
    173   1.5     lukem  *	then a newline
    174   1.5     lukem  */
    175   1.5     lukem static void
    176   1.5     lukem printfmtstrings(char *strings[], const char *prefix, const char *sep,
    177  1.10  christos     const char *fmt, ...)
    178   1.5     lukem {
    179   1.5     lukem 	va_list		ap;
    180   1.5     lukem 	const char	*curpref;
    181  1.10  christos 	size_t		i;
    182   1.1     lukem 
    183   1.5     lukem 	va_start(ap, fmt);
    184  1.10  christos 	(void)vprintf(fmt, ap);
    185  1.10  christos 	va_end(ap);
    186   1.1     lukem 
    187   1.5     lukem 	curpref = prefix;
    188   1.5     lukem 	for (i = 0; strings[i] != NULL; i++) {
    189  1.10  christos 		(void)printf("%s%s", curpref, strings[i]);
    190   1.5     lukem 		curpref = sep;
    191   1.1     lukem 	}
    192  1.10  christos 	(void)printf("\n");
    193   1.1     lukem }
    194   1.1     lukem 
    195   1.5     lukem 
    196   1.5     lukem 		/*
    197   1.7  ginsbach 		 * ethers
    198   1.7  ginsbach 		 */
    199   1.7  ginsbach 
    200   1.7  ginsbach static int
    201   1.7  ginsbach ethers(int argc, char *argv[])
    202   1.7  ginsbach {
    203   1.7  ginsbach 	char		hostname[MAXHOSTNAMELEN + 1], *hp;
    204   1.7  ginsbach 	struct ether_addr ea, *eap;
    205   1.7  ginsbach 	int		i, rv;
    206   1.7  ginsbach 
    207   1.7  ginsbach 	assert(argc > 1);
    208   1.7  ginsbach 	assert(argv != NULL);
    209   1.7  ginsbach 
    210  1.10  christos #define ETHERSPRINT	(void)printf("%-17s  %s\n", ether_ntoa(eap), hp)
    211   1.7  ginsbach 
    212   1.7  ginsbach 	rv = RV_OK;
    213   1.7  ginsbach 	if (argc == 2) {
    214  1.10  christos 		warnx("Enumeration not supported on ethers");
    215   1.7  ginsbach 		rv = RV_NOENUM;
    216   1.7  ginsbach 	} else {
    217   1.7  ginsbach 		for (i = 2; i < argc; i++) {
    218   1.7  ginsbach 			if ((eap = ether_aton(argv[i])) == NULL) {
    219   1.7  ginsbach 				eap = &ea;
    220   1.7  ginsbach 				hp = argv[i];
    221   1.7  ginsbach 				if (ether_hostton(hp, eap) != 0) {
    222   1.7  ginsbach 					rv = RV_NOTFOUND;
    223   1.7  ginsbach 					break;
    224   1.7  ginsbach 				}
    225   1.7  ginsbach 			} else {
    226   1.7  ginsbach 				hp = hostname;
    227   1.7  ginsbach 				if (ether_ntohost(hp, eap) != 0) {
    228   1.7  ginsbach 					rv = RV_NOTFOUND;
    229   1.7  ginsbach 					break;
    230   1.7  ginsbach 				}
    231   1.7  ginsbach 			}
    232   1.7  ginsbach 			ETHERSPRINT;
    233   1.7  ginsbach 		}
    234   1.7  ginsbach 	}
    235   1.7  ginsbach 	return rv;
    236   1.7  ginsbach }
    237   1.7  ginsbach 
    238   1.7  ginsbach 		/*
    239   1.5     lukem 		 * group
    240   1.5     lukem 		 */
    241   1.5     lukem 
    242   1.1     lukem static int
    243   1.1     lukem group(int argc, char *argv[])
    244   1.1     lukem {
    245   1.1     lukem 	struct group	*gr;
    246   1.1     lukem 	unsigned long	id;
    247   1.1     lukem 	int		i, rv;
    248   1.1     lukem 
    249   1.1     lukem 	assert(argc > 1);
    250   1.1     lukem 	assert(argv != NULL);
    251   1.1     lukem 
    252   1.5     lukem #define GROUPPRINT	printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \
    253   1.5     lukem 			    gr->gr_name, gr->gr_passwd, gr->gr_gid)
    254   1.5     lukem 
    255  1.10  christos 	(void)setgroupent(1);
    256   1.1     lukem 	rv = RV_OK;
    257   1.1     lukem 	if (argc == 2) {
    258   1.1     lukem 		while ((gr = getgrent()) != NULL)
    259   1.5     lukem 			GROUPPRINT;
    260   1.1     lukem 	} else {
    261   1.1     lukem 		for (i = 2; i < argc; i++) {
    262   1.1     lukem 			if (parsenum(argv[i], &id))
    263  1.10  christos 				gr = getgrgid((gid_t)id);
    264   1.1     lukem 			else
    265   1.1     lukem 				gr = getgrnam(argv[i]);
    266   1.1     lukem 			if (gr != NULL)
    267   1.5     lukem 				GROUPPRINT;
    268   1.1     lukem 			else {
    269   1.1     lukem 				rv = RV_NOTFOUND;
    270   1.1     lukem 				break;
    271   1.1     lukem 			}
    272   1.1     lukem 		}
    273   1.1     lukem 	}
    274   1.1     lukem 	endgrent();
    275   1.1     lukem 	return rv;
    276   1.1     lukem }
    277   1.1     lukem 
    278   1.3     lukem 
    279   1.1     lukem 		/*
    280   1.1     lukem 		 * hosts
    281   1.1     lukem 		 */
    282   1.1     lukem 
    283   1.1     lukem static void
    284   1.1     lukem hostsprint(const struct hostent *he)
    285   1.1     lukem {
    286   1.1     lukem 	char	buf[INET6_ADDRSTRLEN];
    287   1.1     lukem 
    288   1.1     lukem 	assert(he != NULL);
    289   1.1     lukem 	if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
    290  1.10  christos 		(void)strlcpy(buf, "# unknown", sizeof(buf));
    291   1.5     lukem 	printfmtstrings(he->h_aliases, "  ", " ", "%-16s  %s", buf, he->h_name);
    292   1.1     lukem }
    293   1.1     lukem 
    294   1.1     lukem static int
    295   1.1     lukem hosts(int argc, char *argv[])
    296   1.1     lukem {
    297   1.1     lukem 	struct hostent	*he;
    298   1.1     lukem 	char		addr[IN6ADDRSZ];
    299   1.1     lukem 	int		i, rv;
    300   1.1     lukem 
    301   1.1     lukem 	assert(argc > 1);
    302   1.1     lukem 	assert(argv != NULL);
    303   1.1     lukem 
    304   1.1     lukem 	sethostent(1);
    305   1.1     lukem 	rv = RV_OK;
    306   1.1     lukem 	if (argc == 2) {
    307   1.1     lukem 		while ((he = gethostent()) != NULL)
    308   1.1     lukem 			hostsprint(he);
    309   1.1     lukem 	} else {
    310   1.1     lukem 		for (i = 2; i < argc; i++) {
    311   1.1     lukem 			if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
    312   1.1     lukem 				he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
    313   1.1     lukem 			else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
    314   1.1     lukem 				he = gethostbyaddr(addr, INADDRSZ, AF_INET);
    315   1.1     lukem 			else
    316   1.1     lukem 				he = gethostbyname(argv[i]);
    317   1.1     lukem 			if (he != NULL)
    318   1.1     lukem 				hostsprint(he);
    319   1.1     lukem 			else {
    320   1.1     lukem 				rv = RV_NOTFOUND;
    321   1.1     lukem 				break;
    322   1.1     lukem 			}
    323   1.1     lukem 		}
    324   1.1     lukem 	}
    325   1.1     lukem 	endhostent();
    326   1.1     lukem 	return rv;
    327   1.1     lukem }
    328   1.1     lukem 
    329  1.14      tron 		/*
    330  1.14      tron 		 * netgroup
    331  1.14      tron 		 */
    332  1.14      tron static int
    333  1.14      tron netgroup(int argc, char *argv[])
    334  1.14      tron {
    335  1.14      tron 	int		rv, i;
    336  1.14      tron 	bool		first;
    337  1.14      tron 	const char	*host, *user, *domain;
    338  1.14      tron 
    339  1.14      tron 	assert(argc > 1);
    340  1.14      tron 	assert(argv != NULL);
    341  1.14      tron 
    342  1.14      tron #define NETGROUPPRINT(s)	(((s) != NULL) ? (s) : "")
    343  1.14      tron 
    344  1.14      tron 	rv = RV_OK;
    345  1.14      tron 	if (argc == 2) {
    346  1.14      tron 		warnx("Enumeration not supported on netgroup");
    347  1.14      tron 		rv = RV_NOENUM;
    348  1.14      tron 	} else {
    349  1.14      tron 		for (i = 2; i < argc; i++) {
    350  1.14      tron 			setnetgrent(argv[i]);
    351  1.14      tron 			first = true;
    352  1.14      tron 			while (getnetgrent(&host, &user, &domain) != 0) {
    353  1.14      tron 				if (first) {
    354  1.14      tron 					first = false;
    355  1.14      tron 					(void)fputs(argv[i], stdout);
    356  1.14      tron 				}
    357  1.14      tron 				(void)printf(" (%s,%s,%s)",
    358  1.14      tron 				    NETGROUPPRINT(host),
    359  1.14      tron 				    NETGROUPPRINT(user),
    360  1.14      tron 				    NETGROUPPRINT(domain));
    361  1.14      tron 			}
    362  1.14      tron 			if (!first)
    363  1.14      tron 				(void)putchar('\n');
    364  1.14      tron 			endnetgrent();
    365  1.14      tron 		}
    366  1.14      tron 	}
    367  1.14      tron 
    368  1.14      tron 	return rv;
    369  1.14      tron }
    370   1.2     lukem 
    371   1.2     lukem 		/*
    372   1.2     lukem 		 * networks
    373   1.2     lukem 		 */
    374   1.2     lukem 
    375   1.2     lukem static void
    376   1.2     lukem networksprint(const struct netent *ne)
    377   1.2     lukem {
    378   1.2     lukem 	char		buf[INET6_ADDRSTRLEN];
    379   1.2     lukem 	struct	in_addr	ianet;
    380   1.2     lukem 
    381   1.2     lukem 	assert(ne != NULL);
    382   1.2     lukem 	ianet = inet_makeaddr(ne->n_net, 0);
    383   1.2     lukem 	if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
    384  1.10  christos 		(void)strlcpy(buf, "# unknown", sizeof(buf));
    385   1.5     lukem 	printfmtstrings(ne->n_aliases, "  ", " ", "%-16s  %s", ne->n_name, buf);
    386   1.2     lukem }
    387   1.2     lukem 
    388   1.2     lukem static int
    389   1.2     lukem networks(int argc, char *argv[])
    390   1.2     lukem {
    391   1.2     lukem 	struct netent	*ne;
    392   1.2     lukem 	in_addr_t	net;
    393   1.2     lukem 	int		i, rv;
    394   1.2     lukem 
    395   1.2     lukem 	assert(argc > 1);
    396   1.2     lukem 	assert(argv != NULL);
    397   1.2     lukem 
    398   1.2     lukem 	setnetent(1);
    399   1.2     lukem 	rv = RV_OK;
    400   1.2     lukem 	if (argc == 2) {
    401   1.2     lukem 		while ((ne = getnetent()) != NULL)
    402   1.2     lukem 			networksprint(ne);
    403   1.2     lukem 	} else {
    404   1.2     lukem 		for (i = 2; i < argc; i++) {
    405   1.2     lukem 			net = inet_network(argv[i]);
    406   1.2     lukem 			if (net != INADDR_NONE)
    407   1.2     lukem 				ne = getnetbyaddr(net, AF_INET);
    408   1.2     lukem 			else
    409   1.2     lukem 				ne = getnetbyname(argv[i]);
    410   1.2     lukem 			if (ne != NULL)
    411   1.2     lukem 				networksprint(ne);
    412   1.2     lukem 			else {
    413   1.2     lukem 				rv = RV_NOTFOUND;
    414   1.2     lukem 				break;
    415   1.2     lukem 			}
    416   1.2     lukem 		}
    417   1.2     lukem 	}
    418   1.2     lukem 	endnetent();
    419   1.2     lukem 	return rv;
    420   1.2     lukem }
    421   1.2     lukem 
    422   1.3     lukem 
    423   1.1     lukem 		/*
    424   1.1     lukem 		 * passwd
    425   1.1     lukem 		 */
    426   1.1     lukem 
    427   1.1     lukem static int
    428   1.1     lukem passwd(int argc, char *argv[])
    429   1.1     lukem {
    430   1.1     lukem 	struct passwd	*pw;
    431   1.1     lukem 	unsigned long	id;
    432   1.1     lukem 	int		i, rv;
    433   1.1     lukem 
    434   1.1     lukem 	assert(argc > 1);
    435   1.1     lukem 	assert(argv != NULL);
    436   1.1     lukem 
    437  1.10  christos #define PASSWDPRINT	(void)printf("%s:%s:%u:%u:%s:%s:%s\n", \
    438   1.5     lukem 			    pw->pw_name, pw->pw_passwd, pw->pw_uid, \
    439   1.5     lukem 			    pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell)
    440   1.5     lukem 
    441  1.10  christos 	(void)setpassent(1);
    442   1.1     lukem 	rv = RV_OK;
    443   1.1     lukem 	if (argc == 2) {
    444   1.1     lukem 		while ((pw = getpwent()) != NULL)
    445   1.5     lukem 			PASSWDPRINT;
    446   1.1     lukem 	} else {
    447   1.1     lukem 		for (i = 2; i < argc; i++) {
    448   1.1     lukem 			if (parsenum(argv[i], &id))
    449  1.10  christos 				pw = getpwuid((uid_t)id);
    450   1.1     lukem 			else
    451   1.1     lukem 				pw = getpwnam(argv[i]);
    452   1.1     lukem 			if (pw != NULL)
    453   1.5     lukem 				PASSWDPRINT;
    454   1.1     lukem 			else {
    455   1.1     lukem 				rv = RV_NOTFOUND;
    456   1.1     lukem 				break;
    457   1.1     lukem 			}
    458   1.1     lukem 		}
    459   1.1     lukem 	}
    460   1.1     lukem 	endpwent();
    461   1.1     lukem 	return rv;
    462   1.1     lukem }
    463   1.1     lukem 
    464  1.10  christos static char *
    465  1.10  christos mygetent(const char * const * db_array, const char *name)
    466  1.10  christos {
    467  1.10  christos 	char *buf = NULL;
    468  1.10  christos 	int error;
    469  1.10  christos 
    470  1.10  christos 	switch (error = cgetent(&buf, db_array, name)) {
    471  1.10  christos 	case -3:
    472  1.10  christos 		warnx("tc= loop in record `%s' in `%s'", name, db_array[0]);
    473  1.10  christos 		break;
    474  1.10  christos 	case -2:
    475  1.10  christos 		warn("system error fetching record `%s' in `%s'", name,
    476  1.10  christos 		    db_array[0]);
    477  1.10  christos 		break;
    478  1.10  christos 	case -1:
    479  1.10  christos 	case 0:
    480  1.10  christos 		break;
    481  1.10  christos 	case 1:
    482  1.10  christos 		warnx("tc= reference not found in record for `%s' in `%s'",
    483  1.10  christos 		    name, db_array[0]);
    484  1.10  christos 		break;
    485  1.10  christos 	default:
    486  1.10  christos 		warnx("unknown error %d in record `%s' in `%s'", error, name,
    487  1.10  christos 		    db_array[0]);
    488  1.10  christos 		break;
    489  1.10  christos 	}
    490  1.10  christos 	return buf;
    491  1.10  christos }
    492  1.10  christos 
    493  1.10  christos static char *
    494  1.10  christos mygetone(const char * const * db_array, int first)
    495  1.10  christos {
    496  1.10  christos 	char *buf = NULL;
    497  1.10  christos 	int error;
    498  1.10  christos 
    499  1.10  christos 	switch (error = (first ? cgetfirst : cgetnext)(&buf, db_array)) {
    500  1.10  christos 	case -2:
    501  1.10  christos 		warnx("tc= loop in `%s'", db_array[0]);
    502  1.10  christos 		break;
    503  1.10  christos 	case -1:
    504  1.10  christos 		warn("system error fetching record in `%s'", db_array[0]);
    505  1.10  christos 		break;
    506  1.10  christos 	case 0:
    507  1.10  christos 	case 1:
    508  1.10  christos 		break;
    509  1.10  christos 	case 2:
    510  1.10  christos 		warnx("tc= reference not found in `%s'", db_array[0]);
    511  1.10  christos 		break;
    512  1.10  christos 	default:
    513  1.10  christos 		warnx("unknown error %d in `%s'", error, db_array[0]);
    514  1.10  christos 		break;
    515  1.10  christos 	}
    516  1.10  christos 	return buf;
    517  1.10  christos }
    518  1.10  christos 
    519  1.10  christos static void
    520  1.10  christos capprint(const char *cap)
    521  1.10  christos {
    522  1.10  christos 	char *c = strchr(cap, ':');
    523  1.10  christos 	if (c)
    524  1.10  christos 		if (c == cap)
    525  1.10  christos 			(void)printf("true\n");
    526  1.10  christos 		else {
    527  1.10  christos 			int l = (int)(c - cap);
    528  1.10  christos 			(void)printf("%*.*s\n", l, l, cap);
    529  1.10  christos 		}
    530  1.10  christos 	else
    531  1.10  christos 		(void)printf("%s\n", cap);
    532  1.10  christos }
    533  1.11  christos 
    534  1.11  christos static void
    535  1.11  christos prettyprint(char *b)
    536  1.11  christos {
    537  1.11  christos #define TERMWIDTH 65
    538  1.11  christos 	int did = 0;
    539  1.11  christos 	size_t len;
    540  1.11  christos 	char *s, c;
    541  1.11  christos 
    542  1.11  christos 	for (;;) {
    543  1.11  christos 		len = strlen(b);
    544  1.11  christos 		if (len <= TERMWIDTH) {
    545  1.11  christos done:
    546  1.11  christos 			if (did)
    547  1.11  christos 				printf("\t:");
    548  1.11  christos 			printf("%s\n", b);
    549  1.11  christos 			return;
    550  1.11  christos 		}
    551  1.11  christos 		for (s = b + TERMWIDTH; s > b && *s != ':'; s--)
    552  1.11  christos 			continue;
    553  1.11  christos 		if (*s++ != ':')
    554  1.11  christos 			goto done;
    555  1.11  christos 		c = *s;
    556  1.11  christos 		*s = '\0';
    557  1.11  christos 		if (did)
    558  1.11  christos 			printf("\t:");
    559  1.11  christos 		did++;
    560  1.11  christos 		printf("%s\\\n", b);
    561  1.11  christos 		*s = c;
    562  1.11  christos 		b = s;
    563  1.11  christos 	}
    564  1.11  christos }
    565  1.11  christos 
    566  1.11  christos static void
    567  1.11  christos handleone(const char * const *db_array, char *b, int recurse, int pretty,
    568  1.11  christos     int level)
    569  1.11  christos {
    570  1.11  christos 	char *tc;
    571  1.11  christos 
    572  1.11  christos 	if (level && pretty)
    573  1.11  christos 		printf("\n");
    574  1.11  christos 	if (pretty)
    575  1.11  christos 		prettyprint(b);
    576  1.11  christos 	else
    577  1.11  christos 		printf("%s\n", b);
    578  1.11  christos 	if (!recurse || cgetstr(b, "tc", &tc) <= 0)
    579  1.11  christos 		return;
    580  1.11  christos 
    581  1.11  christos 	b = mygetent(db_array, tc);
    582  1.11  christos 	free(tc);
    583  1.11  christos 
    584  1.11  christos 	if (b == NULL)
    585  1.11  christos 		return;
    586  1.11  christos 
    587  1.11  christos 	handleone(db_array, b, recurse, pretty, ++level);
    588  1.11  christos 	free(b);
    589  1.11  christos }
    590  1.11  christos 
    591  1.10  christos static int
    592  1.10  christos handlecap(const char *db, int argc, char *argv[])
    593  1.10  christos {
    594  1.10  christos 	static const char sfx[] = "=#:";
    595  1.10  christos 	const char *db_array[] = { db, NULL };
    596  1.10  christos 	char	*b, *cap;
    597  1.16     lukem 	int	i, rv, c;
    598  1.16     lukem 	size_t	j;
    599  1.11  christos 	int	expand = 1, recurse = 0, pretty = 0;
    600  1.10  christos 
    601  1.10  christos 	assert(argc > 1);
    602  1.10  christos 	assert(argv != NULL);
    603  1.10  christos 
    604  1.11  christos 	argc--;
    605  1.11  christos 	argv++;
    606  1.11  christos 	while ((c = getopt(argc, argv, "pnr")) != -1)
    607  1.11  christos 		switch (c) {
    608  1.11  christos 		case 'n':
    609  1.11  christos 			expand = 0;
    610  1.11  christos 			break;
    611  1.11  christos 		case 'r':
    612  1.11  christos 			expand = 0;
    613  1.11  christos 			recurse = 1;
    614  1.11  christos 			break;
    615  1.11  christos 		case 'p':
    616  1.11  christos 			pretty = 1;
    617  1.11  christos 			break;
    618  1.11  christos 		default:
    619  1.11  christos 			usage();
    620  1.11  christos 			break;
    621  1.11  christos 		}
    622  1.11  christos 
    623  1.11  christos 	argc -= optind;
    624  1.11  christos 	argv += optind;
    625  1.11  christos 	csetexpandtc(expand);
    626  1.10  christos 	rv = RV_OK;
    627  1.11  christos 	if (argc == 0) {
    628  1.10  christos 		for (b = mygetone(db_array, 1); b; b = mygetone(db_array, 0)) {
    629  1.11  christos 			handleone(db_array, b, recurse, pretty, 0);
    630  1.10  christos 			free(b);
    631  1.10  christos 		}
    632  1.10  christos 	} else {
    633  1.11  christos 		if ((b = mygetent(db_array, argv[0])) == NULL)
    634  1.10  christos 			return RV_NOTFOUND;
    635  1.11  christos 		if (argc == 1)
    636  1.11  christos 			handleone(db_array, b, recurse, pretty, 0);
    637  1.10  christos 		else {
    638  1.11  christos 			for (i = 2; i < argc; i++) {
    639  1.10  christos 				for (j = 0; j < sizeof(sfx) - 1; j++) {
    640  1.10  christos 					cap = cgetcap(b, argv[i], sfx[j]);
    641  1.10  christos 					if (cap) {
    642  1.10  christos 						capprint(cap);
    643  1.10  christos 						break;
    644  1.10  christos 					}
    645  1.10  christos 				}
    646  1.10  christos 				if (j == sizeof(sfx) - 1)
    647  1.10  christos 					printf("false\n");
    648  1.10  christos 			}
    649  1.10  christos 		}
    650  1.10  christos 		free(b);
    651  1.10  christos 	}
    652  1.10  christos 	return rv;
    653  1.10  christos }
    654  1.10  christos 
    655  1.10  christos 		/*
    656  1.12  christos 		 * gettytab
    657  1.12  christos 		 */
    658  1.12  christos 
    659  1.12  christos static int
    660  1.12  christos gettytab(int argc, char *argv[])
    661  1.12  christos {
    662  1.12  christos 	return handlecap(_PATH_GETTYTAB, argc, argv);
    663  1.12  christos }
    664  1.12  christos 
    665  1.12  christos 		/*
    666  1.10  christos 		 * printcap
    667  1.10  christos 		 */
    668  1.10  christos 
    669  1.10  christos static int
    670  1.10  christos printcap(int argc, char *argv[])
    671  1.10  christos {
    672  1.10  christos 	return handlecap(_PATH_PRINTCAP, argc, argv);
    673  1.10  christos }
    674   1.3     lukem 
    675   1.3     lukem 		/*
    676  1.10  christos 		 * disktab
    677  1.10  christos 		 */
    678  1.10  christos 
    679  1.10  christos static int
    680  1.10  christos disktab(int argc, char *argv[])
    681  1.10  christos {
    682  1.10  christos 	return handlecap(_PATH_DISKTAB, argc, argv);
    683  1.10  christos }
    684  1.10  christos 
    685  1.10  christos 		/*
    686  1.10  christos 		 * termcap
    687  1.10  christos 		 */
    688  1.10  christos 
    689  1.10  christos static int
    690  1.10  christos termcap(int argc, char *argv[])
    691  1.10  christos {
    692  1.10  christos 	return handlecap(_PATH_TERMCAP, argc, argv);
    693  1.10  christos }
    694  1.10  christos 		/*
    695   1.3     lukem 		 * protocols
    696   1.3     lukem 		 */
    697   1.3     lukem 
    698   1.3     lukem static int
    699   1.3     lukem protocols(int argc, char *argv[])
    700   1.3     lukem {
    701   1.3     lukem 	struct protoent	*pe;
    702   1.3     lukem 	unsigned long	id;
    703   1.3     lukem 	int		i, rv;
    704   1.3     lukem 
    705   1.3     lukem 	assert(argc > 1);
    706   1.3     lukem 	assert(argv != NULL);
    707   1.3     lukem 
    708   1.5     lukem #define PROTOCOLSPRINT	printfmtstrings(pe->p_aliases, "  ", " ", \
    709   1.5     lukem 			    "%-16s  %5d", pe->p_name, pe->p_proto)
    710   1.5     lukem 
    711   1.3     lukem 	setprotoent(1);
    712   1.3     lukem 	rv = RV_OK;
    713   1.3     lukem 	if (argc == 2) {
    714   1.3     lukem 		while ((pe = getprotoent()) != NULL)
    715   1.5     lukem 			PROTOCOLSPRINT;
    716   1.3     lukem 	} else {
    717   1.3     lukem 		for (i = 2; i < argc; i++) {
    718   1.3     lukem 			if (parsenum(argv[i], &id))
    719  1.10  christos 				pe = getprotobynumber((int)id);
    720   1.3     lukem 			else
    721   1.3     lukem 				pe = getprotobyname(argv[i]);
    722   1.3     lukem 			if (pe != NULL)
    723   1.5     lukem 				PROTOCOLSPRINT;
    724   1.3     lukem 			else {
    725   1.3     lukem 				rv = RV_NOTFOUND;
    726   1.3     lukem 				break;
    727   1.3     lukem 			}
    728   1.3     lukem 		}
    729   1.3     lukem 	}
    730   1.3     lukem 	endprotoent();
    731   1.3     lukem 	return rv;
    732   1.3     lukem }
    733   1.3     lukem 
    734   1.6  ginsbach 		/*
    735   1.6  ginsbach 		 * rpc
    736   1.6  ginsbach 		 */
    737   1.6  ginsbach 
    738   1.6  ginsbach static int
    739   1.6  ginsbach rpc(int argc, char *argv[])
    740   1.6  ginsbach {
    741   1.6  ginsbach 	struct rpcent	*re;
    742   1.6  ginsbach 	unsigned long	id;
    743   1.6  ginsbach 	int		i, rv;
    744   1.6  ginsbach 
    745   1.6  ginsbach 	assert(argc > 1);
    746   1.6  ginsbach 	assert(argv != NULL);
    747   1.6  ginsbach 
    748   1.6  ginsbach #define RPCPRINT	printfmtstrings(re->r_aliases, "  ", " ", \
    749   1.6  ginsbach 				"%-16s  %6d", \
    750   1.6  ginsbach 				re->r_name, re->r_number)
    751   1.6  ginsbach 
    752   1.6  ginsbach 	setrpcent(1);
    753   1.6  ginsbach 	rv = RV_OK;
    754   1.6  ginsbach 	if (argc == 2) {
    755   1.6  ginsbach 		while ((re = getrpcent()) != NULL)
    756   1.6  ginsbach 			RPCPRINT;
    757   1.6  ginsbach 	} else {
    758   1.6  ginsbach 		for (i = 2; i < argc; i++) {
    759   1.6  ginsbach 			if (parsenum(argv[i], &id))
    760  1.10  christos 				re = getrpcbynumber((int)id);
    761   1.6  ginsbach 			else
    762   1.6  ginsbach 				re = getrpcbyname(argv[i]);
    763   1.6  ginsbach 			if (re != NULL)
    764   1.6  ginsbach 				RPCPRINT;
    765   1.6  ginsbach 			else {
    766   1.6  ginsbach 				rv = RV_NOTFOUND;
    767   1.6  ginsbach 				break;
    768   1.6  ginsbach 			}
    769   1.6  ginsbach 		}
    770   1.6  ginsbach 	}
    771   1.6  ginsbach 	endrpcent();
    772   1.6  ginsbach 	return rv;
    773   1.6  ginsbach }
    774   1.3     lukem 
    775   1.1     lukem 		/*
    776   1.4     lukem 		 * services
    777   1.4     lukem 		 */
    778   1.4     lukem 
    779   1.4     lukem static int
    780   1.4     lukem services(int argc, char *argv[])
    781   1.4     lukem {
    782   1.4     lukem 	struct servent	*se;
    783   1.4     lukem 	unsigned long	id;
    784   1.4     lukem 	char		*proto;
    785   1.4     lukem 	int		i, rv;
    786   1.4     lukem 
    787   1.4     lukem 	assert(argc > 1);
    788   1.4     lukem 	assert(argv != NULL);
    789   1.4     lukem 
    790   1.5     lukem #define SERVICESPRINT	printfmtstrings(se->s_aliases, "  ", " ", \
    791   1.5     lukem 			    "%-16s  %5d/%s", \
    792   1.5     lukem 			    se->s_name, ntohs(se->s_port), se->s_proto)
    793   1.5     lukem 
    794   1.4     lukem 	setservent(1);
    795   1.4     lukem 	rv = RV_OK;
    796   1.4     lukem 	if (argc == 2) {
    797   1.4     lukem 		while ((se = getservent()) != NULL)
    798   1.5     lukem 			SERVICESPRINT;
    799   1.4     lukem 	} else {
    800   1.4     lukem 		for (i = 2; i < argc; i++) {
    801   1.4     lukem 			proto = strchr(argv[i], '/');
    802   1.4     lukem 			if (proto != NULL)
    803   1.4     lukem 				*proto++ = '\0';
    804   1.4     lukem 			if (parsenum(argv[i], &id))
    805   1.9    simonb 				se = getservbyport(htons(id), proto);
    806   1.4     lukem 			else
    807   1.4     lukem 				se = getservbyname(argv[i], proto);
    808   1.4     lukem 			if (se != NULL)
    809   1.5     lukem 				SERVICESPRINT;
    810   1.4     lukem 			else {
    811   1.4     lukem 				rv = RV_NOTFOUND;
    812   1.4     lukem 				break;
    813   1.4     lukem 			}
    814   1.4     lukem 		}
    815   1.4     lukem 	}
    816   1.4     lukem 	endservent();
    817   1.4     lukem 	return rv;
    818   1.4     lukem }
    819   1.4     lukem 
    820   1.4     lukem 
    821   1.4     lukem 		/*
    822   1.1     lukem 		 * shells
    823   1.1     lukem 		 */
    824   1.1     lukem 
    825   1.1     lukem static int
    826   1.1     lukem shells(int argc, char *argv[])
    827   1.1     lukem {
    828   1.1     lukem 	const char	*sh;
    829   1.1     lukem 	int		i, rv;
    830   1.1     lukem 
    831   1.1     lukem 	assert(argc > 1);
    832   1.1     lukem 	assert(argv != NULL);
    833   1.1     lukem 
    834  1.10  christos #define SHELLSPRINT	(void)printf("%s\n", sh)
    835   1.5     lukem 
    836   1.1     lukem 	setusershell();
    837   1.1     lukem 	rv = RV_OK;
    838   1.1     lukem 	if (argc == 2) {
    839   1.1     lukem 		while ((sh = getusershell()) != NULL)
    840   1.5     lukem 			SHELLSPRINT;
    841   1.1     lukem 	} else {
    842   1.1     lukem 		for (i = 2; i < argc; i++) {
    843   1.1     lukem 			setusershell();
    844   1.1     lukem 			while ((sh = getusershell()) != NULL) {
    845   1.1     lukem 				if (strcmp(sh, argv[i]) == 0) {
    846   1.5     lukem 					SHELLSPRINT;
    847   1.1     lukem 					break;
    848   1.1     lukem 				}
    849   1.1     lukem 			}
    850   1.1     lukem 			if (sh == NULL) {
    851   1.1     lukem 				rv = RV_NOTFOUND;
    852   1.1     lukem 				break;
    853   1.1     lukem 			}
    854   1.1     lukem 		}
    855   1.1     lukem 	}
    856   1.1     lukem 	endusershell();
    857   1.1     lukem 	return rv;
    858   1.1     lukem }
    859