Fix jn precision
[glibc.git] / nss / getent.c
blob9d43e2f65670a7657ecc42cf3bb3e93dd175625b
1 /* Copyright (c) 1998-2008, 2009, 2010, 2011 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
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. */
20 /* getent: get entries from administrative database. */
22 #include <aliases.h>
23 #include <argp.h>
24 #include <ctype.h>
25 #include <error.h>
26 #include <grp.h>
27 #include <gshadow.h>
28 #include <libintl.h>
29 #include <locale.h>
30 #include <mcheck.h>
31 #include <netdb.h>
32 #include <pwd.h>
33 #include <shadow.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <arpa/inet.h>
39 #include <arpa/nameser.h>
40 #include <netinet/ether.h>
41 #include <netinet/in.h>
42 #include <sys/socket.h>
44 /* Get libc version number. */
45 #include <version.h>
47 #define PACKAGE _libc_intl_domainname
49 /* Name and version of program. */
50 static void print_version (FILE *stream, struct argp_state *state);
51 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
53 /* Short description of parameters. */
54 static const char args_doc[] = N_("database [key ...]");
56 /* Supported options. */
57 static const struct argp_option args_options[] =
59 { "service", 's', "CONFIG", 0, N_("Service configuration to be used") },
60 { "no-idn", 'i', NULL, 0, N_("disable IDN encoding") },
61 { NULL, 0, NULL, 0, NULL },
64 /* Short description of program. */
65 static const char doc[] = N_("Get entries from administrative database.");
67 /* Prototype for option handler. */
68 static error_t parse_option (int key, char *arg, struct argp_state *state);
70 /* Function to print some extra text in the help message. */
71 static char *more_help (int key, const char *text, void *input);
73 /* Data structure to communicate with argp functions. */
74 static struct argp argp =
76 args_options, parse_option, args_doc, doc, NULL, more_help
79 /* Additional getaddrinfo flags for IDN encoding. */
80 static int idn_flags = AI_IDN | AI_CANONIDN;
82 /* Print the version information. */
83 static void
84 print_version (FILE *stream, struct argp_state *state)
86 fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION);
87 fprintf (stream, gettext ("\
88 Copyright (C) %s Free Software Foundation, Inc.\n\
89 This is free software; see the source for copying conditions. There is NO\n\
90 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
91 "), "2011");
92 fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
95 /* This is for aliases */
96 static inline void
97 print_aliases (struct aliasent *alias)
99 unsigned int i = 0;
101 printf ("%s: ", alias->alias_name);
102 for (i = strlen (alias->alias_name); i < 14; ++i)
103 fputs_unlocked (" ", stdout);
105 for (i = 0; i < alias->alias_members_len; ++i)
106 printf ("%s%s",
107 alias->alias_members [i],
108 i + 1 == alias->alias_members_len ? "\n" : ", ");
111 static int
112 aliases_keys (int number, char *key[])
114 int result = 0;
115 int i;
116 struct aliasent *alias;
118 if (number == 0)
120 setaliasent ();
121 while ((alias = getaliasent ()) != NULL)
122 print_aliases (alias);
123 endaliasent ();
124 return result;
127 for (i = 0; i < number; ++i)
129 alias = getaliasbyname (key[i]);
131 if (alias == NULL)
132 result = 2;
133 else
134 print_aliases (alias);
137 return result;
140 /* This is for ethers */
141 static int
142 ethers_keys (int number, char *key[])
144 int result = 0;
145 int i;
147 if (number == 0)
149 fprintf (stderr, _("Enumeration not supported on %s\n"), "ethers");
150 return 3;
153 for (i = 0; i < number; ++i)
155 struct ether_addr *ethp, eth;
156 char buffer [1024], *p;
158 ethp = ether_aton (key[i]);
159 if (ethp != NULL)
161 if (ether_ntohost (buffer, ethp))
163 result = 2;
164 continue;
166 p = buffer;
168 else
170 if (ether_hostton (key[i], &eth))
172 result = 2;
173 continue;
175 p = key[i];
176 ethp = &eth;
178 printf ("%s %s\n", ether_ntoa (ethp), p);
181 return result;
184 /* This is for group */
185 static inline void
186 print_group (struct group *grp)
188 unsigned int i = 0;
190 printf ("%s:%s:%lu:", grp->gr_name ? grp->gr_name : "",
191 grp->gr_passwd ? grp->gr_passwd : "",
192 (unsigned long int) grp->gr_gid);
194 while (grp->gr_mem[i] != NULL)
196 fputs_unlocked (grp->gr_mem[i], stdout);
197 ++i;
198 if (grp->gr_mem[i] != NULL)
199 putchar_unlocked (',');
201 putchar_unlocked ('\n');
204 static int
205 group_keys (int number, char *key[])
207 int result = 0;
208 int i;
209 struct group *grp;
211 if (number == 0)
213 setgrent ();
214 while ((grp = getgrent ()) != NULL)
215 print_group (grp);
216 endgrent ();
217 return result;
220 for (i = 0; i < number; ++i)
222 errno = 0;
223 char *ep;
224 gid_t arg_gid = strtoul(key[i], &ep, 10);
226 if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
227 /* Valid numeric gid. */
228 grp = getgrgid (arg_gid);
229 else
230 grp = getgrnam (key[i]);
232 if (grp == NULL)
233 result = 2;
234 else
235 print_group (grp);
238 return result;
241 /* This is for gshadow */
242 static void
243 print_gshadow (struct sgrp *sg)
245 unsigned int i = 0;
247 printf ("%s:%s:",
248 sg->sg_namp ? sg->sg_namp : "",
249 sg->sg_passwd ? sg->sg_passwd : "");
251 while (sg->sg_adm[i] != NULL)
253 fputs_unlocked (sg->sg_adm[i], stdout);
254 ++i;
255 if (sg->sg_adm[i] != NULL)
256 putchar_unlocked (',');
259 putchar_unlocked (':');
261 i = 0;
262 while (sg->sg_mem[i] != NULL)
264 fputs_unlocked (sg->sg_mem[i], stdout);
265 ++i;
266 if (sg->sg_mem[i] != NULL)
267 putchar_unlocked (',');
270 putchar_unlocked ('\n');
273 static int
274 gshadow_keys (int number, char *key[])
276 int result = 0;
277 int i;
279 if (number == 0)
281 struct sgrp *sg;
283 setsgent ();
284 while ((sg = getsgent ()) != NULL)
285 print_gshadow (sg);
286 endsgent ();
287 return result;
290 for (i = 0; i < number; ++i)
292 struct sgrp *sg;
294 sg = getsgnam (key[i]);
296 if (sg == NULL)
297 result = 2;
298 else
299 print_gshadow (sg);
302 return result;
305 /* This is for hosts */
306 static void
307 print_hosts (struct hostent *host)
309 unsigned int cnt;
311 for (cnt = 0; host->h_addr_list[cnt] != NULL; ++cnt)
313 char buf[INET6_ADDRSTRLEN];
314 const char *ip = inet_ntop (host->h_addrtype, host->h_addr_list[cnt],
315 buf, sizeof (buf));
317 printf ("%-15s %s", ip, host->h_name);
319 unsigned int i;
320 for (i = 0; host->h_aliases[i] != NULL; ++i)
322 putchar_unlocked (' ');
323 fputs_unlocked (host->h_aliases[i], stdout);
325 putchar_unlocked ('\n');
329 static int
330 hosts_keys (int number, char *key[])
332 int result = 0;
333 int i;
334 struct hostent *host;
336 if (number == 0)
338 sethostent (0);
339 while ((host = gethostent ()) != NULL)
340 print_hosts (host);
341 endhostent ();
342 return result;
345 for (i = 0; i < number; ++i)
347 struct hostent *host = NULL;
348 char addr[IN6ADDRSZ];
350 if (inet_pton (AF_INET6, key[i], &addr) > 0)
351 host = gethostbyaddr (addr, IN6ADDRSZ, AF_INET6);
352 else if (inet_pton (AF_INET, key[i], &addr) > 0)
353 host = gethostbyaddr (addr, INADDRSZ, AF_INET);
354 else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
355 host = gethostbyname2 (key[i], AF_INET);
357 if (host == NULL)
358 result = 2;
359 else
360 print_hosts (host);
363 return result;
366 /* This is for hosts, but using getaddrinfo */
367 static int
368 ahosts_keys_int (int af, int xflags, int number, char *key[])
370 int result = 0;
371 int i;
372 struct hostent *host;
374 if (number == 0)
376 sethostent (0);
377 while ((host = gethostent ()) != NULL)
378 print_hosts (host);
379 endhostent ();
380 return result;
383 struct addrinfo hint;
384 memset (&hint, '\0', sizeof (hint));
385 hint.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME
386 | idn_flags | xflags);
387 hint.ai_family = af;
389 for (i = 0; i < number; ++i)
391 struct addrinfo *res;
393 if (getaddrinfo (key[i], NULL, &hint, &res) != 0)
394 result = 2;
395 else
397 struct addrinfo *runp = res;
399 while (runp != NULL)
401 char sockbuf[20];
402 const char *sockstr;
403 if (runp->ai_socktype == SOCK_STREAM)
404 sockstr = "STREAM";
405 else if (runp->ai_socktype == SOCK_DGRAM)
406 sockstr = "DGRAM";
407 else if (runp->ai_socktype == SOCK_RAW)
408 sockstr = "RAW";
409 #ifdef SOCK_SEQPACKET
410 else if (runp->ai_socktype == SOCK_SEQPACKET)
411 sockstr = "SEQPACKET";
412 #endif
413 #ifdef SOCK_RDM
414 else if (runp->ai_socktype == SOCK_RDM)
415 sockstr = "RDM";
416 #endif
417 #ifdef SOCK_DCCP
418 else if (runp->ai_socktype == SOCK_DCCP)
419 sockstr = "DCCP";
420 #endif
421 #ifdef SOCK_PACKET
422 else if (runp->ai_socktype == SOCK_PACKET)
423 sockstr = "PACKET";
424 #endif
425 else
427 snprintf (sockbuf, sizeof (sockbuf), "%d",
428 runp->ai_socktype);
429 sockstr = sockbuf;
432 char buf[INET6_ADDRSTRLEN];
433 printf ("%-15s %-6s %s\n",
434 inet_ntop (runp->ai_family,
435 runp->ai_family == AF_INET
436 ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
437 : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
438 buf, sizeof (buf)),
439 sockstr,
440 runp->ai_canonname ?: "");
442 runp = runp->ai_next;
445 freeaddrinfo (res);
449 return result;
452 static int
453 ahosts_keys (int number, char *key[])
455 return ahosts_keys_int (AF_UNSPEC, 0, number, key);
458 static int
459 ahostsv4_keys (int number, char *key[])
461 return ahosts_keys_int (AF_INET, 0, number, key);
464 static int
465 ahostsv6_keys (int number, char *key[])
467 return ahosts_keys_int (AF_INET6, AI_V4MAPPED, number, key);
470 /* This is for netgroup */
471 static int
472 netgroup_keys (int number, char *key[])
474 int result = 0;
475 int i;
477 if (number == 0)
479 fprintf (stderr, _("Enumeration not supported on %s\n"), "netgroup");
480 return 3;
483 for (i = 0; i < number; ++i)
485 if (!setnetgrent (key[i]))
486 result = 2;
487 else
489 char *p[3];
491 printf ("%-21s", key[i]);
493 while (getnetgrent (p, p + 1, p + 2))
494 printf (" (%s, %s, %s)", p[0] ?: " ", p[1] ?: "", p[2] ?: "");
495 putchar_unlocked ('\n');
499 endnetgrent ();
501 return result;
504 /* This is for initgroups */
505 static int
506 initgroups_keys (int number, char *key[])
508 int ngrps = 100;
509 size_t grpslen = ngrps * sizeof (gid_t);
510 gid_t *grps = alloca (grpslen);
512 for (int i = 0; i < number; ++i)
514 int no = ngrps;
515 int n;
516 while ((n = getgrouplist (key[i], -1, grps, &no)) == -1
517 && no > ngrps)
519 grps = extend_alloca (grps, grpslen, no * sizeof (gid_t));
520 ngrps = no;
523 if (n == -1)
524 return 1;
526 printf ("%-21s", key[i]);
527 for (int j = 0; j < n; ++j)
528 if (grps[j] != -1)
529 printf (" %ld", (long int) grps[j]);
530 putchar_unlocked ('\n');
533 return 0;
536 /* This is for networks */
537 static void
538 print_networks (struct netent *net)
540 unsigned int i;
541 struct in_addr ip;
542 ip.s_addr = htonl (net->n_net);
544 printf ("%-21s %s", net->n_name, inet_ntoa (ip));
546 i = 0;
547 while (net->n_aliases[i] != NULL)
549 putchar_unlocked (' ');
550 fputs_unlocked (net->n_aliases[i], stdout);
551 ++i;
553 putchar_unlocked ('\n');
556 static int
557 networks_keys (int number, char *key[])
559 int result = 0;
560 int i;
561 struct netent *net;
563 if (number == 0)
565 setnetent (0);
566 while ((net = getnetent ()) != NULL)
567 print_networks (net);
568 endnetent ();
569 return result;
572 for (i = 0; i < number; ++i)
574 if (isdigit (key[i][0]))
575 net = getnetbyaddr (ntohl (inet_addr (key[i])), AF_UNSPEC);
576 else
577 net = getnetbyname (key[i]);
579 if (net == NULL)
580 result = 2;
581 else
582 print_networks (net);
585 return result;
588 /* Now is all for passwd */
589 static inline void
590 print_passwd (struct passwd *pwd)
592 printf ("%s:%s:%lu:%lu:%s:%s:%s\n",
593 pwd->pw_name ? pwd->pw_name : "",
594 pwd->pw_passwd ? pwd->pw_passwd : "",
595 (unsigned long int) pwd->pw_uid,
596 (unsigned long int) pwd->pw_gid,
597 pwd->pw_gecos ? pwd->pw_gecos : "",
598 pwd->pw_dir ? pwd->pw_dir : "",
599 pwd->pw_shell ? pwd->pw_shell : "");
602 static int
603 passwd_keys (int number, char *key[])
605 int result = 0;
606 int i;
607 struct passwd *pwd;
609 if (number == 0)
611 setpwent ();
612 while ((pwd = getpwent ()) != NULL)
613 print_passwd (pwd);
614 endpwent ();
615 return result;
618 for (i = 0; i < number; ++i)
620 errno = 0;
621 char *ep;
622 uid_t arg_uid = strtoul(key[i], &ep, 10);
624 if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
625 /* Valid numeric uid. */
626 pwd = getpwuid (arg_uid);
627 else
628 pwd = getpwnam (key[i]);
630 if (pwd == NULL)
631 result = 2;
632 else
633 print_passwd (pwd);
636 return result;
639 /* This is for protocols */
640 static inline void
641 print_protocols (struct protoent *proto)
643 unsigned int i;
645 printf ("%-21s %d", proto->p_name, proto->p_proto);
647 i = 0;
648 while (proto->p_aliases[i] != NULL)
650 putchar_unlocked (' ');
651 fputs_unlocked (proto->p_aliases[i], stdout);
652 ++i;
654 putchar_unlocked ('\n');
657 static int
658 protocols_keys (int number, char *key[])
660 int result = 0;
661 int i;
662 struct protoent *proto;
664 if (number == 0)
666 setprotoent (0);
667 while ((proto = getprotoent ()) != NULL)
668 print_protocols (proto);
669 endprotoent ();
670 return result;
673 for (i = 0; i < number; ++i)
675 if (isdigit (key[i][0]))
676 proto = getprotobynumber (atol (key[i]));
677 else
678 proto = getprotobyname (key[i]);
680 if (proto == NULL)
681 result = 2;
682 else
683 print_protocols (proto);
686 return result;
689 /* Now is all for rpc */
690 static inline void
691 print_rpc (struct rpcent *rpc)
693 int i;
695 printf ("%-15s %d%s",
696 rpc->r_name, rpc->r_number, rpc->r_aliases[0] ? " " : "");
698 for (i = 0; rpc->r_aliases[i]; ++i)
699 printf (" %s", rpc->r_aliases[i]);
700 putchar_unlocked ('\n');
703 static int
704 rpc_keys (int number, char *key[])
706 int result = 0;
707 int i;
708 struct rpcent *rpc;
710 if (number == 0)
712 setrpcent (0);
713 while ((rpc = getrpcent ()) != NULL)
714 print_rpc (rpc);
715 endrpcent ();
716 return result;
719 for (i = 0; i < number; ++i)
721 if (isdigit (key[i][0]))
722 rpc = getrpcbynumber (atol (key[i]));
723 else
724 rpc = getrpcbyname (key[i]);
726 if (rpc == NULL)
727 result = 2;
728 else
729 print_rpc (rpc);
732 return result;
735 /* for services */
736 static void
737 print_services (struct servent *serv)
739 unsigned int i;
741 printf ("%-21s %d/%s", serv->s_name, ntohs (serv->s_port), serv->s_proto);
743 i = 0;
744 while (serv->s_aliases[i] != NULL)
746 putchar_unlocked (' ');
747 fputs_unlocked (serv->s_aliases[i], stdout);
748 ++i;
750 putchar_unlocked ('\n');
753 static int
754 services_keys (int number, char *key[])
756 int result = 0;
757 int i;
758 struct servent *serv;
760 if (!number)
762 setservent (0);
763 while ((serv = getservent ()) != NULL)
764 print_services (serv);
765 endservent ();
766 return result;
769 for (i = 0; i < number; ++i)
771 struct servent *serv;
772 char *proto = strchr (key[i], '/');
774 if (proto != NULL)
775 *proto++ = '\0';
777 if (isdigit (key[i][0]))
778 serv = getservbyport (htons (atol (key[i])), proto);
779 else
780 serv = getservbyname (key[i], proto);
782 if (serv == NULL)
783 result = 2;
784 else
785 print_services (serv);
788 return result;
791 /* This is for shadow */
792 static void
793 print_shadow (struct spwd *sp)
795 printf ("%s:%s:",
796 sp->sp_namp ? sp->sp_namp : "",
797 sp->sp_pwdp ? sp->sp_pwdp : "");
799 #define SHADOW_FIELD(n) \
800 if (sp->n == -1) \
801 putchar_unlocked (':'); \
802 else \
803 printf ("%ld:", sp->n)
805 SHADOW_FIELD (sp_lstchg);
806 SHADOW_FIELD (sp_min);
807 SHADOW_FIELD (sp_max);
808 SHADOW_FIELD (sp_warn);
809 SHADOW_FIELD (sp_inact);
810 SHADOW_FIELD (sp_expire);
811 if (sp->sp_flag == ~0ul)
812 putchar_unlocked ('\n');
813 else
814 printf ("%lu\n", sp->sp_flag);
817 static int
818 shadow_keys (int number, char *key[])
820 int result = 0;
821 int i;
823 if (number == 0)
825 struct spwd *sp;
827 setspent ();
828 while ((sp = getspent ()) != NULL)
829 print_shadow (sp);
830 endpwent ();
831 return result;
834 for (i = 0; i < number; ++i)
836 struct spwd *sp;
838 sp = getspnam (key[i]);
840 if (sp == NULL)
841 result = 2;
842 else
843 print_shadow (sp);
846 return result;
849 struct
851 const char *name;
852 int (*func) (int number, char *key[]);
853 } databases[] =
855 #define D(name) { #name, name ## _keys },
856 D(ahosts)
857 D(ahostsv4)
858 D(ahostsv6)
859 D(aliases)
860 D(ethers)
861 D(group)
862 D(gshadow)
863 D(hosts)
864 D(initgroups)
865 D(netgroup)
866 D(networks)
867 D(passwd)
868 D(protocols)
869 D(rpc)
870 D(services)
871 D(shadow)
872 #undef D
873 { NULL, NULL }
876 /* Handle arguments found by argp. */
877 static error_t
878 parse_option (int key, char *arg, struct argp_state *state)
880 char *endp;
881 switch (key)
883 case 's':
884 endp = strchr (arg, ':');
885 if (endp == NULL)
886 /* No specific database, change them all. */
887 for (int i = 0; databases[i].name != NULL; ++i)
888 __nss_configure_lookup (databases[i].name, arg);
889 else
891 int i;
892 for (i = 0; databases[i].name != NULL; ++i)
893 if (strncmp (databases[i].name, arg, endp - arg) == 0)
895 __nss_configure_lookup (databases[i].name, endp + 1);
896 break;
898 if (databases[i].name == NULL)
899 error (EXIT_FAILURE, 0, gettext ("Unknown database name"));
901 break;
903 case 'i':
904 idn_flags = 0;
905 break;
907 default:
908 return ARGP_ERR_UNKNOWN;
911 return 0;
915 static char *
916 more_help (int key, const char *text, void *input)
918 switch (key)
920 size_t len;
921 char *doc;
922 FILE *fp;
924 case ARGP_KEY_HELP_EXTRA:
925 /* We print some extra information. */
926 fp = open_memstream (&doc, &len);
927 if (fp != NULL)
929 fputs_unlocked (_("Supported databases:\n"), fp);
931 for (int i = 0, col = 0; databases[i].name != NULL; ++i)
933 len = strlen (databases[i].name);
934 if (i != 0)
936 if (col + len > 72)
938 col = 0;
939 fputc_unlocked ('\n', fp);
941 else
942 fputc_unlocked (' ', fp);
945 fputs_unlocked (databases[i].name, fp);
946 col += len + 1;
949 fputs ("\n\n", fp);
951 fputs (gettext ("\
952 For bug reporting instructions, please see:\n\
953 <http://www.gnu.org/software/libc/bugs.html>.\n"), fp);
955 if (fclose (fp) == 0)
956 return doc;
958 break;
960 default:
961 break;
963 return (char *) text;
967 /* the main function */
969 main (int argc, char *argv[])
971 /* Debugging support. */
972 mtrace ();
974 /* Set locale via LC_ALL. */
975 setlocale (LC_ALL, "");
976 /* Set the text message domain. */
977 textdomain (PACKAGE);
979 /* Parse and process arguments. */
980 int remaining;
981 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
983 if ((argc - remaining) < 1)
985 error (0, 0, gettext ("wrong number of arguments"));
986 argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
987 return 1;
990 for (int i = 0; databases[i].name; ++i)
991 if (argv[remaining][0] == databases[i].name[0]
992 && !strcmp (argv[remaining], databases[i].name))
993 return databases[i].func (argc - remaining - 1, &argv[remaining + 1]);
995 fprintf (stderr, _("Unknown database: %s\n"), argv[remaining]);
996 argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
997 return 1;