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