Home | History | Annotate | Line # | Download | only in getent
getent.c revision 1.4
      1 /*	$NetBSD: getent.c,v 1.4 2004/11/29 04:13:15 lukem Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Luke Mewburn.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 #ifndef lint
     41 __RCSID("$NetBSD: getent.c,v 1.4 2004/11/29 04:13:15 lukem Exp $");
     42 #endif /* not lint */
     43 
     44 #include <sys/socket.h>
     45 
     46 #include <assert.h>
     47 #include <ctype.h>
     48 #include <errno.h>
     49 #include <grp.h>
     50 #include <limits.h>
     51 #include <netdb.h>
     52 #include <pwd.h>
     53 #include <stdio.h>
     54 #include <stdlib.h>
     55 #include <string.h>
     56 #include <unistd.h>
     57 
     58 #include <arpa/inet.h>
     59 #include <arpa/nameser.h>
     60 
     61 #include <netinet/in.h>		/* for INET6_ADDRSTRLEN */
     62 
     63 static int	usage(void);
     64 static int	parsenum(const char *, unsigned long *);
     65 static int	group(int, char *[]);
     66 static int	hosts(int, char *[]);
     67 static int	networks(int, char *[]);
     68 static int	passwd(int, char *[]);
     69 static int	protocols(int, char *[]);
     70 static int	services(int, char *[]);
     71 static int	shells(int, char *[]);
     72 
     73 enum {
     74 	RV_OK		= 0,
     75 	RV_USAGE	= 1,
     76 	RV_NOTFOUND	= 2,
     77 	RV_NOENUM	= 3,
     78 };
     79 
     80 int
     81 main(int argc, char *argv[])
     82 {
     83 	static struct {
     84 		const char	*name;
     85 		int		(*callback)(int, char *[]);
     86 	} *curdb, dbs[] = {
     87 		{	"group",	group,		},
     88 		{	"hosts",	hosts,		},
     89 		{	"networks",	networks,	},
     90 		{	"passwd",	passwd,		},
     91 		{	"protocols",	protocols,	},
     92 		{	"services",	services,	},
     93 		{	"shells",	shells,		},
     94 
     95 		{	NULL,		NULL,		},
     96 	};
     97 
     98 	setprogname(argv[0]);
     99 
    100 	if (argc < 2)
    101 		usage();
    102 	for (curdb = dbs; curdb->name != NULL; curdb++) {
    103 		if (strcmp(curdb->name, argv[1]) == 0) {
    104 			exit(curdb->callback(argc, argv));
    105 			break;
    106 		}
    107 	}
    108 	fprintf(stderr, "Unknown database: %s\n", argv[1]);
    109 	usage();
    110 	/* NOTREACHED */
    111 	return RV_USAGE;
    112 }
    113 
    114 static int
    115 usage(void)
    116 {
    117 
    118 	fprintf(stderr, "Usage: %s database [key ...]\n",
    119 	    getprogname());
    120 	exit(RV_USAGE);
    121 	/* NOTREACHED */
    122 }
    123 
    124 static int
    125 parsenum(const char *word, unsigned long *result)
    126 {
    127 	unsigned long	num;
    128 	char		*ep;
    129 
    130 	assert(word != NULL);
    131 	assert(result != NULL);
    132 
    133 	if (!isdigit((unsigned char)word[0]))
    134 		return 0;
    135 	errno = 0;
    136 	num = strtoul(word, &ep, 10);
    137 	if (num == ULONG_MAX && errno == ERANGE)
    138 		return 0;
    139 	if (*ep != '\0')
    140 		return 0;
    141 	*result = num;
    142 	return 1;
    143 }
    144 
    145 
    146 		/*
    147 		 * group
    148 		 */
    149 
    150 static void
    151 groupprint(const struct group *gr)
    152 {
    153 	char	prefix;
    154 	int	i;
    155 
    156 	assert(gr != NULL);
    157 	printf("%s:%s:%u",
    158 	    gr->gr_name, gr->gr_passwd, gr->gr_gid);
    159 	prefix = ':';
    160 	for (i = 0; gr->gr_mem[i] != NULL; i++) {
    161 		printf("%c%s", prefix, gr->gr_mem[i]);
    162 		prefix = ',';
    163 	}
    164 	printf("\n");
    165 }
    166 
    167 static int
    168 group(int argc, char *argv[])
    169 {
    170 	struct group	*gr;
    171 	unsigned long	id;
    172 	int		i, rv;
    173 
    174 	assert(argc > 1);
    175 	assert(argv != NULL);
    176 
    177 	setgroupent(1);
    178 	rv = RV_OK;
    179 	if (argc == 2) {
    180 		while ((gr = getgrent()) != NULL)
    181 			groupprint(gr);
    182 	} else {
    183 		for (i = 2; i < argc; i++) {
    184 			if (parsenum(argv[i], &id))
    185 				gr = getgrgid((gid_t)id);
    186 			else
    187 				gr = getgrnam(argv[i]);
    188 			if (gr != NULL)
    189 				groupprint(gr);
    190 			else {
    191 				rv = RV_NOTFOUND;
    192 				break;
    193 			}
    194 		}
    195 	}
    196 	endgrent();
    197 	return rv;
    198 }
    199 
    200 
    201 		/*
    202 		 * hosts
    203 		 */
    204 
    205 static void
    206 hostsprint(const struct hostent *he)
    207 {
    208 	char	buf[INET6_ADDRSTRLEN];
    209 	int	i;
    210 
    211 	assert(he != NULL);
    212 	if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
    213 		strlcpy(buf, "# unknown", sizeof(buf));
    214 	printf("%s\t%s",
    215 	    buf, he->h_name);
    216 	for (i = 0; he->h_aliases[i] != NULL; i++) {
    217 		printf(" %s", he->h_aliases[i]);
    218 	}
    219 	printf("\n");
    220 }
    221 
    222 static int
    223 hosts(int argc, char *argv[])
    224 {
    225 	struct hostent	*he;
    226 	char		addr[IN6ADDRSZ];
    227 	int		i, rv;
    228 
    229 	assert(argc > 1);
    230 	assert(argv != NULL);
    231 
    232 	sethostent(1);
    233 	rv = RV_OK;
    234 	if (argc == 2) {
    235 		while ((he = gethostent()) != NULL)
    236 			hostsprint(he);
    237 	} else {
    238 		for (i = 2; i < argc; i++) {
    239 			if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
    240 				he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
    241 			else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
    242 				he = gethostbyaddr(addr, INADDRSZ, AF_INET);
    243 			else
    244 				he = gethostbyname(argv[i]);
    245 			if (he != NULL)
    246 				hostsprint(he);
    247 			else {
    248 				rv = RV_NOTFOUND;
    249 				break;
    250 			}
    251 		}
    252 	}
    253 	endhostent();
    254 	return rv;
    255 }
    256 
    257 
    258 		/*
    259 		 * networks
    260 		 */
    261 
    262 static void
    263 networksprint(const struct netent *ne)
    264 {
    265 	char		buf[INET6_ADDRSTRLEN];
    266 	struct	in_addr	ianet;
    267 	int		i;
    268 	char		prefix;
    269 
    270 	assert(ne != NULL);
    271 	ianet = inet_makeaddr(ne->n_net, 0);
    272 	if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
    273 		strlcpy(buf, "# unknown", sizeof(buf));
    274 	printf("%s\t%s",
    275 	    ne->n_name, buf);
    276 	prefix = '\t';
    277 	for (i = 0; ne->n_aliases[i] != NULL; i++) {
    278 		printf("%c%s", prefix, ne->n_aliases[i]);
    279 		prefix = ' ';
    280 	}
    281 	printf("\n");
    282 }
    283 
    284 static int
    285 networks(int argc, char *argv[])
    286 {
    287 	struct netent	*ne;
    288 	in_addr_t	net;
    289 	int		i, rv;
    290 
    291 	assert(argc > 1);
    292 	assert(argv != NULL);
    293 
    294 	setnetent(1);
    295 	rv = RV_OK;
    296 	if (argc == 2) {
    297 		while ((ne = getnetent()) != NULL)
    298 			networksprint(ne);
    299 	} else {
    300 		for (i = 2; i < argc; i++) {
    301 			net = inet_network(argv[i]);
    302 			if (net != INADDR_NONE)
    303 				ne = getnetbyaddr(net, AF_INET);
    304 			else
    305 				ne = getnetbyname(argv[i]);
    306 			if (ne != NULL)
    307 				networksprint(ne);
    308 			else {
    309 				rv = RV_NOTFOUND;
    310 				break;
    311 			}
    312 		}
    313 	}
    314 	endnetent();
    315 	return rv;
    316 }
    317 
    318 
    319 		/*
    320 		 * passwd
    321 		 */
    322 
    323 static void
    324 passwdprint(const struct passwd *pw)
    325 {
    326 
    327 	assert(pw != NULL);
    328 	printf("%s:%s:%u:%u:%s:%s:%s\n",
    329 	    pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
    330 	    pw->pw_gecos, pw->pw_dir, pw->pw_shell);
    331 }
    332 
    333 static int
    334 passwd(int argc, char *argv[])
    335 {
    336 	struct passwd	*pw;
    337 	unsigned long	id;
    338 	int		i, rv;
    339 
    340 	assert(argc > 1);
    341 	assert(argv != NULL);
    342 
    343 	setpassent(1);
    344 	rv = RV_OK;
    345 	if (argc == 2) {
    346 		while ((pw = getpwent()) != NULL)
    347 			passwdprint(pw);
    348 	} else {
    349 		for (i = 2; i < argc; i++) {
    350 			if (parsenum(argv[i], &id))
    351 				pw = getpwuid((uid_t)id);
    352 			else
    353 				pw = getpwnam(argv[i]);
    354 			if (pw != NULL)
    355 				passwdprint(pw);
    356 			else {
    357 				rv = RV_NOTFOUND;
    358 				break;
    359 			}
    360 		}
    361 	}
    362 	endpwent();
    363 	return rv;
    364 }
    365 
    366 
    367 		/*
    368 		 * protocols
    369 		 */
    370 
    371 static void
    372 protocolsprint(const struct protoent *pe)
    373 {
    374 	int		i;
    375 
    376 	assert(pe != NULL);
    377 	printf("%s\t%d", pe->p_name, pe->p_proto);
    378 	for (i = 0; pe->p_aliases[i] != NULL; i++) {
    379 		printf(" %s", pe->p_aliases[i]);
    380 	}
    381 	printf("\n");
    382 }
    383 
    384 static int
    385 protocols(int argc, char *argv[])
    386 {
    387 	struct protoent	*pe;
    388 	unsigned long	id;
    389 	int		i, rv;
    390 
    391 	assert(argc > 1);
    392 	assert(argv != NULL);
    393 
    394 	setprotoent(1);
    395 	rv = RV_OK;
    396 	if (argc == 2) {
    397 		while ((pe = getprotoent()) != NULL)
    398 			protocolsprint(pe);
    399 	} else {
    400 		for (i = 2; i < argc; i++) {
    401 			if (parsenum(argv[i], &id))
    402 				pe = getprotobynumber((int)id);
    403 			else
    404 				pe = getprotobyname(argv[i]);
    405 			if (pe != NULL)
    406 				protocolsprint(pe);
    407 			else {
    408 				rv = RV_NOTFOUND;
    409 				break;
    410 			}
    411 		}
    412 	}
    413 	endprotoent();
    414 	return rv;
    415 }
    416 
    417 
    418 		/*
    419 		 * services
    420 		 */
    421 
    422 static void
    423 servicesprint(const struct servent *se)
    424 {
    425 	int		i;
    426 
    427 	assert(se != NULL);
    428 	printf("%s\t%d/%s", se->s_name, ntohs(se->s_port), se->s_proto);
    429 	for (i = 0; se->s_aliases[i] != NULL; i++) {
    430 		printf(" %s", se->s_aliases[i]);
    431 	}
    432 	printf("\n");
    433 }
    434 
    435 static int
    436 services(int argc, char *argv[])
    437 {
    438 	struct servent	*se;
    439 	unsigned long	id;
    440 	char		*proto;
    441 	int		i, rv;
    442 
    443 	assert(argc > 1);
    444 	assert(argv != NULL);
    445 
    446 	setservent(1);
    447 	rv = RV_OK;
    448 	if (argc == 2) {
    449 		while ((se = getservent()) != NULL)
    450 			servicesprint(se);
    451 	} else {
    452 		for (i = 2; i < argc; i++) {
    453 			proto = strchr(argv[i], '/');
    454 			if (proto != NULL)
    455 				*proto++ = '\0';
    456 			if (parsenum(argv[i], &id))
    457 				se = getservbyport((int)id, proto);
    458 			else
    459 				se = getservbyname(argv[i], proto);
    460 			if (se != NULL)
    461 				servicesprint(se);
    462 			else {
    463 				rv = RV_NOTFOUND;
    464 				break;
    465 			}
    466 		}
    467 	}
    468 	endservent();
    469 	return rv;
    470 }
    471 
    472 
    473 		/*
    474 		 * shells
    475 		 */
    476 
    477 static int
    478 shells(int argc, char *argv[])
    479 {
    480 	const char	*sh;
    481 	int		i, rv;
    482 
    483 	assert(argc > 1);
    484 	assert(argv != NULL);
    485 
    486 	setusershell();
    487 	rv = RV_OK;
    488 	if (argc == 2) {
    489 		while ((sh = getusershell()) != NULL)
    490 			printf("%s\n", sh);
    491 	} else {
    492 		for (i = 2; i < argc; i++) {
    493 			setusershell();
    494 			while ((sh = getusershell()) != NULL) {
    495 				if (strcmp(sh, argv[i]) == 0) {
    496 					printf("%s\n", sh);
    497 					break;
    498 				}
    499 			}
    500 			if (sh == NULL) {
    501 				rv = RV_NOTFOUND;
    502 				break;
    503 			}
    504 		}
    505 	}
    506 	endusershell();
    507 	return rv;
    508 }
    509