Annotation of src/usr.bin/getent/getent.c, Revision 1.15
1.15 ! mestre 1: /* $OpenBSD: getent.c,v 1.14 2016/02/01 19:57:28 jca 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>
1.10 doug 37: #include <err.h>
1.1 otto 38: #include <errno.h>
39: #include <grp.h>
40: #include <limits.h>
41: #include <netdb.h>
42: #include <pwd.h>
43: #include <stdio.h>
44: #include <stdarg.h>
45: #include <stdlib.h>
46: #include <string.h>
47: #include <unistd.h>
48:
49: #include <net/if.h>
50: #include <netinet/in.h> /* for INET6_ADDRSTRLEN */
51: #include <netinet/if_ether.h>
1.3 millert 52:
53: #include <arpa/inet.h>
54: #include <arpa/nameser.h>
1.1 otto 55:
56: #include <rpc/rpc.h>
57:
58: static int usage(void);
59: static int ethers(int, char *[]);
60: static int group(int, char *[]);
61: static int hosts(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.10 doug 79: const char *pledge;
1.1 otto 80: } databases[] = {
1.10 doug 81: { "ethers", ethers, "stdio rpath" },
1.12 doug 82: { "group", group, "stdio getpw" },
1.10 doug 83: { "hosts", hosts, "stdio dns" },
1.12 doug 84: { "passwd", passwd, "stdio getpw" },
1.10 doug 85: { "protocols", protocols, "stdio rpath" },
86: { "rpc", rpc, "stdio rpath" },
87: { "services", services, "stdio rpath" },
88: { "shells", shells, "stdio rpath" },
1.1 otto 89:
1.10 doug 90: { NULL, NULL, },
1.1 otto 91: };
92:
93: int
94: main(int argc, char *argv[])
95: {
96: struct getentdb *curdb;
1.10 doug 97:
1.1 otto 98: if (argc < 2)
99: usage();
100: for (curdb = databases; curdb->name != NULL; curdb++) {
101: if (strcmp(curdb->name, argv[1]) == 0) {
1.10 doug 102: if (pledge(curdb->pledge, NULL) == -1)
103: err(1, "pledge");
104:
1.2 deraadt 105: exit(curdb->fn(argc, argv));
1.1 otto 106: break;
107: }
108: }
1.2 deraadt 109: fprintf(stderr, "%s: unknown database: %s\n", __progname, argv[1]);
1.1 otto 110: return RV_USAGE;
111: }
112:
113: static int
114: usage(void)
115: {
1.2 deraadt 116: fprintf(stderr, "usage: %s database [key ...]\n", __progname);
1.1 otto 117: exit(RV_USAGE);
118: /* NOTREACHED */
119: }
120:
121: /*
122: * printfmtstrings --
123: * vprintf(format, ...),
124: * then the aliases (beginning with prefix, separated by sep),
125: * then a newline
126: */
127: static void
128: printfmtstrings(char *strings[], const char *prefix, const char *sep,
129: const char *fmt, ...)
130: {
131: va_list ap;
132: const char *curpref;
133: int i;
134:
135: va_start(ap, fmt);
136: vprintf(fmt, ap);
1.2 deraadt 137: va_end(ap);
1.1 otto 138:
139: curpref = prefix;
140: for (i = 0; strings[i] != NULL; i++) {
141: printf("%s%s", curpref, strings[i]);
142: curpref = sep;
143: }
144: printf("\n");
145: }
146:
1.2 deraadt 147: #define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp)
1.1 otto 148:
149: static int
150: ethers(int argc, char *argv[])
151: {
1.9 deraadt 152: char hostname[HOST_NAME_MAX+1], *hp;
1.2 deraadt 153: int i, rv = RV_OK;
1.1 otto 154: struct ether_addr ea, *eap;
155:
156: if (argc == 2) {
1.2 deraadt 157: fprintf(stderr, "%s: Enumeration not supported on ethers\n",
158: __progname);
1.1 otto 159: rv = RV_NOENUM;
160: } else {
161: for (i = 2; i < argc; i++) {
162: if ((eap = ether_aton(argv[i])) == NULL) {
163: eap = &ea;
164: hp = argv[i];
165: if (ether_hostton(hp, eap) != 0) {
166: rv = RV_NOTFOUND;
167: break;
168: }
169: } else {
170: hp = hostname;
171: if (ether_ntohost(hp, eap) != 0) {
172: rv = RV_NOTFOUND;
173: break;
174: }
175: }
176: ETHERSPRINT;
177: }
178: }
179: return rv;
180: }
181:
1.2 deraadt 182: #define GROUPPRINT \
183: printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \
184: gr->gr_name, gr->gr_passwd, gr->gr_gid)
1.1 otto 185:
186: static int
187: group(int argc, char *argv[])
188: {
1.2 deraadt 189: int i, rv = RV_OK;
1.1 otto 190: struct group *gr;
191:
192: setgroupent(1);
193: if (argc == 2) {
194: while ((gr = getgrent()) != NULL)
195: GROUPPRINT;
196: } else {
197: for (i = 2; i < argc; i++) {
1.2 deraadt 198: const char *err;
199: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
200:
201: if (!err)
1.1 otto 202: gr = getgrgid((gid_t)id);
203: else
204: gr = getgrnam(argv[i]);
205: if (gr != NULL)
206: GROUPPRINT;
207: else {
208: rv = RV_NOTFOUND;
209: break;
210: }
211: }
212: }
213: endgrent();
214: return rv;
215: }
216:
217: static void
218: hostsprint(const struct hostent *he)
219: {
220: char buf[INET6_ADDRSTRLEN];
221:
222: if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
223: strlcpy(buf, "# unknown", sizeof(buf));
224: printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
225: }
1.6 florian 226: static int
227: hostsaddrinfo(char* name)
228: {
229: struct addrinfo hints, *res, *res0;
230: void *src;
231: int rv;
232: char buf[INET6_ADDRSTRLEN];
233:
234: rv = RV_NOTFOUND;
235: memset(buf, 0, sizeof(buf));
236: memset(&hints, 0, sizeof(hints));
237: hints.ai_family = PF_UNSPEC;
238: hints.ai_socktype = SOCK_DGRAM;
239:
240: if (getaddrinfo(name, NULL, &hints, &res0) == 0) {
241: for (res = res0; res; res = res->ai_next) {
242: switch (res->ai_family) {
243: case AF_INET:
244: src = &((struct sockaddr_in*)
245: res->ai_addr)->sin_addr;
246: break;
247: case AF_INET6:
248: src = &((struct sockaddr_in6*)
249: res->ai_addr)->sin6_addr;
250: break;
251: default: /* not reached */
252: src = NULL;
253: }
254: if (src==NULL || inet_ntop(res->ai_family, src, buf,
255: sizeof(buf)) == NULL)
256: strlcpy(buf, "# unknown", sizeof(buf));
257: else
258: rv = RV_OK;
259: printf("%-39s %s\n", buf, name);
260: }
261: freeaddrinfo(res0);
262: }
263:
264: return (rv);
265: }
1.1 otto 266:
267: static int
268: hosts(int argc, char *argv[])
269: {
1.2 deraadt 270: char addr[IN6ADDRSZ];
271: int i, rv = RV_OK;
1.1 otto 272: struct hostent *he;
273:
274: if (argc == 2) {
1.7 schwarze 275: fprintf(stderr, "%s: Enumeration not supported on hosts\n",
276: __progname);
277: rv = RV_NOENUM;
1.1 otto 278: } else {
279: for (i = 2; i < argc; i++) {
1.6 florian 280: he = NULL;
1.1 otto 281: if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
282: he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
283: else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
284: he = gethostbyaddr(addr, INADDRSZ, AF_INET);
285: if (he != NULL)
286: hostsprint(he);
1.6 florian 287: else if ((rv = hostsaddrinfo(argv[i])) == RV_NOTFOUND)
1.1 otto 288: break;
289: }
290: }
291: return rv;
292: }
293:
1.2 deraadt 294: #define PASSWDPRINT \
295: printf("%s:%s:%u:%u:%s:%s:%s\n", \
296: pw->pw_name, pw->pw_passwd, pw->pw_uid, \
297: pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell)
1.1 otto 298:
299: static int
300: passwd(int argc, char *argv[])
301: {
1.2 deraadt 302: int i, rv = RV_OK;
1.1 otto 303: struct passwd *pw;
304:
305: setpassent(1);
306: if (argc == 2) {
307: while ((pw = getpwent()) != NULL)
308: PASSWDPRINT;
309: } else {
310: for (i = 2; i < argc; i++) {
1.2 deraadt 311: const char *err;
312: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
313:
314: if (!err)
1.1 otto 315: pw = getpwuid((uid_t)id);
316: else
317: pw = getpwnam(argv[i]);
318: if (pw != NULL)
319: PASSWDPRINT;
320: else {
321: rv = RV_NOTFOUND;
322: break;
323: }
324: }
325: }
326: endpwent();
327: return rv;
328: }
329:
1.2 deraadt 330: #define PROTOCOLSPRINT \
331: printfmtstrings(pe->p_aliases, " ", " ", \
332: "%-16s %5d", pe->p_name, pe->p_proto)
1.1 otto 333:
334: static int
335: protocols(int argc, char *argv[])
336: {
337: struct protoent *pe;
1.2 deraadt 338: int i, rv = RV_OK;
1.1 otto 339:
340: setprotoent(1);
341: if (argc == 2) {
342: while ((pe = getprotoent()) != NULL)
343: PROTOCOLSPRINT;
344: } else {
345: for (i = 2; i < argc; i++) {
1.2 deraadt 346: const char *err;
347: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
348:
349: if (!err)
1.1 otto 350: pe = getprotobynumber((int)id);
351: else
352: pe = getprotobyname(argv[i]);
353: if (pe != NULL)
354: PROTOCOLSPRINT;
355: else {
356: rv = RV_NOTFOUND;
357: break;
358: }
359: }
360: }
361: endprotoent();
362: return rv;
363: }
364:
1.2 deraadt 365: #define RPCPRINT \
366: printfmtstrings(re->r_aliases, " ", " ", \
367: "%-16s %6d", re->r_name, re->r_number)
1.1 otto 368:
369: static int
370: rpc(int argc, char *argv[])
371: {
372: struct rpcent *re;
1.2 deraadt 373: int i, rv = RV_OK;
1.1 otto 374:
375: setrpcent(1);
376: if (argc == 2) {
377: while ((re = getrpcent()) != NULL)
378: RPCPRINT;
379: } else {
380: for (i = 2; i < argc; i++) {
1.2 deraadt 381: const char *err;
382: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
383:
384: if (!err)
1.1 otto 385: re = getrpcbynumber((int)id);
386: else
387: re = getrpcbyname(argv[i]);
388: if (re != NULL)
389: RPCPRINT;
390: else {
391: rv = RV_NOTFOUND;
392: break;
393: }
394: }
395: }
396: endrpcent();
397: return rv;
398: }
399:
1.2 deraadt 400: #define SERVICESPRINT \
401: printfmtstrings(se->s_aliases, " ", " ", \
402: "%-16s %5d/%s", se->s_name, ntohs(se->s_port), se->s_proto)
1.1 otto 403:
404: static int
405: services(int argc, char *argv[])
406: {
407: struct servent *se;
1.2 deraadt 408: int i, rv = RV_OK;
1.1 otto 409:
410: setservent(1);
411: if (argc == 2) {
412: while ((se = getservent()) != NULL)
413: SERVICESPRINT;
414: } else {
415: for (i = 2; i < argc; i++) {
1.2 deraadt 416: const char *err;
417: long long id;
418: char *proto = strchr(argv[i], '/');
419:
1.1 otto 420: if (proto != NULL)
421: *proto++ = '\0';
1.2 deraadt 422: id = strtonum(argv[i], 0, UINT_MAX, &err);
423: if (!err)
1.4 otto 424: se = getservbyport(htons((u_short)id), proto);
1.1 otto 425: else
426: se = getservbyname(argv[i], proto);
427: if (se != NULL)
428: SERVICESPRINT;
429: else {
430: rv = RV_NOTFOUND;
431: break;
432: }
433: }
434: }
435: endservent();
436: return rv;
437: }
438:
1.14 jca 439: #define SHELLSPRINT printf("%s\n", sh)
440:
1.1 otto 441: static int
442: shells(int argc, char *argv[])
443: {
444: const char *sh;
1.2 deraadt 445: int i, rv = RV_OK;
1.1 otto 446:
447: setusershell();
448: if (argc == 2) {
449: while ((sh = getusershell()) != NULL)
1.14 jca 450: SHELLSPRINT;
1.1 otto 451: } else {
452: for (i = 2; i < argc; i++) {
453: setusershell();
454: while ((sh = getusershell()) != NULL) {
455: if (strcmp(sh, argv[i]) == 0) {
1.14 jca 456: SHELLSPRINT;
1.1 otto 457: break;
458: }
459: }
460: if (sh == NULL) {
461: rv = RV_NOTFOUND;
462: break;
463: }
464: }
465: }
466: endusershell();
467: return rv;
468: }