Program to get entries from administrative database.
[kopensolaris-gnu/glibc.git] / nss / getent.c
1 /* Copyright (c) 1998 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
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
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA. */
19
20 /* getent: get entries from administrative database
21    supported databases: passwd, group, hosts, services, protocols
22    and networks */
23
24 #include <argp.h>
25 #include <grp.h>
26 #include <pwd.h>
27 #include <ctype.h>
28 #include <error.h>
29 #include <libintl.h>
30 #include <locale.h>
31 #include <netdb.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38
39 /* Get libc version number.  */
40 #include <version.h>
41
42 #define PACKAGE _libc_intl_domainname
43
44 /* Name and version of program.  */
45 static void print_version (FILE *stream, struct argp_state *state);
46 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
47
48 /* Short description of parameters.  */
49 static const char args_doc[] = N_("database [key ...]");
50
51 /* Short description of program.  */
52 static const char doc[] =
53                 N_("getent - get entries from administrative database.");
54
55 /* Data structure to communicate with argp functions.  */
56 static struct argp argp = {
57   NULL, NULL, args_doc, doc,
58 };
59
60 /* Print the version information.  */
61 static void
62 print_version (FILE *stream, struct argp_state *state)
63 {
64   fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION);
65   fprintf (stream, gettext ("\
66 Copyright (C) %s Free Software Foundation, Inc.\n\
67 This is free software; see the source for copying conditions.  There is NO\n\
68 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
69 "), "1998");
70   fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
71 }
72
73 /* This is for group */
74 static inline void
75 print_group (struct group *grp)
76 {
77   unsigned int i = 0;
78
79   printf ("%s:%s:%ld:", grp->gr_name ? grp->gr_name : "",
80           grp->gr_passwd ? grp->gr_passwd : "",
81           (unsigned long)grp->gr_gid);
82
83   while (grp->gr_mem[i] != NULL)
84     {
85       fputs (grp->gr_mem[i], stdout);
86       ++i;
87       if (grp->gr_mem[i] != NULL)
88         fputs (",", stdout);
89     }
90   fputs ("\n", stdout);
91 }
92
93 static inline int
94 group_keys (int number, char *key[])
95 {
96   int result = 0;
97   int i;
98
99   for (i = 0; i < number; ++i)
100     {
101       struct group *grp;
102
103       if (isdigit (key[i][0]))
104         grp = getgrgid (atol (key[i]));
105       else
106         grp = getgrnam (key[i]);
107
108       if (grp == NULL)
109         result = 2;
110       else
111         print_group (grp);
112     }
113
114   return result;
115 }
116
117 /* This is for networks */
118 static inline void
119 print_networks (struct netent *net)
120 {
121   unsigned int i;
122   struct in_addr ip;
123   ip.s_addr = htonl (net->n_net);
124
125   fputs (net->n_name, stdout);
126   for  (i = strlen (net->n_name); i < 22; ++i)
127     fputs (" ", stdout);
128   fputs (inet_ntoa (ip), stdout);
129
130   i = 0;
131   while (net->n_aliases[i] != NULL)
132     {
133       fputs (" ", stdout);
134       fputs (net->n_aliases[i], stdout);
135       ++i;
136       if (net->n_aliases[i] != NULL)
137         fputs (",", stdout);
138     }
139   fputs ("\n", stdout);
140 }
141
142 static inline int
143 networks_keys (int number, char *key[])
144 {
145   int result = 0;
146   int i;
147
148   for (i = 0; i < number; ++i)
149     {
150       struct netent *net;
151
152       if (isdigit (key[i][0]))
153         net = getnetbyaddr (inet_addr (key[i]), AF_UNIX);
154       else
155         net = getnetbyname (key[i]);
156
157       if (net == NULL)
158         result = 2;
159       else
160         print_networks (net);
161     }
162
163   return result;
164 }
165
166 /* Now is all for passwd */
167 static inline void
168 print_passwd (struct passwd *pwd)
169 {
170   printf ("%s:%s:%ld:%ld:%s:%s:%s\n",
171           pwd->pw_name ? pwd->pw_name : "",
172           pwd->pw_passwd ? pwd->pw_passwd : "",
173           (unsigned long)pwd->pw_uid,
174           (unsigned long)pwd->pw_gid,
175           pwd->pw_gecos ? pwd->pw_gecos : "",
176           pwd->pw_dir ? pwd->pw_dir : "",
177           pwd->pw_shell ? pwd->pw_shell : "");
178 }
179
180 static inline int
181 passwd_keys (int number, char *key[])
182 {
183   int result = 0;
184   int i;
185
186   for (i = 0; i < number; ++i)
187     {
188       struct passwd *pwd;
189
190       if (isdigit (key[i][0]))
191         pwd = getpwuid (atol (key[i]));
192       else
193         pwd = getpwnam (key[i]);
194
195       if (pwd == NULL)
196         result = 2;
197       else
198         print_passwd (pwd);
199     }
200
201   return result;
202 }
203
204 /* This is for protocols */
205 static inline void
206 print_protocols (struct protoent *proto)
207 {
208   unsigned int i;
209
210   fputs (proto->p_name, stdout);
211   for (i = strlen (proto->p_name); i < 22; ++i)
212     fputs (" ", stdout);
213   printf ("%d", proto->p_proto);
214
215   i = 0;
216   while (proto->p_aliases[i] != NULL)
217     {
218       fputs (" ", stdout);
219       fputs (proto->p_aliases[i], stdout);
220       ++i;
221     }
222   fputs ("\n", stdout);
223 }
224
225 static inline int
226 protocols_keys (int number, char *key[])
227 {
228   int result = 0;
229   int i;
230
231   for (i = 0; i < number; ++i)
232     {
233       struct protoent *proto;
234
235       if (isdigit (key[i][0]))
236         proto = getprotobynumber (atol (key[i]));
237       else
238         proto = getprotobyname (key[i]);
239
240       if (proto == NULL)
241         result = 2;
242       else
243         print_protocols (proto);
244     }
245
246   return result;
247 }
248
249 /* This is for hosts */
250 static inline void
251 print_hosts (struct hostent *host)
252 {
253   unsigned int i;
254   char *ip = inet_ntoa(* (struct in_addr *) host->h_addr_list[0]);
255
256   fputs (ip, stdout);
257   for (i = strlen (ip); i < 16; ++i)
258     fputs (" ", stdout);
259   fputs (host->h_name, stdout);
260
261   i = 0;
262   while (host->h_aliases[i] != NULL)
263     {
264       fputs (" ", stdout);
265       fputs (host->h_aliases[i], stdout);
266       ++i;
267     }
268   fputs ("\n", stdout);
269 }
270
271 static inline int
272 hosts_keys (int number, char *key[])
273 {
274   int result = 0;
275   int i;
276
277   for (i = 0; i < number; ++i)
278     {
279       struct hostent *host;
280
281       if (isdigit (key[i][0]))
282         {
283           struct in_addr addr;
284           addr.s_addr = inet_addr (key[i]);
285
286           host = gethostbyaddr ((char *)&addr, sizeof (struct in_addr),
287                                 AF_INET);
288         }
289       else
290         host = gethostbyname (key[i]);
291
292       if (host == NULL)
293         result = 2;
294       else
295         print_hosts (host);
296     }
297
298   return result;
299 }
300
301 /* for services */
302 static inline void
303 print_services (struct servent *serv)
304 {
305   unsigned int i;
306
307   fputs (serv->s_name, stdout);
308   for (i = strlen (serv->s_name); i < 22; ++i)
309     fputs (" ", stdout);
310   printf ("%d/%s", ntohs (serv->s_port), serv->s_proto);
311
312   i = 0;
313   while (serv->s_aliases[i] != NULL)
314     {
315       fputs (" ", stdout);
316       fputs (serv->s_aliases[i], stdout);
317       ++i;
318     }
319   fputs ("\n", stdout);
320 }
321
322 static inline int
323 services_keys (int number, char *key[])
324 {
325   int result = 0;
326   int i;
327
328   for (i = 0; i < number; ++i)
329     {
330       struct servent *serv;
331       char *proto = strchr (key[i], '/');
332
333       if (proto == NULL)
334         {
335           setservent (0);
336           if (isdigit (key[i][0]))
337             {
338               int port = htons (atol (key[i]));
339               while ((serv = getservent ()) != NULL)
340                 if (serv->s_port == port)
341                   {
342                     print_services (serv);
343                     break;
344                   }
345             }
346           else
347             {
348               while ((serv = getservent ()) != NULL)
349                 if (strcmp (serv->s_name, key[i]) == 0)
350                   {
351                     print_services (serv);
352                     break;
353                   }
354             }
355           endservent ();
356         }
357       else
358         {
359           *proto++ = '\0';
360
361           if (isdigit (key[i][0]))
362             serv = getservbyport (atol (key[i]), proto);
363           else
364             serv = getservbyname (key[i], proto);
365
366           if (serv == NULL)
367             result = 2;
368           else
369             print_services (serv);
370         }
371     }
372
373   return result;
374 }
375
376 /* the main function */
377 int
378 main (int argc, char *argv[])
379 {
380   int remaining;
381
382   /* Set locale via LC_ALL.  */
383   setlocale (LC_ALL, "");
384   /* Set the text message domain.  */
385   textdomain (PACKAGE);
386
387   /* Parse and process arguments.  */
388   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
389
390   if ((argc - remaining) < 1)
391     {
392       error (0, 0, gettext ("wrong number of arguments"));
393       argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
394       return 1;
395     }
396
397   switch(argv[1][0])
398     {
399     case 'g': /* group */
400       if (strcmp (argv[1], "group") == 0)
401         {
402           if (argc == 2)
403             {
404               struct group *grp;
405
406               setgrent ();
407               while ((grp = getgrent()) != NULL)
408                 print_group (grp);
409               endgrent ();
410             }
411           else
412             return group_keys (argc - 2, &argv[2]);
413         }
414       else
415         goto error;
416       break;
417     case 'h': /* hosts */
418       if (strcmp (argv[1], "hosts") == 0)
419         {
420           if (argc == 2)
421             {
422               struct hostent *host;
423
424               sethostent (0);
425               while ((host = gethostent()) != NULL)
426                 print_hosts (host);
427               endhostent ();
428             }
429           else
430             return hosts_keys (argc - 2, &argv[2]);
431         }
432       else
433         goto error;
434       break;
435     case 'n': /* networks */
436       if (strcmp (argv[1], "networks") == 0)
437         {
438           if (argc == 2)
439             {
440               struct netent *net;
441
442               setnetent (0);
443               while ((net = getnetent()) != NULL)
444                 print_networks (net);
445               endnetent ();
446             }
447           else
448             return networks_keys (argc - 2, &argv[2]);
449         }
450       else
451         goto error;
452       break;
453     case 'p': /* passwd, protocols */
454       if (strcmp (argv[1], "passwd") == 0)
455         {
456           if (argc == 2)
457             {
458               struct passwd *pwd;
459
460               setpwent ();
461               while ((pwd = getpwent()) != NULL)
462                 print_passwd (pwd);
463               endpwent ();
464             }
465           else
466             return passwd_keys (argc - 2, &argv[2]);
467         }
468       else if (strcmp (argv[1], "protocols") == 0)
469         {
470           if (argc == 2)
471             {
472               struct protoent *proto;
473
474               setprotoent (0);
475               while ((proto = getprotoent()) != NULL)
476                 print_protocols (proto);
477               endprotoent ();
478             }
479           else
480             return protocols_keys (argc - 2, &argv[2]);
481         }
482       else
483         goto error;
484       break;
485     case 's': /* services */
486       if (strcmp (argv[1], "services") == 0)
487         {
488           if (argc == 2)
489             {
490               struct servent *serv;
491
492               setservent (0);
493               while ((serv = getservent()) != NULL)
494                 print_services (serv);
495               endservent ();
496             }
497           else
498             return services_keys (argc - 2, &argv[2]);
499         }
500       else
501         goto error;
502       break;
503     default:
504     error:
505       fprintf (stderr, _("Unknown database: %s\n"), argv[1]);
506       argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
507       return 1;
508     }
509
510   return 0;
511 }