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