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