3f2b32c5bba737af7efafb9955876b30f56a8d1e
[platform/upstream/coreutils.git] / src / id.c
1 /* id -- print real and effective UIDs and GIDs
2    Copyright (C) 1989, 1991 Free Software Foundation.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17
18 /* Written by Arnold Robbins, arnold@audiofax.com.
19    Major rewrite by David MacKenzie, djm@gnu.ai.mit.edu. */
20
21 #ifdef HAVE_CONFIG_H
22 #if defined (CONFIG_BROKETS)
23 /* We use <config.h> instead of "config.h" so that a compilation
24    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
25    (which it would do because it found this file in $srcdir).  */
26 #include <config.h>
27 #else
28 #include "config.h"
29 #endif
30 #endif
31
32 #include <stdio.h>
33 #include <getopt.h>
34 #include <sys/types.h>
35 #include <pwd.h>
36 #include <grp.h>
37 #include <getopt.h>
38
39 #include "version.h"
40 #include "system.h"
41
42 #ifdef _POSIX_VERSION
43 #include <limits.h>
44 #if !defined(NGROUPS_MAX) || NGROUPS_MAX < 1
45 #define NGROUPS_MAX sysconf (_SC_NGROUPS_MAX)
46 #endif /* !NGROUPS_MAX */
47
48 #else /* not _POSIX_VERSION */
49 struct passwd *getpwuid ();
50 struct group *getgrgid ();
51 uid_t getuid ();
52 gid_t getgid ();
53 uid_t geteuid ();
54 gid_t getegid ();
55 #include <sys/param.h>
56 #if !defined(NGROUPS_MAX) && defined(NGROUPS)
57 #define NGROUPS_MAX NGROUPS
58 #endif /* not NGROUPS_MAX and NGROUPS */
59 #endif /* not _POSIX_VERSION */
60
61 char *xmalloc ();
62 int getugroups ();
63 void error ();
64
65 static void print_user ();
66 static void print_group ();
67 static void print_group_list ();
68 static void print_full_info ();
69 static void usage ();
70
71 /* The name this program was run with. */
72 char *program_name;
73
74 /* If nonzero, output only the group ID(s). -g */
75 static int just_group = 0;
76
77 /* If nonzero, output user/group name instead of ID number. -n */
78 static int use_name = 0;
79
80 /* If nonzero, output real UID/GID instead of default effective UID/GID. -r */
81 static int use_real = 0;
82
83 /* If nonzero, output only the user ID(s). -u */
84 static int just_user = 0;
85
86 /* If nonzero, output only the supplementary groups. -G */
87 static int just_group_list = 0;
88
89 /* The real and effective IDs of the user to print. */
90 static uid_t ruid, euid;
91 static gid_t rgid, egid;
92
93 /* The number of errors encountered so far. */
94 static int problems = 0;
95
96 /* If non-zero, display usage information and exit.  */
97 static int show_help;
98
99 /* If non-zero, print the version on standard output and exit.  */
100 static int show_version;
101
102 static struct option const longopts[] =
103 {
104   {"group", no_argument, NULL, 'g'},
105   {"groups", no_argument, NULL, 'G'},
106   {"help", no_argument, &show_help, 1},
107   {"name", no_argument, NULL, 'n'},
108   {"real", no_argument, NULL, 'r'},
109   {"user", no_argument, NULL, 'u'},
110   {"version", no_argument, &show_version, 1},
111   {NULL, 0, NULL, 0}
112 };
113
114 void
115 main (argc, argv)
116      int argc;
117      char **argv;
118 {
119   int optc;
120
121   program_name = argv[0];
122
123   while ((optc = getopt_long (argc, argv, "gnruG", longopts, (int *) 0))
124          != EOF)
125     {
126       switch (optc)
127         {
128         case 0:
129           break;
130         case 'g':
131           just_group = 1;
132           break;
133         case 'n':
134           use_name = 1;
135           break;
136         case 'r':
137           use_real = 1;
138           break;
139         case 'u':
140           just_user = 1;
141           break;
142         case 'G':
143           just_group_list = 1;
144           break;
145         default:
146           usage (1);
147         }
148     }
149
150   if (show_version)
151     {
152       printf ("%s\n", version_string);
153       exit (0);
154     }
155
156   if (show_help)
157     usage (0);
158
159   if (just_user + just_group + just_group_list > 1)
160     error (1, 0, "cannot print only user and only group");
161
162   if (just_user + just_group + just_group_list == 0 && (use_real || use_name))
163     error (1, 0, "cannot print only names or real IDs in default format");
164
165   if (argc - optind > 1)
166     usage (1);
167
168   if (argc - optind == 1)
169     {
170       struct passwd *pwd = getpwnam (argv[optind]);
171       if (pwd == NULL)
172         error (1, 0, "%s: No such user", argv[optind]);
173       ruid = euid = pwd->pw_uid;
174       rgid = egid = pwd->pw_gid;
175     }
176   else
177     {
178       euid = geteuid ();
179       ruid = getuid ();
180       egid = getegid ();
181       rgid = getgid ();
182     }
183
184   if (just_user)
185     print_user (use_real ? ruid : euid);
186   else if (just_group)
187     print_group (use_real ? rgid : egid);
188   else if (just_group_list)
189     print_group_list (argv[optind]);
190   else
191     print_full_info (argv[optind]);
192   putchar ('\n');
193
194   exit (problems != 0);
195 }
196
197 /* Print the name or value of user ID UID. */
198
199 static void
200 print_user (uid)
201      int uid;
202 {
203   struct passwd *pwd = NULL;
204
205   if (use_name)
206     {
207       pwd = getpwuid (uid);
208       if (pwd == NULL)
209         problems++;
210     }
211
212   if (pwd == NULL)
213     printf ("%u", (unsigned) uid);
214   else
215     printf ("%s", pwd->pw_name);
216 }
217
218 /* Print the name or value of group ID GID. */
219
220 static void
221 print_group (gid)
222      int gid;
223 {
224   struct group *grp = NULL;
225
226   if (use_name)
227     {
228       grp = getgrgid (gid);
229       if (grp == NULL)
230         problems++;
231     }
232
233   if (grp == NULL)
234     printf ("%u", (unsigned) gid);
235   else
236     printf ("%s", grp->gr_name);
237 }
238
239 /* Print all of the distinct groups the user is in . */
240
241 static void
242 print_group_list (username)
243      char *username;
244 {
245   print_group (rgid);
246   if (egid != rgid)
247     {
248       putchar (' ');
249       print_group (egid);
250     }
251
252 #ifdef NGROUPS_MAX
253   {
254     int ngroups;
255     GETGROUPS_T *groups;
256     register int i;
257
258     groups = (GETGROUPS_T *) xmalloc (NGROUPS_MAX * sizeof (GETGROUPS_T));
259     if (username == 0)
260       ngroups = getgroups (NGROUPS_MAX, groups);
261     else
262       ngroups = getugroups (NGROUPS_MAX, groups, username);
263     if (ngroups < 0)
264       {
265         error (0, errno, "cannot get supplemental group list");
266         problems++;
267         free (groups);
268         return;
269       }
270
271     for (i = 0; i < ngroups; i++)
272       if (groups[i] != rgid && groups[i] != egid)
273         {
274           putchar (' ');
275           print_group (groups[i]);
276         }
277     free (groups);
278   }
279 #endif
280 }
281
282 /* Print all of the info about the user's user and group IDs. */
283
284 static void
285 print_full_info (username)
286      char *username;
287 {
288   struct passwd *pwd;
289   struct group *grp;
290
291   printf ("uid=%u", (unsigned) ruid);
292   pwd = getpwuid (ruid);
293   if (pwd == NULL)
294     problems++;
295   else
296     printf ("(%s)", pwd->pw_name);
297   
298   printf (" gid=%u", (unsigned) rgid);
299   grp = getgrgid (rgid);
300   if (grp == NULL)
301     problems++;
302   else
303     printf ("(%s)", grp->gr_name);
304   
305   if (euid != ruid)
306     {
307       printf (" euid=%u", (unsigned) euid);
308       pwd = getpwuid (euid);
309       if (pwd == NULL)
310         problems++;
311       else
312         printf ("(%s)", pwd->pw_name);
313     }
314   
315   if (egid != rgid)
316     {
317       printf (" egid=%u", (unsigned) egid);
318       grp = getgrgid (egid);
319       if (grp == NULL)
320         problems++;
321       else
322         printf ("(%s)", grp->gr_name);
323     }
324
325 #ifdef NGROUPS_MAX
326   {
327     int ngroups;
328     GETGROUPS_T *groups;
329     register int i;
330
331     groups = (GETGROUPS_T *) xmalloc (NGROUPS_MAX * sizeof (GETGROUPS_T));
332     if (username == 0)
333       ngroups = getgroups (NGROUPS_MAX, groups);
334     else
335       ngroups = getugroups (NGROUPS_MAX, groups, username);
336     if (ngroups < 0)
337       {
338         error (0, errno, "cannot get supplemental group list");
339         problems++;
340         free (groups);
341         return;
342       }
343
344     if (ngroups > 0)
345       fputs (" groups=", stdout);
346     for (i = 0; i < ngroups; i++)
347       {
348         if (i > 0)
349           putchar (',');
350         printf ("%u", (unsigned) groups[i]);
351         grp = getgrgid (groups[i]);
352         if (grp == NULL)
353           problems++;
354         else
355           printf ("(%s)", grp->gr_name);
356       }
357     free (groups);
358   }
359 #endif
360 }
361
362 static void
363 usage (status)
364      int status;
365 {
366   fprintf (status == 0 ? stdout : stderr, "\
367 Usage: %s [OPTION]... [USERNAME]\n\
368 ",
369            program_name);
370
371   if (status != 0)
372     fprintf (stderr, "Try `%s --help' for more information.\n",
373              program_name);
374   else
375
376     printf ("\
377 \n\
378   -g, --group     print only the group ID\n\
379   -n, --name      print a name instead of a number, for -ugG\n\
380   -r, --real      print the real ID instead of effective ID, for -ugG\n\
381   -u, --user      print only the user ID\n\
382   -G, --groups    print only the supplementary groups\n\
383       --help      display this help and exit\n\
384       --version   output version information and exit\n\
385 \n\
386 Without any OPTION, print some useful set of identified information.\n\
387 ");
388
389   exit (status);
390 }