Tizen 2.0 Release
[external/tizen-coreutils.git] / src / id.c
1 /* id -- print real and effective UIDs and GIDs
2    Copyright (C) 1989-2005 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 Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Arnold Robbins.
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 "system.h"
30 #include "error.h"
31 #include "quote.h"
32
33 /* The official name of this program (e.g., no `g' prefix).  */
34 #define PROGRAM_NAME "id"
35
36 #define AUTHORS "Arnold Robbins", "David MacKenzie"
37
38 int getugroups ();
39
40 static void print_user (uid_t uid);
41 static void print_group (gid_t gid);
42 static void print_group_list (const char *username);
43 static void print_full_info (const char *username);
44
45 /* The name this program was run with. */
46 char *program_name;
47
48 /* If true, output user/group name instead of ID number. -n */
49 static bool use_name = false;
50
51 /* The real and effective IDs of the user to print. */
52 static uid_t ruid, euid;
53 static gid_t rgid, egid;
54
55 /* True unless errors have been encountered.  */
56 static bool ok = true;
57
58 static struct option const longopts[] =
59 {
60   {"group", no_argument, NULL, 'g'},
61   {"groups", no_argument, NULL, 'G'},
62   {"name", no_argument, NULL, 'n'},
63   {"real", no_argument, NULL, 'r'},
64   {"user", no_argument, NULL, 'u'},
65   {GETOPT_HELP_OPTION_DECL},
66   {GETOPT_VERSION_OPTION_DECL},
67   {NULL, 0, NULL, 0}
68 };
69
70 void
71 usage (int status)
72 {
73   if (status != EXIT_SUCCESS)
74     fprintf (stderr, _("Try `%s --help' for more information.\n"),
75              program_name);
76   else
77     {
78       printf (_("Usage: %s [OPTION]... [USERNAME]\n"), program_name);
79       fputs (_("\
80 Print information for USERNAME, or the current user.\n\
81 \n\
82   -a              ignore, for compatibility with other versions\n\
83   -g, --group     print only the effective group ID\n\
84   -G, --groups    print all group IDs\n\
85   -n, --name      print a name instead of a number, for -ugG\n\
86   -r, --real      print the real ID instead of the effective ID, with -ugG\n\
87   -u, --user      print only the effective user ID\n\
88 "), stdout);
89       fputs (HELP_OPTION_DESCRIPTION, stdout);
90       fputs (VERSION_OPTION_DESCRIPTION, stdout);
91       fputs (_("\
92 \n\
93 Without any OPTION, print some useful set of identified information.\n\
94 "), stdout);
95       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
96     }
97   exit (status);
98 }
99
100 int
101 main (int argc, char **argv)
102 {
103   int optc;
104
105   /* If true, output the list of all group IDs. -G */
106   bool just_group_list = false;
107   /* If true, output only the group ID(s). -g */
108   bool just_group = false;
109   /* If true, output real UID/GID instead of default effective UID/GID. -r */
110   bool use_real = false;
111   /* If true, output only the user ID(s). -u */
112   bool just_user = false;
113
114   initialize_main (&argc, &argv);
115   program_name = argv[0];
116   setlocale (LC_ALL, "");
117   bindtextdomain (PACKAGE, LOCALEDIR);
118   textdomain (PACKAGE);
119
120   atexit (close_stdout);
121
122   while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1)
123     {
124       switch (optc)
125         {
126         case 'a':
127           /* Ignore -a, for compatibility with SVR4.  */
128           break;
129         case 'g':
130           just_group = true;
131           break;
132         case 'n':
133           use_name = true;
134           break;
135         case 'r':
136           use_real = true;
137           break;
138         case 'u':
139           just_user = true;
140           break;
141         case 'G':
142           just_group_list = true;
143           break;
144         case_GETOPT_HELP_CHAR;
145         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
146         default:
147           usage (EXIT_FAILURE);
148         }
149     }
150
151   if (just_user + just_group + just_group_list > 1)
152     error (EXIT_FAILURE, 0, _("cannot print only user and only group"));
153
154   if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
155     error (EXIT_FAILURE, 0,
156            _("cannot print only names or real IDs in default format"));
157
158   if (argc - optind > 1)
159     {
160       error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
161       usage (EXIT_FAILURE);
162     }
163
164   if (argc - optind == 1)
165     {
166       struct passwd *pwd = getpwnam (argv[optind]);
167       if (pwd == NULL)
168         error (EXIT_FAILURE, 0, _("%s: No such user"), argv[optind]);
169       ruid = euid = pwd->pw_uid;
170       rgid = egid = pwd->pw_gid;
171     }
172   else
173     {
174       euid = geteuid ();
175       ruid = getuid ();
176       egid = getegid ();
177       rgid = getgid ();
178     }
179
180   if (just_user)
181     print_user (use_real ? ruid : euid);
182   else if (just_group)
183     print_group (use_real ? rgid : egid);
184   else if (just_group_list)
185     print_group_list (argv[optind]);
186   else
187     print_full_info (argv[optind]);
188   putchar ('\n');
189
190   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
191 }
192
193 /* Print the name or value of user ID UID. */
194
195 static void
196 print_user (uid_t uid)
197 {
198   struct passwd *pwd = NULL;
199
200   if (use_name)
201     {
202       pwd = getpwuid (uid);
203       if (pwd == NULL)
204         {
205           error (0, 0, _("cannot find name for user ID %lu"),
206                  (unsigned long int) uid);
207           ok = false;
208         }
209     }
210
211   if (pwd == NULL)
212     printf ("%lu", (unsigned long int) uid);
213   else
214     printf ("%s", pwd->pw_name);
215 }
216
217 /* Print the name or value of group ID GID. */
218
219 static void
220 print_group (gid_t gid)
221 {
222   struct group *grp = NULL;
223
224   if (use_name)
225     {
226       grp = getgrgid (gid);
227       if (grp == NULL)
228         {
229           error (0, 0, _("cannot find name for group ID %lu"),
230                  (unsigned long int) gid);
231           ok = false;
232         }
233     }
234
235   if (grp == NULL)
236     printf ("%lu", (unsigned long int) gid);
237   else
238     printf ("%s", grp->gr_name);
239 }
240
241 #if HAVE_GETGROUPS
242
243 /* FIXME: document */
244
245 static bool
246 xgetgroups (const char *username, gid_t gid, int *n_groups,
247             GETGROUPS_T **groups)
248 {
249   int max_n_groups;
250   int ng;
251   GETGROUPS_T *g = NULL;
252
253   if (!username)
254     max_n_groups = getgroups (0, NULL);
255   else
256     max_n_groups = getugroups (0, NULL, username, gid);
257
258   if (max_n_groups < 0)
259     ng = -1;
260   else
261     {
262       g = xnmalloc (max_n_groups, sizeof *g);
263       if (!username)
264         ng = getgroups (max_n_groups, g);
265       else
266         ng = getugroups (max_n_groups, g, username, gid);
267     }
268
269   if (ng < 0)
270     {
271       error (0, errno, _("cannot get supplemental group list"));
272       free (g);
273       return false;
274     }
275   else
276     {
277       *n_groups = ng;
278       *groups = g;
279       return true;
280     }
281 }
282
283 #endif /* HAVE_GETGROUPS */
284
285 /* Print all of the distinct groups the user is in. */
286
287 static void
288 print_group_list (const char *username)
289 {
290   struct passwd *pwd;
291
292   pwd = getpwuid (ruid);
293   if (pwd == NULL)
294     ok = false;
295
296   print_group (rgid);
297   if (egid != rgid)
298     {
299       putchar (' ');
300       print_group (egid);
301     }
302
303 #if HAVE_GETGROUPS
304   {
305     int n_groups;
306     GETGROUPS_T *groups;
307     int i;
308
309     if (! xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
310                       &n_groups, &groups))
311       {
312         ok = false;
313         return;
314       }
315
316     for (i = 0; i < n_groups; i++)
317       if (groups[i] != rgid && groups[i] != egid)
318         {
319           putchar (' ');
320           print_group (groups[i]);
321         }
322     free (groups);
323   }
324 #endif /* HAVE_GETGROUPS */
325 }
326
327 /* Print all of the info about the user's user and group IDs. */
328
329 static void
330 print_full_info (const char *username)
331 {
332   struct passwd *pwd;
333   struct group *grp;
334
335   printf ("uid=%lu", (unsigned long int) ruid);
336   pwd = getpwuid (ruid);
337   if (pwd)
338     printf ("(%s)", pwd->pw_name);
339
340   printf (" gid=%lu", (unsigned long int) rgid);
341   grp = getgrgid (rgid);
342   if (grp)
343     printf ("(%s)", grp->gr_name);
344
345   if (euid != ruid)
346     {
347       printf (" euid=%lu", (unsigned long int) euid);
348       pwd = getpwuid (euid);
349       if (pwd)
350         printf ("(%s)", pwd->pw_name);
351     }
352
353   if (egid != rgid)
354     {
355       printf (" egid=%lu", (unsigned long int) egid);
356       grp = getgrgid (egid);
357       if (grp)
358         printf ("(%s)", grp->gr_name);
359     }
360
361 #if HAVE_GETGROUPS
362   {
363     int n_groups;
364     GETGROUPS_T *groups;
365     int i;
366
367     if (! xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
368                       &n_groups, &groups))
369       {
370         ok = false;
371         return;
372       }
373
374     if (n_groups > 0)
375       fputs (_(" groups="), stdout);
376     for (i = 0; i < n_groups; i++)
377       {
378         if (i > 0)
379           putchar (',');
380         printf ("%lu", (unsigned long int) groups[i]);
381         grp = getgrgid (groups[i]);
382         if (grp)
383           printf ("(%s)", grp->gr_name);
384       }
385     free (groups);
386   }
387 #endif /* HAVE_GETGROUPS */
388 }