]>
Commit | Line | Data |
---|---|---|
32c075e1 | 1 | /* Copyright (c) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. |
7d6a8338 | 2 | This file is part of the GNU C Library. |
ce75c139 | 3 | Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. |
7d6a8338 UD |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
7d6a8338 UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
7d6a8338 | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
7d6a8338 | 19 | |
232b4655 | 20 | /* getent: get entries from administrative database. */ |
7d6a8338 | 21 | |
232b4655 | 22 | #include <aliases.h> |
7d6a8338 | 23 | #include <argp.h> |
7d6a8338 UD |
24 | #include <ctype.h> |
25 | #include <error.h> | |
ff3cacc5 | 26 | #include <grp.h> |
7d6a8338 UD |
27 | #include <libintl.h> |
28 | #include <locale.h> | |
ff3cacc5 | 29 | #include <mcheck.h> |
7d6a8338 | 30 | #include <netdb.h> |
ff3cacc5 UD |
31 | #include <pwd.h> |
32 | #include <shadow.h> | |
7d6a8338 UD |
33 | #include <stdio.h> |
34 | #include <stdlib.h> | |
35 | #include <string.h> | |
7d6a8338 | 36 | #include <arpa/inet.h> |
ce75c139 | 37 | #include <arpa/nameser.h> |
ff3cacc5 UD |
38 | #include <netinet/ether.h> |
39 | #include <netinet/in.h> | |
40 | #include <sys/socket.h> | |
7d6a8338 UD |
41 | |
42 | /* Get libc version number. */ | |
43 | #include <version.h> | |
44 | ||
45 | #define PACKAGE _libc_intl_domainname | |
46 | ||
47 | /* Name and version of program. */ | |
48 | static void print_version (FILE *stream, struct argp_state *state); | |
49 | void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; | |
50 | ||
51 | /* Short description of parameters. */ | |
52 | static const char args_doc[] = N_("database [key ...]"); | |
53 | ||
9d0881aa UD |
54 | /* Supported options. */ |
55 | static const struct argp_option args_options[] = | |
56 | { | |
57 | { "service", 's', "CONFIG", 0, N_("Service configuration to be used") }, | |
58 | { NULL, 0, NULL, 0, NULL }, | |
59 | }; | |
60 | ||
f69425fa UD |
61 | /* Short description of program. */ |
62 | static const char doc[] = N_("Get entries from administrative database.\v\ | |
63 | For bug reporting instructions, please see:\n\ | |
64 | <http://www.gnu.org/software/libc/bugs.html>.\n"); | |
65 | ||
9d0881aa UD |
66 | /* Prototype for option handler. */ |
67 | static error_t parse_option (int key, char *arg, struct argp_state *state); | |
68 | ||
f69425fa UD |
69 | /* Function to print some extra text in the help message. */ |
70 | static char *more_help (int key, const char *text, void *input); | |
71 | ||
7d6a8338 | 72 | /* Data structure to communicate with argp functions. */ |
9d0881aa UD |
73 | static struct argp argp = |
74 | { | |
f69425fa | 75 | args_options, parse_option, args_doc, doc, NULL, more_help |
9d0881aa | 76 | }; |
7d6a8338 UD |
77 | |
78 | /* Print the version information. */ | |
79 | static void | |
80 | print_version (FILE *stream, struct argp_state *state) | |
81 | { | |
82 | fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION); | |
83 | fprintf (stream, gettext ("\ | |
84 | Copyright (C) %s Free Software Foundation, Inc.\n\ | |
85 | This is free software; see the source for copying conditions. There is NO\n\ | |
86 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ | |
32c075e1 | 87 | "), "2006"); |
7d6a8338 UD |
88 | fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk"); |
89 | } | |
90 | ||
232b4655 UD |
91 | /* This is for aliases */ |
92 | static inline void | |
93 | print_aliases (struct aliasent *alias) | |
94 | { | |
95 | unsigned int i = 0; | |
96 | ||
97 | printf ("%s: ", alias->alias_name); | |
98 | for (i = strlen (alias->alias_name); i < 14; ++i) | |
9d0881aa | 99 | fputs_unlocked (" ", stdout); |
232b4655 | 100 | |
9d0881aa | 101 | for (i = 0; i < alias->alias_members_len; ++i) |
232b4655 UD |
102 | printf ("%s%s", |
103 | alias->alias_members [i], | |
104 | i + 1 == alias->alias_members_len ? "\n" : ", "); | |
105 | } | |
106 | ||
107 | static int | |
108 | aliases_keys (int number, char *key[]) | |
109 | { | |
110 | int result = 0; | |
111 | int i; | |
112 | struct aliasent *alias; | |
113 | ||
9d0881aa | 114 | if (number == 0) |
232b4655 UD |
115 | { |
116 | setaliasent (); | |
9d0881aa | 117 | while ((alias = getaliasent ()) != NULL) |
232b4655 UD |
118 | print_aliases (alias); |
119 | endaliasent (); | |
120 | return result; | |
121 | } | |
122 | ||
123 | for (i = 0; i < number; ++i) | |
124 | { | |
125 | alias = getaliasbyname (key[i]); | |
126 | ||
127 | if (alias == NULL) | |
128 | result = 2; | |
129 | else | |
130 | print_aliases (alias); | |
131 | } | |
132 | ||
133 | return result; | |
134 | } | |
135 | ||
136 | /* This is for ethers */ | |
137 | static int | |
138 | ethers_keys (int number, char *key[]) | |
139 | { | |
140 | int result = 0; | |
141 | int i; | |
142 | ||
9d0881aa | 143 | if (number == 0) |
232b4655 UD |
144 | { |
145 | fprintf (stderr, _("Enumeration not supported on %s\n"), "ethers"); | |
146 | return 3; | |
147 | } | |
148 | ||
149 | for (i = 0; i < number; ++i) | |
150 | { | |
151 | struct ether_addr *ethp, eth; | |
152 | char buffer [1024], *p; | |
153 | ||
154 | ethp = ether_aton (key[i]); | |
9d0881aa | 155 | if (ethp != NULL) |
232b4655 UD |
156 | { |
157 | if (ether_ntohost (buffer, ethp)) | |
158 | { | |
159 | result = 2; | |
160 | continue; | |
161 | } | |
162 | p = buffer; | |
163 | } | |
164 | else | |
165 | { | |
166 | if (ether_hostton (key[i], ð)) | |
167 | { | |
168 | result = 2; | |
169 | continue; | |
170 | } | |
171 | p = key[i]; | |
172 | ethp = ð | |
173 | } | |
174 | printf ("%s %s\n", ether_ntoa (ethp), p); | |
175 | } | |
176 | ||
177 | return result; | |
178 | } | |
179 | ||
7d6a8338 UD |
180 | /* This is for group */ |
181 | static inline void | |
182 | print_group (struct group *grp) | |
183 | { | |
184 | unsigned int i = 0; | |
185 | ||
c61a8bb4 | 186 | printf ("%s:%s:%lu:", grp->gr_name ? grp->gr_name : "", |
7d6a8338 | 187 | grp->gr_passwd ? grp->gr_passwd : "", |
9d0881aa | 188 | (unsigned long int) grp->gr_gid); |
7d6a8338 UD |
189 | |
190 | while (grp->gr_mem[i] != NULL) | |
191 | { | |
9d0881aa | 192 | fputs_unlocked (grp->gr_mem[i], stdout); |
7d6a8338 UD |
193 | ++i; |
194 | if (grp->gr_mem[i] != NULL) | |
9d0881aa | 195 | putchar_unlocked (','); |
7d6a8338 | 196 | } |
9d0881aa | 197 | putchar_unlocked ('\n'); |
7d6a8338 UD |
198 | } |
199 | ||
232b4655 | 200 | static int |
7d6a8338 UD |
201 | group_keys (int number, char *key[]) |
202 | { | |
203 | int result = 0; | |
204 | int i; | |
232b4655 | 205 | struct group *grp; |
7d6a8338 | 206 | |
9d0881aa | 207 | if (number == 0) |
7d6a8338 | 208 | { |
232b4655 | 209 | setgrent (); |
9d0881aa | 210 | while ((grp = getgrent ()) != NULL) |
232b4655 UD |
211 | print_group (grp); |
212 | endgrent (); | |
213 | return result; | |
214 | } | |
7d6a8338 | 215 | |
232b4655 UD |
216 | for (i = 0; i < number; ++i) |
217 | { | |
9030e7c4 UD |
218 | errno = 0; |
219 | char *ep; | |
220 | gid_t arg_gid = strtoul(key[i], &ep, 10); | |
8e9b2075 | 221 | |
9030e7c4 UD |
222 | if (errno != EINVAL && *key[i] != '\0' && *ep == '\0') |
223 | /* Valid numeric gid. */ | |
224 | grp = getgrgid (arg_gid); | |
7d6a8338 UD |
225 | else |
226 | grp = getgrnam (key[i]); | |
227 | ||
228 | if (grp == NULL) | |
229 | result = 2; | |
230 | else | |
231 | print_group (grp); | |
232 | } | |
233 | ||
234 | return result; | |
235 | } | |
236 | ||
232b4655 | 237 | /* This is for hosts */ |
25337753 | 238 | static void |
232b4655 UD |
239 | print_hosts (struct hostent *host) |
240 | { | |
fdcd8f9c | 241 | unsigned int cnt; |
232b4655 | 242 | |
fdcd8f9c | 243 | for (cnt = 0; host->h_addr_list[cnt] != NULL; ++cnt) |
232b4655 | 244 | { |
fdcd8f9c UD |
245 | char buf[INET6_ADDRSTRLEN]; |
246 | const char *ip = inet_ntop (host->h_addrtype, host->h_addr_list[cnt], | |
247 | buf, sizeof (buf)); | |
248 | ||
249 | printf ("%-15s %s", ip, host->h_name); | |
250 | ||
251 | unsigned int i; | |
252 | for (i = 0; host->h_aliases[i] != NULL; ++i) | |
253 | { | |
254 | putchar_unlocked (' '); | |
255 | fputs_unlocked (host->h_aliases[i], stdout); | |
256 | } | |
257 | putchar_unlocked ('\n'); | |
232b4655 | 258 | } |
232b4655 UD |
259 | } |
260 | ||
261 | static int | |
262 | hosts_keys (int number, char *key[]) | |
263 | { | |
264 | int result = 0; | |
265 | int i; | |
266 | struct hostent *host; | |
267 | ||
9d0881aa | 268 | if (number == 0) |
232b4655 UD |
269 | { |
270 | sethostent (0); | |
9d0881aa | 271 | while ((host = gethostent ()) != NULL) |
232b4655 UD |
272 | print_hosts (host); |
273 | endhostent (); | |
274 | return result; | |
275 | } | |
276 | ||
277 | for (i = 0; i < number; ++i) | |
278 | { | |
279 | struct hostent *host = NULL; | |
653aeda5 | 280 | char addr[IN6ADDRSZ]; |
232b4655 | 281 | |
653aeda5 | 282 | if (inet_pton (AF_INET6, key[i], &addr) > 0) |
4f3d6536 | 283 | host = gethostbyaddr (addr, IN6ADDRSZ, AF_INET6); |
653aeda5 | 284 | else if (inet_pton (AF_INET, key[i], &addr) > 0) |
4f3d6536 | 285 | host = gethostbyaddr (addr, INADDRSZ, AF_INET); |
232b4655 UD |
286 | else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL) |
287 | host = gethostbyname2 (key[i], AF_INET); | |
288 | ||
289 | if (host == NULL) | |
290 | result = 2; | |
291 | else | |
292 | print_hosts (host); | |
293 | } | |
294 | ||
295 | return result; | |
296 | } | |
297 | ||
29bfc945 UD |
298 | /* This is for hosts, but using getaddrinfo */ |
299 | static int | |
a7d24833 | 300 | ahosts_keys_int (int af, int xflags, int number, char *key[]) |
29bfc945 UD |
301 | { |
302 | int result = 0; | |
303 | int i; | |
304 | struct hostent *host; | |
305 | ||
306 | if (number == 0) | |
307 | { | |
308 | sethostent (0); | |
309 | while ((host = gethostent ()) != NULL) | |
310 | print_hosts (host); | |
311 | endhostent (); | |
312 | return result; | |
313 | } | |
314 | ||
315 | struct addrinfo hint; | |
316 | memset (&hint, '\0', sizeof (hint)); | |
a7d24833 UD |
317 | hint.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME | xflags; |
318 | hint.ai_family = af; | |
29bfc945 UD |
319 | |
320 | for (i = 0; i < number; ++i) | |
321 | { | |
322 | struct addrinfo *res; | |
323 | ||
324 | if (getaddrinfo (key[i], NULL, &hint, &res) != 0) | |
325 | result = 2; | |
326 | else | |
327 | { | |
328 | struct addrinfo *runp = res; | |
329 | ||
330 | while (runp != NULL) | |
331 | { | |
332 | char sockbuf[20]; | |
333 | const char *sockstr; | |
334 | if (runp->ai_socktype == SOCK_STREAM) | |
335 | sockstr = "STREAM"; | |
336 | else if (runp->ai_socktype == SOCK_DGRAM) | |
337 | sockstr = "DGRAM"; | |
338 | else if (runp->ai_socktype == SOCK_RAW) | |
339 | sockstr = "RAW"; | |
340 | else | |
341 | { | |
342 | snprintf (sockbuf, sizeof (sockbuf), "%d", | |
343 | runp->ai_socktype); | |
344 | sockstr = sockbuf; | |
345 | } | |
346 | ||
347 | char buf[INET6_ADDRSTRLEN]; | |
348 | printf ("%-15s %-6s %s\n", | |
349 | inet_ntop (runp->ai_family, | |
a691b217 UD |
350 | runp->ai_family == AF_INET |
351 | ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr | |
352 | : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, | |
29bfc945 UD |
353 | buf, sizeof (buf)), |
354 | sockstr, | |
5c81b3e1 | 355 | runp->ai_canonname ?: ""); |
29bfc945 UD |
356 | |
357 | runp = runp->ai_next; | |
358 | } | |
359 | ||
360 | freeaddrinfo (res); | |
361 | } | |
362 | } | |
363 | ||
364 | return result; | |
365 | } | |
366 | ||
a7d24833 UD |
367 | static int |
368 | ahosts_keys (int number, char *key[]) | |
369 | { | |
370 | return ahosts_keys_int (AF_UNSPEC, 0, number, key); | |
371 | } | |
372 | ||
373 | static int | |
374 | ahostsv4_keys (int number, char *key[]) | |
375 | { | |
376 | return ahosts_keys_int (AF_INET, 0, number, key); | |
377 | } | |
378 | ||
379 | static int | |
380 | ahostsv6_keys (int number, char *key[]) | |
381 | { | |
382 | return ahosts_keys_int (AF_INET6, AI_V4MAPPED, number, key); | |
383 | } | |
384 | ||
232b4655 UD |
385 | /* This is for netgroup */ |
386 | static int | |
387 | netgroup_keys (int number, char *key[]) | |
388 | { | |
389 | int result = 0; | |
9d0881aa | 390 | int i; |
232b4655 | 391 | |
9d0881aa | 392 | if (number == 0) |
232b4655 UD |
393 | { |
394 | fprintf (stderr, _("Enumeration not supported on %s\n"), "netgroup"); | |
395 | return 3; | |
396 | } | |
397 | ||
398 | for (i = 0; i < number; ++i) | |
399 | { | |
400 | if (!setnetgrent (key[i])) | |
401 | result = 2; | |
402 | else | |
403 | { | |
404 | char *p[3]; | |
405 | ||
9d0881aa | 406 | printf ("%-21s", key[i]); |
232b4655 UD |
407 | |
408 | while (getnetgrent (p, p + 1, p + 2)) | |
409 | printf (" (%s, %s, %s)", p[0] ?: " ", p[1] ?: "", p[2] ?: ""); | |
9d0881aa | 410 | putchar_unlocked ('\n'); |
232b4655 UD |
411 | } |
412 | } | |
413 | ||
ff3cacc5 UD |
414 | endnetgrent (); |
415 | ||
232b4655 UD |
416 | return result; |
417 | } | |
418 | ||
7d6a8338 | 419 | /* This is for networks */ |
25337753 | 420 | static void |
7d6a8338 UD |
421 | print_networks (struct netent *net) |
422 | { | |
423 | unsigned int i; | |
424 | struct in_addr ip; | |
425 | ip.s_addr = htonl (net->n_net); | |
426 | ||
9d0881aa | 427 | printf ("%-21s %s", net->n_name, inet_ntoa (ip)); |
7d6a8338 UD |
428 | |
429 | i = 0; | |
430 | while (net->n_aliases[i] != NULL) | |
431 | { | |
9d0881aa UD |
432 | putchar_unlocked (' '); |
433 | fputs_unlocked (net->n_aliases[i], stdout); | |
7d6a8338 UD |
434 | ++i; |
435 | if (net->n_aliases[i] != NULL) | |
9d0881aa | 436 | putchar_unlocked (','); |
7d6a8338 | 437 | } |
9d0881aa | 438 | putchar_unlocked ('\n'); |
7d6a8338 UD |
439 | } |
440 | ||
232b4655 | 441 | static int |
7d6a8338 UD |
442 | networks_keys (int number, char *key[]) |
443 | { | |
444 | int result = 0; | |
445 | int i; | |
232b4655 | 446 | struct netent *net; |
7d6a8338 | 447 | |
9d0881aa | 448 | if (number == 0) |
7d6a8338 | 449 | { |
232b4655 | 450 | setnetent (0); |
9d0881aa | 451 | while ((net = getnetent ()) != NULL) |
232b4655 UD |
452 | print_networks (net); |
453 | endnetent (); | |
454 | return result; | |
455 | } | |
7d6a8338 | 456 | |
232b4655 UD |
457 | for (i = 0; i < number; ++i) |
458 | { | |
7d6a8338 UD |
459 | if (isdigit (key[i][0])) |
460 | net = getnetbyaddr (inet_addr (key[i]), AF_UNIX); | |
461 | else | |
462 | net = getnetbyname (key[i]); | |
463 | ||
464 | if (net == NULL) | |
465 | result = 2; | |
466 | else | |
467 | print_networks (net); | |
468 | } | |
469 | ||
470 | return result; | |
471 | } | |
472 | ||
473 | /* Now is all for passwd */ | |
474 | static inline void | |
475 | print_passwd (struct passwd *pwd) | |
476 | { | |
c61a8bb4 | 477 | printf ("%s:%s:%lu:%lu:%s:%s:%s\n", |
7d6a8338 UD |
478 | pwd->pw_name ? pwd->pw_name : "", |
479 | pwd->pw_passwd ? pwd->pw_passwd : "", | |
9d0881aa UD |
480 | (unsigned long int) pwd->pw_uid, |
481 | (unsigned long int) pwd->pw_gid, | |
7d6a8338 UD |
482 | pwd->pw_gecos ? pwd->pw_gecos : "", |
483 | pwd->pw_dir ? pwd->pw_dir : "", | |
484 | pwd->pw_shell ? pwd->pw_shell : ""); | |
485 | } | |
486 | ||
232b4655 | 487 | static int |
7d6a8338 UD |
488 | passwd_keys (int number, char *key[]) |
489 | { | |
490 | int result = 0; | |
491 | int i; | |
232b4655 | 492 | struct passwd *pwd; |
7d6a8338 | 493 | |
9d0881aa | 494 | if (number == 0) |
7d6a8338 | 495 | { |
232b4655 | 496 | setpwent (); |
9d0881aa | 497 | while ((pwd = getpwent ()) != NULL) |
232b4655 UD |
498 | print_passwd (pwd); |
499 | endpwent (); | |
500 | return result; | |
501 | } | |
7d6a8338 | 502 | |
232b4655 UD |
503 | for (i = 0; i < number; ++i) |
504 | { | |
9030e7c4 UD |
505 | errno = 0; |
506 | char *ep; | |
507 | uid_t arg_uid = strtoul(key[i], &ep, 10); | |
508 | ||
509 | if (errno != EINVAL && *key[i] != '\0' && *ep == '\0') | |
510 | /* Valid numeric uid. */ | |
511 | pwd = getpwuid (arg_uid); | |
7d6a8338 UD |
512 | else |
513 | pwd = getpwnam (key[i]); | |
514 | ||
515 | if (pwd == NULL) | |
516 | result = 2; | |
517 | else | |
518 | print_passwd (pwd); | |
519 | } | |
520 | ||
521 | return result; | |
522 | } | |
523 | ||
524 | /* This is for protocols */ | |
525 | static inline void | |
526 | print_protocols (struct protoent *proto) | |
527 | { | |
528 | unsigned int i; | |
529 | ||
9d0881aa | 530 | printf ("%-21s %d", proto->p_name, proto->p_proto); |
7d6a8338 UD |
531 | |
532 | i = 0; | |
533 | while (proto->p_aliases[i] != NULL) | |
534 | { | |
9d0881aa UD |
535 | putchar_unlocked (' '); |
536 | fputs_unlocked (proto->p_aliases[i], stdout); | |
7d6a8338 UD |
537 | ++i; |
538 | } | |
9d0881aa | 539 | putchar_unlocked ('\n'); |
7d6a8338 UD |
540 | } |
541 | ||
232b4655 | 542 | static int |
7d6a8338 UD |
543 | protocols_keys (int number, char *key[]) |
544 | { | |
545 | int result = 0; | |
546 | int i; | |
232b4655 | 547 | struct protoent *proto; |
7d6a8338 | 548 | |
9d0881aa | 549 | if (number == 0) |
7d6a8338 | 550 | { |
232b4655 | 551 | setprotoent (0); |
9d0881aa | 552 | while ((proto = getprotoent ()) != NULL) |
232b4655 UD |
553 | print_protocols (proto); |
554 | endprotoent (); | |
555 | return result; | |
556 | } | |
7d6a8338 | 557 | |
232b4655 UD |
558 | for (i = 0; i < number; ++i) |
559 | { | |
7d6a8338 UD |
560 | if (isdigit (key[i][0])) |
561 | proto = getprotobynumber (atol (key[i])); | |
562 | else | |
563 | proto = getprotobyname (key[i]); | |
564 | ||
565 | if (proto == NULL) | |
566 | result = 2; | |
567 | else | |
568 | print_protocols (proto); | |
569 | } | |
570 | ||
571 | return result; | |
572 | } | |
573 | ||
232b4655 | 574 | /* Now is all for rpc */ |
7d6a8338 | 575 | static inline void |
232b4655 | 576 | print_rpc (struct rpcent *rpc) |
7d6a8338 | 577 | { |
232b4655 | 578 | int i; |
7d6a8338 | 579 | |
9d0881aa UD |
580 | printf ("%-15s %d%s", |
581 | rpc->r_name, rpc->r_number, rpc->r_aliases[0] ? " " : ""); | |
7d6a8338 | 582 | |
232b4655 UD |
583 | for (i = 0; rpc->r_aliases[i]; ++i) |
584 | printf (" %s", rpc->r_aliases[i]); | |
9d0881aa | 585 | putchar_unlocked ('\n'); |
7d6a8338 UD |
586 | } |
587 | ||
232b4655 UD |
588 | static int |
589 | rpc_keys (int number, char *key[]) | |
7d6a8338 UD |
590 | { |
591 | int result = 0; | |
592 | int i; | |
232b4655 | 593 | struct rpcent *rpc; |
7d6a8338 | 594 | |
9d0881aa | 595 | if (number == 0) |
7d6a8338 | 596 | { |
232b4655 | 597 | setrpcent (0); |
9d0881aa | 598 | while ((rpc = getrpcent ()) != NULL) |
232b4655 UD |
599 | print_rpc (rpc); |
600 | endrpcent (); | |
601 | return result; | |
602 | } | |
7d6a8338 | 603 | |
232b4655 UD |
604 | for (i = 0; i < number; ++i) |
605 | { | |
606 | if (isdigit (key[i][0])) | |
607 | rpc = getrpcbynumber (atol (key[i])); | |
608 | else | |
609 | rpc = getrpcbyname (key[i]); | |
7d6a8338 | 610 | |
232b4655 | 611 | if (rpc == NULL) |
7d6a8338 UD |
612 | result = 2; |
613 | else | |
232b4655 | 614 | print_rpc (rpc); |
7d6a8338 UD |
615 | } |
616 | ||
617 | return result; | |
618 | } | |
619 | ||
620 | /* for services */ | |
232b4655 | 621 | static void |
7d6a8338 UD |
622 | print_services (struct servent *serv) |
623 | { | |
624 | unsigned int i; | |
625 | ||
9d0881aa | 626 | printf ("%-21s %d/%s", serv->s_name, ntohs (serv->s_port), serv->s_proto); |
7d6a8338 UD |
627 | |
628 | i = 0; | |
629 | while (serv->s_aliases[i] != NULL) | |
630 | { | |
9d0881aa UD |
631 | putchar_unlocked (' '); |
632 | fputs_unlocked (serv->s_aliases[i], stdout); | |
7d6a8338 UD |
633 | ++i; |
634 | } | |
9d0881aa | 635 | putchar_unlocked ('\n'); |
7d6a8338 UD |
636 | } |
637 | ||
232b4655 | 638 | static int |
7d6a8338 UD |
639 | services_keys (int number, char *key[]) |
640 | { | |
641 | int result = 0; | |
642 | int i; | |
232b4655 UD |
643 | struct servent *serv; |
644 | ||
645 | if (!number) | |
646 | { | |
647 | setservent (0); | |
9d0881aa | 648 | while ((serv = getservent ()) != NULL) |
232b4655 UD |
649 | print_services (serv); |
650 | endservent (); | |
651 | return result; | |
652 | } | |
7d6a8338 UD |
653 | |
654 | for (i = 0; i < number; ++i) | |
655 | { | |
656 | struct servent *serv; | |
657 | char *proto = strchr (key[i], '/'); | |
658 | ||
a70e964e UD |
659 | if (proto != NULL) |
660 | *proto++ = '\0'; | |
7d6a8338 | 661 | |
a70e964e UD |
662 | if (isdigit (key[i][0])) |
663 | serv = getservbyport (htons (atol (key[i])), proto); | |
664 | else | |
665 | serv = getservbyname (key[i], proto); | |
7d6a8338 | 666 | |
a70e964e UD |
667 | if (serv == NULL) |
668 | result = 2; | |
669 | else | |
670 | print_services (serv); | |
7d6a8338 UD |
671 | } |
672 | ||
673 | return result; | |
674 | } | |
675 | ||
232b4655 | 676 | /* This is for shadow */ |
25337753 | 677 | static void |
232b4655 | 678 | print_shadow (struct spwd *sp) |
7d6a8338 | 679 | { |
232b4655 UD |
680 | printf ("%s:%s:", |
681 | sp->sp_namp ? sp->sp_namp : "", | |
682 | sp->sp_pwdp ? sp->sp_pwdp : ""); | |
683 | ||
9d0881aa UD |
684 | #define SHADOW_FIELD(n) \ |
685 | if (sp->n == -1) \ | |
686 | putchar_unlocked (':'); \ | |
687 | else \ | |
232b4655 UD |
688 | printf ("%ld:", sp->n) |
689 | ||
690 | SHADOW_FIELD (sp_lstchg); | |
691 | SHADOW_FIELD (sp_min); | |
692 | SHADOW_FIELD (sp_max); | |
693 | SHADOW_FIELD (sp_warn); | |
694 | SHADOW_FIELD (sp_inact); | |
695 | SHADOW_FIELD (sp_expire); | |
696 | if (sp->sp_flag == ~0ul) | |
9d0881aa | 697 | putchar_unlocked ('\n'); |
232b4655 UD |
698 | else |
699 | printf ("%lu\n", sp->sp_flag); | |
700 | } | |
7d6a8338 | 701 | |
232b4655 UD |
702 | static int |
703 | shadow_keys (int number, char *key[]) | |
704 | { | |
705 | int result = 0; | |
706 | int i; | |
7d6a8338 | 707 | |
9d0881aa | 708 | if (number == 0) |
7d6a8338 | 709 | { |
232b4655 UD |
710 | struct spwd *sp; |
711 | ||
712 | setspent (); | |
9d0881aa | 713 | while ((sp = getspent ()) != NULL) |
232b4655 UD |
714 | print_shadow (sp); |
715 | endpwent (); | |
716 | return result; | |
7d6a8338 UD |
717 | } |
718 | ||
232b4655 | 719 | for (i = 0; i < number; ++i) |
7d6a8338 | 720 | { |
232b4655 | 721 | struct spwd *sp; |
7d6a8338 | 722 | |
232b4655 | 723 | sp = getspnam (key[i]); |
7d6a8338 | 724 | |
232b4655 UD |
725 | if (sp == NULL) |
726 | result = 2; | |
7d6a8338 | 727 | else |
232b4655 UD |
728 | print_shadow (sp); |
729 | } | |
7d6a8338 | 730 | |
232b4655 UD |
731 | return result; |
732 | } | |
7d6a8338 | 733 | |
232b4655 UD |
734 | struct |
735 | { | |
736 | const char *name; | |
737 | int (*func) (int number, char *key[]); | |
738 | } databases[] = | |
739 | { | |
740 | #define D(name) { #name, name ## _keys }, | |
29bfc945 | 741 | D(ahosts) |
a7d24833 UD |
742 | D(ahostsv4) |
743 | D(ahostsv6) | |
232b4655 UD |
744 | D(aliases) |
745 | D(ethers) | |
746 | D(group) | |
747 | D(hosts) | |
748 | D(netgroup) | |
749 | D(networks) | |
750 | D(passwd) | |
751 | D(protocols) | |
752 | D(rpc) | |
753 | D(services) | |
754 | D(shadow) | |
755 | #undef D | |
9d0881aa | 756 | { NULL, NULL } |
232b4655 UD |
757 | }; |
758 | ||
9d0881aa UD |
759 | /* Handle arguments found by argp. */ |
760 | static error_t | |
761 | parse_option (int key, char *arg, struct argp_state *state) | |
762 | { | |
b4f6f4be | 763 | char *endp; |
9d0881aa UD |
764 | switch (key) |
765 | { | |
766 | case 's': | |
b4f6f4be UD |
767 | endp = strchr (arg, ':'); |
768 | if (endp == NULL) | |
769 | /* No specific database, change them all. */ | |
770 | for (int i = 0; databases[i].name != NULL; ++i) | |
771 | __nss_configure_lookup (databases[i].name, arg); | |
772 | else | |
773 | { | |
774 | int i; | |
775 | for (i = 0; databases[i].name != NULL; ++i) | |
776 | if (strncmp (databases[i].name, arg, endp - arg) == 0) | |
777 | { | |
778 | __nss_configure_lookup (databases[i].name, endp + 1); | |
779 | break; | |
780 | } | |
781 | if (databases[i].name == NULL) | |
782 | error (EXIT_FAILURE, 0, gettext ("Unknown database name")); | |
783 | } | |
9d0881aa UD |
784 | break; |
785 | ||
786 | default: | |
787 | return ARGP_ERR_UNKNOWN; | |
788 | } | |
789 | ||
790 | return 0; | |
791 | } | |
792 | ||
232b4655 | 793 | |
f69425fa UD |
794 | static char * |
795 | more_help (int key, const char *text, void *input) | |
796 | { | |
f69425fa | 797 | switch (key) |
232b4655 | 798 | { |
b4f6f4be UD |
799 | size_t len; |
800 | char *doc; | |
801 | FILE *fp; | |
802 | ||
f69425fa UD |
803 | case ARGP_KEY_HELP_EXTRA: |
804 | /* We print some extra information. */ | |
b4f6f4be UD |
805 | fp = open_memstream (&doc, &len); |
806 | if (fp != NULL) | |
7d6a8338 | 807 | { |
b4f6f4be | 808 | fputs_unlocked (_("Supported databases:\n"), fp); |
f69425fa | 809 | |
b4f6f4be | 810 | for (int i = 0, col = 0; databases[i].name != NULL; ++i) |
7d6a8338 | 811 | { |
f69425fa UD |
812 | len = strlen (databases[i].name); |
813 | if (i != 0) | |
232b4655 | 814 | { |
f69425fa UD |
815 | if (col + len > 72) |
816 | { | |
817 | col = 0; | |
b4f6f4be | 818 | fputc_unlocked ('\n', fp); |
f69425fa UD |
819 | } |
820 | else | |
b4f6f4be | 821 | fputc_unlocked (' ', fp); |
232b4655 | 822 | } |
f69425fa | 823 | |
b4f6f4be | 824 | fputs_unlocked (databases[i].name, fp); |
f69425fa | 825 | col += len + 1; |
7d6a8338 | 826 | } |
232b4655 | 827 | |
b4f6f4be UD |
828 | if (fclose (fp) == 0) |
829 | return doc; | |
7d6a8338 | 830 | } |
f69425fa | 831 | break; |
232b4655 | 832 | |
f69425fa UD |
833 | default: |
834 | break; | |
835 | } | |
836 | return (char *) text; | |
232b4655 UD |
837 | } |
838 | ||
f69425fa | 839 | |
232b4655 UD |
840 | /* the main function */ |
841 | int | |
842 | main (int argc, char *argv[]) | |
843 | { | |
ff3cacc5 UD |
844 | /* Debugging support. */ |
845 | mtrace (); | |
232b4655 UD |
846 | |
847 | /* Set locale via LC_ALL. */ | |
848 | setlocale (LC_ALL, ""); | |
849 | /* Set the text message domain. */ | |
850 | textdomain (PACKAGE); | |
851 | ||
232b4655 | 852 | /* Parse and process arguments. */ |
ff3cacc5 | 853 | int remaining; |
232b4655 UD |
854 | argp_parse (&argp, argc, argv, 0, &remaining, NULL); |
855 | ||
856 | if ((argc - remaining) < 1) | |
857 | { | |
858 | error (0, 0, gettext ("wrong number of arguments")); | |
7d6a8338 UD |
859 | argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name); |
860 | return 1; | |
861 | } | |
862 | ||
ff3cacc5 | 863 | for (int i = 0; databases[i].name; ++i) |
9d0881aa UD |
864 | if (argv[remaining][0] == databases[i].name[0] |
865 | && !strcmp (argv[remaining], databases[i].name)) | |
866 | return databases[i].func (argc - remaining - 1, &argv[remaining + 1]); | |
232b4655 | 867 | |
9d0881aa | 868 | fprintf (stderr, _("Unknown database: %s\n"), argv[remaining]); |
232b4655 UD |
869 | argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name); |
870 | return 1; | |
7d6a8338 | 871 | } |