getent.c revision 1.1 1 /* $NetBSD: getent.c,v 1.1 2004/11/23 07:35:06 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 __RCSID("$NetBSD: getent.c,v 1.1 2004/11/23 07:35:06 lukem Exp $");
42 #endif /* not lint */
43
44 #include <sys/socket.h>
45
46 #include <assert.h>
47 #include <ctype.h>
48 #include <errno.h>
49 #include <grp.h>
50 #include <limits.h>
51 #include <netdb.h>
52 #include <pwd.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 #include <arpa/inet.h>
59 #include <arpa/nameser.h>
60
61 #include <netinet/in.h> /* for INET6_ADDRSTRLEN */
62
63 static int usage(void);
64 static int parsenum(const char *, unsigned long *);
65 static int group(int, char *[]);
66 static int hosts(int, char *[]);
67 static int passwd(int, char *[]);
68 static int shells(int, char *[]);
69
70 enum {
71 RV_OK = 0,
72 RV_USAGE = 1,
73 RV_NOTFOUND = 2,
74 RV_NOENUM = 3,
75 };
76
77 int
78 main(int argc, char *argv[])
79 {
80 static struct {
81 const char *name;
82 int (*callback)(int, char *[]);
83 } *curdb, dbs[] = {
84 { "group", group, },
85 { "hosts", hosts, },
86 /* networks */
87 { "passwd", passwd, },
88 { "shells", shells, },
89
90 { NULL, NULL, },
91 };
92
93 setprogname(argv[0]);
94
95 if (argc < 2)
96 usage();
97 for (curdb = dbs; curdb->name != NULL; curdb++) {
98 if (strcmp(curdb->name, argv[1]) == 0) {
99 exit(curdb->callback(argc, argv));
100 break;
101 }
102 }
103 fprintf(stderr, "Unknown database: %s\n", argv[1]);
104 usage();
105 /* NOTREACHED */
106 return RV_USAGE;
107 }
108
109 static int
110 usage(void)
111 {
112
113 fprintf(stderr, "Usage: %s database [key ...]\n",
114 getprogname());
115 exit(RV_USAGE);
116 /* NOTREACHED */
117 }
118
119 static int
120 parsenum(const char *word, unsigned long *result)
121 {
122 unsigned long num;
123 char *ep;
124
125 assert(word != NULL);
126 assert(result != NULL);
127
128 if (!isdigit((unsigned char)word[0]))
129 return 0;
130 errno = 0;
131 num = strtoul(word, &ep, 10);
132 if (num == ULONG_MAX && errno == ERANGE)
133 return 0;
134 if (*ep != '\0')
135 return 0;
136 *result = num;
137 return 1;
138 }
139
140
141 /*
142 * group
143 */
144
145 static void
146 groupprint(const struct group *gr)
147 {
148 char prefix;
149 int i;
150
151 assert(gr != NULL);
152 printf("%s:%s:%u",
153 gr->gr_name, gr->gr_passwd, gr->gr_gid);
154 prefix = ':';
155 for (i = 0; gr->gr_mem[i] != NULL; i++) {
156 printf("%c%s", prefix, gr->gr_mem[i]);
157 prefix = ',';
158 }
159 printf("\n");
160 }
161
162 static int
163 group(int argc, char *argv[])
164 {
165 struct group *gr;
166 unsigned long id;
167 int i, rv;
168
169 assert(argc > 1);
170 assert(argv != NULL);
171
172 setgroupent(1);
173 rv = RV_OK;
174 if (argc == 2) {
175 while ((gr = getgrent()) != NULL)
176 groupprint(gr);
177 } else {
178 for (i = 2; i < argc; i++) {
179 if (parsenum(argv[i], &id))
180 gr = getgrgid((gid_t)id);
181 else
182 gr = getgrnam(argv[i]);
183 if (gr != NULL)
184 groupprint(gr);
185 else {
186 rv = RV_NOTFOUND;
187 break;
188 }
189 }
190 }
191 endgrent();
192 return rv;
193 }
194
195 /*
196 * hosts
197 */
198
199 static void
200 hostsprint(const struct hostent *he)
201 {
202 char buf[INET6_ADDRSTRLEN];
203 int i;
204
205 assert(he != NULL);
206 if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
207 strlcpy(buf, "# unknown", sizeof(buf));
208 printf("%s\t%s",
209 buf, he->h_name);
210 for (i = 0; he->h_aliases[i] != NULL; i++) {
211 printf(" %s", he->h_aliases[i]);
212 }
213 printf("\n");
214 }
215
216 static int
217 hosts(int argc, char *argv[])
218 {
219 struct hostent *he;
220 char addr[IN6ADDRSZ];
221 int i, rv;
222
223 assert(argc > 1);
224 assert(argv != NULL);
225
226 sethostent(1);
227 rv = RV_OK;
228 if (argc == 2) {
229 while ((he = gethostent()) != NULL)
230 hostsprint(he);
231 } else {
232 for (i = 2; i < argc; i++) {
233 if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
234 he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
235 else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
236 he = gethostbyaddr(addr, INADDRSZ, AF_INET);
237 else
238 he = gethostbyname(argv[i]);
239 if (he != NULL)
240 hostsprint(he);
241 else {
242 rv = RV_NOTFOUND;
243 break;
244 }
245 }
246 }
247 endhostent();
248 return rv;
249 }
250
251 /*
252 * passwd
253 */
254
255 static void
256 passwdprint(const struct passwd *pw)
257 {
258
259 assert(pw != NULL);
260 printf("%s:%s:%u:%u:%s:%s:%s\n",
261 pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
262 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
263 }
264
265 static int
266 passwd(int argc, char *argv[])
267 {
268 struct passwd *pw;
269 unsigned long id;
270 int i, rv;
271
272 assert(argc > 1);
273 assert(argv != NULL);
274
275 setpassent(1);
276 rv = RV_OK;
277 if (argc == 2) {
278 while ((pw = getpwent()) != NULL)
279 passwdprint(pw);
280 } else {
281 for (i = 2; i < argc; i++) {
282 if (parsenum(argv[i], &id))
283 pw = getpwuid((uid_t)id);
284 else
285 pw = getpwnam(argv[i]);
286 if (pw != NULL)
287 passwdprint(pw);
288 else {
289 rv = RV_NOTFOUND;
290 break;
291 }
292 }
293 }
294 endpwent();
295 return rv;
296 }
297
298 /*
299 * shells
300 */
301
302 static int
303 shells(int argc, char *argv[])
304 {
305 const char *sh;
306 int i, rv;
307
308 assert(argc > 1);
309 assert(argv != NULL);
310
311 setusershell();
312 rv = RV_OK;
313 if (argc == 2) {
314 while ((sh = getusershell()) != NULL)
315 printf("%s\n", sh);
316 } else {
317 for (i = 2; i < argc; i++) {
318 setusershell();
319 while ((sh = getusershell()) != NULL) {
320 if (strcmp(sh, argv[i]) == 0) {
321 printf("%s\n", sh);
322 break;
323 }
324 }
325 if (sh == NULL) {
326 rv = RV_NOTFOUND;
327 break;
328 }
329 }
330 }
331 endusershell();
332 return rv;
333 }
334