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