]> git.ipfire.org Git - thirdparty/glibc.git/blame - nss/getent.c
[BZ #2510, BZ #2830, BZ #3137, BZ #3313, BZ #3426, BZ #3465, BZ #3480, BZ #3483,...
[thirdparty/glibc.git] / nss / getent.c
CommitLineData
11bf311e 1/* Copyright (c) 1998-2006, 2007 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. */
48static void print_version (FILE *stream, struct argp_state *state);
49void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
50
51/* Short description of parameters. */
52static const char args_doc[] = N_("database [key ...]");
53
9d0881aa
UD
54/* Supported options. */
55static 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. */
62static const char doc[] = N_("Get entries from administrative database.\v\
63For bug reporting instructions, please see:\n\
64<http://www.gnu.org/software/libc/bugs.html>.\n");
65
9d0881aa
UD
66/* Prototype for option handler. */
67static 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. */
70static char *more_help (int key, const char *text, void *input);
71
7d6a8338 72/* Data structure to communicate with argp functions. */
9d0881aa
UD
73static 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. */
79static void
80print_version (FILE *stream, struct argp_state *state)
81{
82 fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION);
83 fprintf (stream, gettext ("\
84Copyright (C) %s Free Software Foundation, Inc.\n\
85This is free software; see the source for copying conditions. There is NO\n\
86warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
11bf311e 87"), "2007");
7d6a8338
UD
88 fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
89}
90
232b4655
UD
91/* This is for aliases */
92static inline void
93print_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
107static int
108aliases_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 */
137static int
138ethers_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], &eth))
167 {
168 result = 2;
169 continue;
170 }
171 p = key[i];
172 ethp = &eth;
173 }
174 printf ("%s %s\n", ether_ntoa (ethp), p);
175 }
176
177 return result;
178}
179
7d6a8338
UD
180/* This is for group */
181static inline void
182print_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 200static int
7d6a8338
UD
201group_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 238static void
232b4655
UD
239print_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
261static int
262hosts_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 */
299static int
a7d24833 300ahosts_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
367static int
368ahosts_keys (int number, char *key[])
369{
370 return ahosts_keys_int (AF_UNSPEC, 0, number, key);
371}
372
373static int
374ahostsv4_keys (int number, char *key[])
375{
376 return ahosts_keys_int (AF_INET, 0, number, key);
377}
378
379static int
380ahostsv6_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 */
386static int
387netgroup_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 420static void
7d6a8338
UD
421print_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 441static int
7d6a8338
UD
442networks_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 */
474static inline void
475print_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 487static int
7d6a8338
UD
488passwd_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 */
525static inline void
526print_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 542static int
7d6a8338
UD
543protocols_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 575static inline void
232b4655 576print_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
588static int
589rpc_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 621static void
7d6a8338
UD
622print_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 638static int
7d6a8338
UD
639services_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 677static void
232b4655 678print_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
702static int
703shadow_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
734struct
735 {
736 const char *name;
737 int (*func) (int number, char *key[]);
738 } databases[] =
739 {
740#define D(name) { #name, name ## _keys },
29bfc945 741D(ahosts)
a7d24833
UD
742D(ahostsv4)
743D(ahostsv6)
232b4655
UD
744D(aliases)
745D(ethers)
746D(group)
747D(hosts)
748D(netgroup)
749D(networks)
750D(passwd)
751D(protocols)
752D(rpc)
753D(services)
754D(shadow)
755#undef D
9d0881aa 756 { NULL, NULL }
232b4655
UD
757 };
758
9d0881aa
UD
759/* Handle arguments found by argp. */
760static error_t
761parse_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
794static char *
795more_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 */
841int
842main (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}