Annotation of src/usr.bin/getent/getent.c, Revision 1.5
1.5 ! ray 1: /* $OpenBSD: getent.c,v 1.4 2006/05/07 21:18:55 otto 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: }
223:
224: static int
225: hosts(int argc, char *argv[])
226: {
1.2 deraadt 227: char addr[IN6ADDRSZ];
228: int i, rv = RV_OK;
1.1 otto 229: struct hostent *he;
230:
231: sethostent(1);
232: if (argc == 2) {
233: while ((he = gethostent()) != NULL)
234: hostsprint(he);
235: } else {
236: for (i = 2; i < argc; i++) {
237: if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
238: he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
239: else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
240: he = gethostbyaddr(addr, INADDRSZ, AF_INET);
241: else
242: he = gethostbyname(argv[i]);
243: if (he != NULL)
244: hostsprint(he);
245: else {
246: rv = RV_NOTFOUND;
247: break;
248: }
249: }
250: }
251: endhostent();
252: return rv;
253: }
254:
255: static void
256: networksprint(const struct netent *ne)
257: {
258: char buf[INET6_ADDRSTRLEN];
1.2 deraadt 259: struct in_addr ianet;
1.1 otto 260:
261: ianet = inet_makeaddr(ne->n_net, 0);
262: if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
263: strlcpy(buf, "# unknown", sizeof(buf));
264: printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
265: }
266:
267: static int
268: networks(int argc, char *argv[])
269: {
1.2 deraadt 270: int i, rv = RV_OK;
1.1 otto 271: struct netent *ne;
272: in_addr_t net;
273:
274: setnetent(1);
275: if (argc == 2) {
276: while ((ne = getnetent()) != NULL)
277: networksprint(ne);
278: } else {
279: for (i = 2; i < argc; i++) {
280: net = inet_network(argv[i]);
281: if (net != INADDR_NONE)
282: ne = getnetbyaddr(net, AF_INET);
283: else
284: ne = getnetbyname(argv[i]);
285: if (ne != NULL)
286: networksprint(ne);
287: else {
288: rv = RV_NOTFOUND;
289: break;
290: }
291: }
292: }
293: endnetent();
294: return rv;
295: }
296:
1.2 deraadt 297: #define PASSWDPRINT \
298: printf("%s:%s:%u:%u:%s:%s:%s\n", \
299: pw->pw_name, pw->pw_passwd, pw->pw_uid, \
300: pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell)
1.1 otto 301:
302: static int
303: passwd(int argc, char *argv[])
304: {
1.2 deraadt 305: int i, rv = RV_OK;
1.1 otto 306: struct passwd *pw;
307:
308: setpassent(1);
309: if (argc == 2) {
310: while ((pw = getpwent()) != NULL)
311: PASSWDPRINT;
312: } else {
313: for (i = 2; i < argc; i++) {
1.2 deraadt 314: const char *err;
315: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
316:
317: if (!err)
1.1 otto 318: pw = getpwuid((uid_t)id);
319: else
320: pw = getpwnam(argv[i]);
321: if (pw != NULL)
322: PASSWDPRINT;
323: else {
324: rv = RV_NOTFOUND;
325: break;
326: }
327: }
328: }
329: endpwent();
330: return rv;
331: }
332:
1.2 deraadt 333: #define PROTOCOLSPRINT \
334: printfmtstrings(pe->p_aliases, " ", " ", \
335: "%-16s %5d", pe->p_name, pe->p_proto)
1.1 otto 336:
337: static int
338: protocols(int argc, char *argv[])
339: {
340: struct protoent *pe;
1.2 deraadt 341: int i, rv = RV_OK;
1.1 otto 342:
343: setprotoent(1);
344: if (argc == 2) {
345: while ((pe = getprotoent()) != NULL)
346: PROTOCOLSPRINT;
347: } else {
348: for (i = 2; i < argc; i++) {
1.2 deraadt 349: const char *err;
350: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
351:
352: if (!err)
1.1 otto 353: pe = getprotobynumber((int)id);
354: else
355: pe = getprotobyname(argv[i]);
356: if (pe != NULL)
357: PROTOCOLSPRINT;
358: else {
359: rv = RV_NOTFOUND;
360: break;
361: }
362: }
363: }
364: endprotoent();
365: return rv;
366: }
367:
1.2 deraadt 368: #define RPCPRINT \
369: printfmtstrings(re->r_aliases, " ", " ", \
370: "%-16s %6d", re->r_name, re->r_number)
1.1 otto 371:
372: static int
373: rpc(int argc, char *argv[])
374: {
375: struct rpcent *re;
1.2 deraadt 376: int i, rv = RV_OK;
1.1 otto 377:
378: setrpcent(1);
379: if (argc == 2) {
380: while ((re = getrpcent()) != NULL)
381: RPCPRINT;
382: } else {
383: for (i = 2; i < argc; i++) {
1.2 deraadt 384: const char *err;
385: long long id = strtonum(argv[i], 0, UINT_MAX, &err);
386:
387: if (!err)
1.1 otto 388: re = getrpcbynumber((int)id);
389: else
390: re = getrpcbyname(argv[i]);
391: if (re != NULL)
392: RPCPRINT;
393: else {
394: rv = RV_NOTFOUND;
395: break;
396: }
397: }
398: }
399: endrpcent();
400: return rv;
401: }
402:
1.2 deraadt 403: #define SERVICESPRINT \
404: printfmtstrings(se->s_aliases, " ", " ", \
405: "%-16s %5d/%s", se->s_name, ntohs(se->s_port), se->s_proto)
1.1 otto 406:
407: static int
408: services(int argc, char *argv[])
409: {
410: struct servent *se;
1.2 deraadt 411: int i, rv = RV_OK;
1.1 otto 412:
413: setservent(1);
414: if (argc == 2) {
415: while ((se = getservent()) != NULL)
416: SERVICESPRINT;
417: } else {
418: for (i = 2; i < argc; i++) {
1.2 deraadt 419: const char *err;
420: long long id;
421: char *proto = strchr(argv[i], '/');
422:
1.1 otto 423: if (proto != NULL)
424: *proto++ = '\0';
1.2 deraadt 425: id = strtonum(argv[i], 0, UINT_MAX, &err);
426: if (!err)
1.4 otto 427: se = getservbyport(htons((u_short)id), proto);
1.1 otto 428: else
429: se = getservbyname(argv[i], proto);
430: if (se != NULL)
431: SERVICESPRINT;
432: else {
433: rv = RV_NOTFOUND;
434: break;
435: }
436: }
437: }
438: endservent();
439: return rv;
440: }
441:
1.2 deraadt 442: #define SHELLSPRINT printf("%s\n", sh)
1.1 otto 443:
444: static int
445: shells(int argc, char *argv[])
446: {
447: const char *sh;
1.2 deraadt 448: int i, rv = RV_OK;
1.1 otto 449:
450: setusershell();
451: if (argc == 2) {
452: while ((sh = getusershell()) != NULL)
453: SHELLSPRINT;
454: } else {
455: for (i = 2; i < argc; i++) {
456: setusershell();
457: while ((sh = getusershell()) != NULL) {
458: if (strcmp(sh, argv[i]) == 0) {
459: SHELLSPRINT;
460: break;
461: }
462: }
463: if (sh == NULL) {
464: rv = RV_NOTFOUND;
465: break;
466: }
467: }
468: }
469: endusershell();
470: return rv;
471: }