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