Optimize 32bit memset/memcpy with SSE2/SSSE3.
[glibc.git] / nss / getent.c
blobd70a8da0f4d20236b4a05c3f828057818a96d9ec
1 /* Copyright (c) 1998-2008, 2009 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 <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <arpa/inet.h>
38 #include <arpa/nameser.h>
39 #include <netinet/ether.h>
40 #include <netinet/in.h>
41 #include <sys/socket.h>
43 /* Get libc version number. */
44 #include <version.h>
46 #define PACKAGE _libc_intl_domainname
48 /* Name and version of program. */
49 static void print_version (FILE *stream, struct argp_state *state);
50 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
52 /* Short description of parameters. */
53 static const char args_doc[] = N_("database [key ...]");
55 /* Supported options. */
56 static const struct argp_option args_options[] =
58 { "service", 's', "CONFIG", 0, N_("Service configuration to be used") },
59 { NULL, 0, NULL, 0, NULL },
62 /* Short description of program. */
63 static const char doc[] = N_("Get entries from administrative database.");
65 /* Prototype for option handler. */
66 static error_t parse_option (int key, char *arg, struct argp_state *state);
68 /* Function to print some extra text in the help message. */
69 static char *more_help (int key, const char *text, void *input);
71 /* Data structure to communicate with argp functions. */
72 static struct argp argp =
74 args_options, parse_option, args_doc, doc, NULL, more_help
77 /* Print the version information. */
78 static void
79 print_version (FILE *stream, struct argp_state *state)
81 fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION);
82 fprintf (stream, gettext ("\
83 Copyright (C) %s Free Software Foundation, Inc.\n\
84 This is free software; see the source for copying conditions. There is NO\n\
85 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
86 "), "2009");
87 fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
90 /* This is for aliases */
91 static inline void
92 print_aliases (struct aliasent *alias)
94 unsigned int i = 0;
96 printf ("%s: ", alias->alias_name);
97 for (i = strlen (alias->alias_name); i < 14; ++i)
98 fputs_unlocked (" ", stdout);
100 for (i = 0; i < alias->alias_members_len; ++i)
101 printf ("%s%s",
102 alias->alias_members [i],
103 i + 1 == alias->alias_members_len ? "\n" : ", ");
106 static int
107 aliases_keys (int number, char *key[])
109 int result = 0;
110 int i;
111 struct aliasent *alias;
113 if (number == 0)
115 setaliasent ();
116 while ((alias = getaliasent ()) != NULL)
117 print_aliases (alias);
118 endaliasent ();
119 return result;
122 for (i = 0; i < number; ++i)
124 alias = getaliasbyname (key[i]);
126 if (alias == NULL)
127 result = 2;
128 else
129 print_aliases (alias);
132 return result;
135 /* This is for ethers */
136 static int
137 ethers_keys (int number, char *key[])
139 int result = 0;
140 int i;
142 if (number == 0)
144 fprintf (stderr, _("Enumeration not supported on %s\n"), "ethers");
145 return 3;
148 for (i = 0; i < number; ++i)
150 struct ether_addr *ethp, eth;
151 char buffer [1024], *p;
153 ethp = ether_aton (key[i]);
154 if (ethp != NULL)
156 if (ether_ntohost (buffer, ethp))
158 result = 2;
159 continue;
161 p = buffer;
163 else
165 if (ether_hostton (key[i], &eth))
167 result = 2;
168 continue;
170 p = key[i];
171 ethp = &eth;
173 printf ("%s %s\n", ether_ntoa (ethp), p);
176 return result;
179 /* This is for group */
180 static inline void
181 print_group (struct group *grp)
183 unsigned int i = 0;
185 printf ("%s:%s:%lu:", grp->gr_name ? grp->gr_name : "",
186 grp->gr_passwd ? grp->gr_passwd : "",
187 (unsigned long int) grp->gr_gid);
189 while (grp->gr_mem[i] != NULL)
191 fputs_unlocked (grp->gr_mem[i], stdout);
192 ++i;
193 if (grp->gr_mem[i] != NULL)
194 putchar_unlocked (',');
196 putchar_unlocked ('\n');
199 static int
200 group_keys (int number, char *key[])
202 int result = 0;
203 int i;
204 struct group *grp;
206 if (number == 0)
208 setgrent ();
209 while ((grp = getgrent ()) != NULL)
210 print_group (grp);
211 endgrent ();
212 return result;
215 for (i = 0; i < number; ++i)
217 errno = 0;
218 char *ep;
219 gid_t arg_gid = strtoul(key[i], &ep, 10);
221 if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
222 /* Valid numeric gid. */
223 grp = getgrgid (arg_gid);
224 else
225 grp = getgrnam (key[i]);
227 if (grp == NULL)
228 result = 2;
229 else
230 print_group (grp);
233 return result;
236 /* This is for gshadow */
237 static void
238 print_gshadow (struct sgrp *sg)
240 unsigned int i = 0;
242 printf ("%s:%s:",
243 sg->sg_namp ? sg->sg_namp : "",
244 sg->sg_passwd ? sg->sg_passwd : "");
246 while (sg->sg_adm[i] != NULL)
248 fputs_unlocked (sg->sg_adm[i], stdout);
249 ++i;
250 if (sg->sg_adm[i] != NULL)
251 putchar_unlocked (',');
254 putchar_unlocked (':');
256 i = 0;
257 while (sg->sg_mem[i] != NULL)
259 fputs_unlocked (sg->sg_mem[i], stdout);
260 ++i;
261 if (sg->sg_mem[i] != NULL)
262 putchar_unlocked (',');
265 putchar_unlocked ('\n');
268 static int
269 gshadow_keys (int number, char *key[])
271 int result = 0;
272 int i;
274 if (number == 0)
276 struct sgrp *sg;
278 setsgent ();
279 while ((sg = getsgent ()) != NULL)
280 print_gshadow (sg);
281 endsgent ();
282 return result;
285 for (i = 0; i < number; ++i)
287 struct sgrp *sg;
289 sg = getsgnam (key[i]);
291 if (sg == NULL)
292 result = 2;
293 else
294 print_gshadow (sg);
297 return result;
300 /* This is for hosts */
301 static void
302 print_hosts (struct hostent *host)
304 unsigned int cnt;
306 for (cnt = 0; host->h_addr_list[cnt] != NULL; ++cnt)
308 char buf[INET6_ADDRSTRLEN];
309 const char *ip = inet_ntop (host->h_addrtype, host->h_addr_list[cnt],
310 buf, sizeof (buf));
312 printf ("%-15s %s", ip, host->h_name);
314 unsigned int i;
315 for (i = 0; host->h_aliases[i] != NULL; ++i)
317 putchar_unlocked (' ');
318 fputs_unlocked (host->h_aliases[i], stdout);
320 putchar_unlocked ('\n');
324 static int
325 hosts_keys (int number, char *key[])
327 int result = 0;
328 int i;
329 struct hostent *host;
331 if (number == 0)
333 sethostent (0);
334 while ((host = gethostent ()) != NULL)
335 print_hosts (host);
336 endhostent ();
337 return result;
340 for (i = 0; i < number; ++i)
342 struct hostent *host = NULL;
343 char addr[IN6ADDRSZ];
345 if (inet_pton (AF_INET6, key[i], &addr) > 0)
346 host = gethostbyaddr (addr, IN6ADDRSZ, AF_INET6);
347 else if (inet_pton (AF_INET, key[i], &addr) > 0)
348 host = gethostbyaddr (addr, INADDRSZ, AF_INET);
349 else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
350 host = gethostbyname2 (key[i], AF_INET);
352 if (host == NULL)
353 result = 2;
354 else
355 print_hosts (host);
358 return result;
361 /* This is for hosts, but using getaddrinfo */
362 static int
363 ahosts_keys_int (int af, int xflags, int number, char *key[])
365 int result = 0;
366 int i;
367 struct hostent *host;
369 if (number == 0)
371 sethostent (0);
372 while ((host = gethostent ()) != NULL)
373 print_hosts (host);
374 endhostent ();
375 return result;
378 struct addrinfo hint;
379 memset (&hint, '\0', sizeof (hint));
380 hint.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME | xflags;
381 hint.ai_family = af;
383 for (i = 0; i < number; ++i)
385 struct addrinfo *res;
387 if (getaddrinfo (key[i], NULL, &hint, &res) != 0)
388 result = 2;
389 else
391 struct addrinfo *runp = res;
393 while (runp != NULL)
395 char sockbuf[20];
396 const char *sockstr;
397 if (runp->ai_socktype == SOCK_STREAM)
398 sockstr = "STREAM";
399 else if (runp->ai_socktype == SOCK_DGRAM)
400 sockstr = "DGRAM";
401 else if (runp->ai_socktype == SOCK_RAW)
402 sockstr = "RAW";
403 #ifdef SOCK_SEQPACKET
404 else if (runp->ai_socktype == SOCK_SEQPACKET)
405 sockstr = "SEQPACKET";
406 #endif
407 #ifdef SOCK_RDM
408 else if (runp->ai_socktype == SOCK_RDM)
409 sockstr = "RDM";
410 #endif
411 #ifdef SOCK_DCCP
412 else if (runp->ai_socktype == SOCK_DCCP)
413 sockstr = "DCCP";
414 #endif
415 #ifdef SOCK_PACKET
416 else if (runp->ai_socktype == SOCK_PACKET)
417 sockstr = "PACKET";
418 #endif
419 else
421 snprintf (sockbuf, sizeof (sockbuf), "%d",
422 runp->ai_socktype);
423 sockstr = sockbuf;
426 char buf[INET6_ADDRSTRLEN];
427 printf ("%-15s %-6s %s\n",
428 inet_ntop (runp->ai_family,
429 runp->ai_family == AF_INET
430 ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
431 : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
432 buf, sizeof (buf)),
433 sockstr,
434 runp->ai_canonname ?: "");
436 runp = runp->ai_next;
439 freeaddrinfo (res);
443 return result;
446 static int
447 ahosts_keys (int number, char *key[])
449 return ahosts_keys_int (AF_UNSPEC, 0, number, key);
452 static int
453 ahostsv4_keys (int number, char *key[])
455 return ahosts_keys_int (AF_INET, 0, number, key);
458 static int
459 ahostsv6_keys (int number, char *key[])
461 return ahosts_keys_int (AF_INET6, AI_V4MAPPED, number, key);
464 /* This is for netgroup */
465 static int
466 netgroup_keys (int number, char *key[])
468 int result = 0;
469 int i;
471 if (number == 0)
473 fprintf (stderr, _("Enumeration not supported on %s\n"), "netgroup");
474 return 3;
477 for (i = 0; i < number; ++i)
479 if (!setnetgrent (key[i]))
480 result = 2;
481 else
483 char *p[3];
485 printf ("%-21s", key[i]);
487 while (getnetgrent (p, p + 1, p + 2))
488 printf (" (%s, %s, %s)", p[0] ?: " ", p[1] ?: "", p[2] ?: "");
489 putchar_unlocked ('\n');
493 endnetgrent ();
495 return result;
498 /* This is for networks */
499 static void
500 print_networks (struct netent *net)
502 unsigned int i;
503 struct in_addr ip;
504 ip.s_addr = htonl (net->n_net);
506 printf ("%-21s %s", net->n_name, inet_ntoa (ip));
508 i = 0;
509 while (net->n_aliases[i] != NULL)
511 putchar_unlocked (' ');
512 fputs_unlocked (net->n_aliases[i], stdout);
513 ++i;
515 putchar_unlocked ('\n');
518 static int
519 networks_keys (int number, char *key[])
521 int result = 0;
522 int i;
523 struct netent *net;
525 if (number == 0)
527 setnetent (0);
528 while ((net = getnetent ()) != NULL)
529 print_networks (net);
530 endnetent ();
531 return result;
534 for (i = 0; i < number; ++i)
536 if (isdigit (key[i][0]))
537 net = getnetbyaddr (ntohl (inet_addr (key[i])), AF_UNSPEC);
538 else
539 net = getnetbyname (key[i]);
541 if (net == NULL)
542 result = 2;
543 else
544 print_networks (net);
547 return result;
550 /* Now is all for passwd */
551 static inline void
552 print_passwd (struct passwd *pwd)
554 printf ("%s:%s:%lu:%lu:%s:%s:%s\n",
555 pwd->pw_name ? pwd->pw_name : "",
556 pwd->pw_passwd ? pwd->pw_passwd : "",
557 (unsigned long int) pwd->pw_uid,
558 (unsigned long int) pwd->pw_gid,
559 pwd->pw_gecos ? pwd->pw_gecos : "",
560 pwd->pw_dir ? pwd->pw_dir : "",
561 pwd->pw_shell ? pwd->pw_shell : "");
564 static int
565 passwd_keys (int number, char *key[])
567 int result = 0;
568 int i;
569 struct passwd *pwd;
571 if (number == 0)
573 setpwent ();
574 while ((pwd = getpwent ()) != NULL)
575 print_passwd (pwd);
576 endpwent ();
577 return result;
580 for (i = 0; i < number; ++i)
582 errno = 0;
583 char *ep;
584 uid_t arg_uid = strtoul(key[i], &ep, 10);
586 if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
587 /* Valid numeric uid. */
588 pwd = getpwuid (arg_uid);
589 else
590 pwd = getpwnam (key[i]);
592 if (pwd == NULL)
593 result = 2;
594 else
595 print_passwd (pwd);
598 return result;
601 /* This is for protocols */
602 static inline void
603 print_protocols (struct protoent *proto)
605 unsigned int i;
607 printf ("%-21s %d", proto->p_name, proto->p_proto);
609 i = 0;
610 while (proto->p_aliases[i] != NULL)
612 putchar_unlocked (' ');
613 fputs_unlocked (proto->p_aliases[i], stdout);
614 ++i;
616 putchar_unlocked ('\n');
619 static int
620 protocols_keys (int number, char *key[])
622 int result = 0;
623 int i;
624 struct protoent *proto;
626 if (number == 0)
628 setprotoent (0);
629 while ((proto = getprotoent ()) != NULL)
630 print_protocols (proto);
631 endprotoent ();
632 return result;
635 for (i = 0; i < number; ++i)
637 if (isdigit (key[i][0]))
638 proto = getprotobynumber (atol (key[i]));
639 else
640 proto = getprotobyname (key[i]);
642 if (proto == NULL)
643 result = 2;
644 else
645 print_protocols (proto);
648 return result;
651 /* Now is all for rpc */
652 static inline void
653 print_rpc (struct rpcent *rpc)
655 int i;
657 printf ("%-15s %d%s",
658 rpc->r_name, rpc->r_number, rpc->r_aliases[0] ? " " : "");
660 for (i = 0; rpc->r_aliases[i]; ++i)
661 printf (" %s", rpc->r_aliases[i]);
662 putchar_unlocked ('\n');
665 static int
666 rpc_keys (int number, char *key[])
668 int result = 0;
669 int i;
670 struct rpcent *rpc;
672 if (number == 0)
674 setrpcent (0);
675 while ((rpc = getrpcent ()) != NULL)
676 print_rpc (rpc);
677 endrpcent ();
678 return result;
681 for (i = 0; i < number; ++i)
683 if (isdigit (key[i][0]))
684 rpc = getrpcbynumber (atol (key[i]));
685 else
686 rpc = getrpcbyname (key[i]);
688 if (rpc == NULL)
689 result = 2;
690 else
691 print_rpc (rpc);
694 return result;
697 /* for services */
698 static void
699 print_services (struct servent *serv)
701 unsigned int i;
703 printf ("%-21s %d/%s", serv->s_name, ntohs (serv->s_port), serv->s_proto);
705 i = 0;
706 while (serv->s_aliases[i] != NULL)
708 putchar_unlocked (' ');
709 fputs_unlocked (serv->s_aliases[i], stdout);
710 ++i;
712 putchar_unlocked ('\n');
715 static int
716 services_keys (int number, char *key[])
718 int result = 0;
719 int i;
720 struct servent *serv;
722 if (!number)
724 setservent (0);
725 while ((serv = getservent ()) != NULL)
726 print_services (serv);
727 endservent ();
728 return result;
731 for (i = 0; i < number; ++i)
733 struct servent *serv;
734 char *proto = strchr (key[i], '/');
736 if (proto != NULL)
737 *proto++ = '\0';
739 if (isdigit (key[i][0]))
740 serv = getservbyport (htons (atol (key[i])), proto);
741 else
742 serv = getservbyname (key[i], proto);
744 if (serv == NULL)
745 result = 2;
746 else
747 print_services (serv);
750 return result;
753 /* This is for shadow */
754 static void
755 print_shadow (struct spwd *sp)
757 printf ("%s:%s:",
758 sp->sp_namp ? sp->sp_namp : "",
759 sp->sp_pwdp ? sp->sp_pwdp : "");
761 #define SHADOW_FIELD(n) \
762 if (sp->n == -1) \
763 putchar_unlocked (':'); \
764 else \
765 printf ("%ld:", sp->n)
767 SHADOW_FIELD (sp_lstchg);
768 SHADOW_FIELD (sp_min);
769 SHADOW_FIELD (sp_max);
770 SHADOW_FIELD (sp_warn);
771 SHADOW_FIELD (sp_inact);
772 SHADOW_FIELD (sp_expire);
773 if (sp->sp_flag == ~0ul)
774 putchar_unlocked ('\n');
775 else
776 printf ("%lu\n", sp->sp_flag);
779 static int
780 shadow_keys (int number, char *key[])
782 int result = 0;
783 int i;
785 if (number == 0)
787 struct spwd *sp;
789 setspent ();
790 while ((sp = getspent ()) != NULL)
791 print_shadow (sp);
792 endpwent ();
793 return result;
796 for (i = 0; i < number; ++i)
798 struct spwd *sp;
800 sp = getspnam (key[i]);
802 if (sp == NULL)
803 result = 2;
804 else
805 print_shadow (sp);
808 return result;
811 struct
813 const char *name;
814 int (*func) (int number, char *key[]);
815 } databases[] =
817 #define D(name) { #name, name ## _keys },
818 D(ahosts)
819 D(ahostsv4)
820 D(ahostsv6)
821 D(aliases)
822 D(ethers)
823 D(group)
824 D(gshadow)
825 D(hosts)
826 D(netgroup)
827 D(networks)
828 D(passwd)
829 D(protocols)
830 D(rpc)
831 D(services)
832 D(shadow)
833 #undef D
834 { NULL, NULL }
837 /* Handle arguments found by argp. */
838 static error_t
839 parse_option (int key, char *arg, struct argp_state *state)
841 char *endp;
842 switch (key)
844 case 's':
845 endp = strchr (arg, ':');
846 if (endp == NULL)
847 /* No specific database, change them all. */
848 for (int i = 0; databases[i].name != NULL; ++i)
849 __nss_configure_lookup (databases[i].name, arg);
850 else
852 int i;
853 for (i = 0; databases[i].name != NULL; ++i)
854 if (strncmp (databases[i].name, arg, endp - arg) == 0)
856 __nss_configure_lookup (databases[i].name, endp + 1);
857 break;
859 if (databases[i].name == NULL)
860 error (EXIT_FAILURE, 0, gettext ("Unknown database name"));
862 break;
864 default:
865 return ARGP_ERR_UNKNOWN;
868 return 0;
872 static char *
873 more_help (int key, const char *text, void *input)
875 switch (key)
877 size_t len;
878 char *doc;
879 FILE *fp;
881 case ARGP_KEY_HELP_EXTRA:
882 /* We print some extra information. */
883 fp = open_memstream (&doc, &len);
884 if (fp != NULL)
886 fputs_unlocked (_("Supported databases:\n"), fp);
888 for (int i = 0, col = 0; databases[i].name != NULL; ++i)
890 len = strlen (databases[i].name);
891 if (i != 0)
893 if (col + len > 72)
895 col = 0;
896 fputc_unlocked ('\n', fp);
898 else
899 fputc_unlocked (' ', fp);
902 fputs_unlocked (databases[i].name, fp);
903 col += len + 1;
906 fputs ("\n\n", fp);
908 fputs (gettext ("\
909 For bug reporting instructions, please see:\n\
910 <http://www.gnu.org/software/libc/bugs.html>.\n"), fp);
912 if (fclose (fp) == 0)
913 return doc;
915 break;
917 default:
918 break;
920 return (char *) text;
924 /* the main function */
926 main (int argc, char *argv[])
928 /* Debugging support. */
929 mtrace ();
931 /* Set locale via LC_ALL. */
932 setlocale (LC_ALL, "");
933 /* Set the text message domain. */
934 textdomain (PACKAGE);
936 /* Parse and process arguments. */
937 int remaining;
938 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
940 if ((argc - remaining) < 1)
942 error (0, 0, gettext ("wrong number of arguments"));
943 argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
944 return 1;
947 for (int i = 0; databases[i].name; ++i)
948 if (argv[remaining][0] == databases[i].name[0]
949 && !strcmp (argv[remaining], databases[i].name))
950 return databases[i].func (argc - remaining - 1, &argv[remaining + 1]);
952 fprintf (stderr, _("Unknown database: %s\n"), argv[remaining]);
953 argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
954 return 1;