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