Initial commit for Tizen
[profile/extras/shadow-utils.git] / src / id.c
1 /*
2  * Copyright (c) 1991 - 1994, Julianne Frances Haugh
3  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4  * Copyright (c) 2001 - 2006, Tomasz Kłoczko
5  * Copyright (c) 2007 - 2008, Nicolas François
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the copyright holders or contributors may not be used to
17  *    endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * id - print current process user identification information
35  *
36  *      Print the current process identifiers. This includes the
37  *      UID, GID, effective-UID and effective-GID. Optionally print
38  *      the concurrent group set if the current system supports it.
39  */
40
41 #include <config.h>
42
43 #ident "$Id: id.c 2849 2009-04-30 21:08:49Z nekral-guest $"
44
45 #include <grp.h>
46 #include <pwd.h>
47 #include <stdio.h>
48 #include <sys/types.h>
49 #include "defines.h"
50 /* local function prototypes */
51 static void usage (void);
52
53 static void usage (void)
54 {
55 #ifdef HAVE_GETGROUPS
56         (void) fputs (_("Usage: id [-a]\n"), stderr);
57 #else
58         (void) fputs (_("Usage: id\n"), stderr);
59 #endif
60         exit (EXIT_FAILURE);
61 }
62
63  /*ARGSUSED*/ int main (int argc, char **argv)
64 {
65         uid_t ruid, euid;
66         gid_t rgid, egid;
67         int i;
68         long sys_ngroups;
69
70 /*
71  * This block of declarations is particularly strained because of several
72  * different ways of doing concurrent groups. Old BSD systems used int for
73  * gid's, but short for the type passed to getgroups(). Newer systems use
74  * gid_t for everything. Some systems have a small and fixed NGROUPS,
75  * usually about 16 or 32. Others use bigger values.
76  */
77 #ifdef HAVE_GETGROUPS
78         GETGROUPS_T *groups;
79         int ngroups;
80         bool aflg = 0;
81 #endif
82         struct passwd *pw;
83         struct group *gr;
84
85         (void) setlocale (LC_ALL, "");
86         (void) bindtextdomain (PACKAGE, LOCALEDIR);
87         (void) textdomain (PACKAGE);
88
89         /*
90          * Dynamically get the maximum number of groups from system, instead
91          * of using the symbolic constant NGROUPS_MAX. This ensures that the
92          * group limit is not hard coded into the binary, so it will still
93          * work if the system library is recompiled.
94          */
95         sys_ngroups = sysconf (_SC_NGROUPS_MAX);
96 #ifdef HAVE_GETGROUPS
97         groups = (GETGROUPS_T *) malloc (sizeof (GETGROUPS_T) * sys_ngroups);
98         /*
99          * See if the -a flag has been given to print out the concurrent
100          * group set.
101          */
102
103         if (argc > 1) {
104                 if ((argc > 2) || (strcmp (argv[1], "-a") != 0)) {
105                         usage ();
106                 } else {
107                         aflg = true;
108                 }
109         }
110 #else
111         if (argc > 1) {
112                 usage ();
113         }
114 #endif
115
116         ruid = getuid ();
117         euid = geteuid ();
118         rgid = getgid ();
119         egid = getegid ();
120
121         /*
122          * Print out the real user ID and group ID. If the user or group
123          * does not exist, just give the numerical value.
124          */
125
126         pw = getpwuid (ruid); /* local, no need for xgetpwuid */
127         if (NULL != pw) {
128                 (void) printf ("UID=%lu(%s)",
129                                (unsigned long) ruid, pw->pw_name);
130         } else {
131                 (void) printf ("UID=%lu", (unsigned long) ruid);
132         }
133
134         gr = getgrgid (rgid);; /* local, no need for xgetgrgid */
135         if (NULL != gr) {
136                 (void) printf (" GID=%lu(%s)",
137                                (unsigned long) rgid, gr->gr_name);
138         } else {
139                 (void) printf (" GID=%lu", (unsigned long) rgid);
140         }
141
142         /*
143          * Print out the effective user ID and group ID if they are
144          * different from the real values.
145          */
146
147         if (ruid != euid) {
148                 pw = getpwuid (euid); /* local, no need for xgetpwuid */
149                 if (NULL != pw) {
150                         (void) printf (" EUID=%lu(%s)",
151                                        (unsigned long) euid, pw->pw_name);
152                 } else {
153                         (void) printf (" EUID=%lu", (unsigned long) euid);
154                 }
155         }
156         if (rgid != egid) {
157                 gr = getgrgid (egid); /* local, no need for xgetgrgid */
158                 if (NULL != gr) {
159                         (void) printf (" EGID=%lu(%s)",
160                                        (unsigned long) egid, gr->gr_name);
161                 } else {
162                         (void) printf (" EGID=%lu", (unsigned long) egid);
163                 }
164         }
165 #ifdef HAVE_GETGROUPS
166         /*
167          * Print out the concurrent group set if the user has requested it.
168          * The group numbers will be printed followed by their names.
169          */
170         if (aflg && (ngroups = getgroups (sys_ngroups, groups)) != -1) {
171
172                 /*
173                  * Start off the group message. It will be of the format
174                  *
175                  *      groups=###(aaa),###(aaa),###(aaa)
176                  *
177                  * where "###" is a numerical value and "aaa" is the
178                  * corresponding name for each respective numerical value.
179                  */
180                 (void) puts (_(" groups="));
181                 for (i = 0; i < ngroups; i++) {
182                         if (0 != i)
183                                 (void) putchar (',');
184
185                         /* local, no need for xgetgrgid */
186                         gr = getgrgid (groups[i]);
187                         if (NULL != gr) {
188                                 (void) printf ("%lu(%s)",
189                                                (unsigned long) groups[i],
190                                                gr->gr_name);
191                         } else {
192                                 (void) printf ("%lu",
193                                                (unsigned long) groups[i]);
194                         }
195                 }
196         }
197         free (groups);
198 #endif
199
200         /*
201          * Finish off the line.
202          */
203         (void) putchar ('\n');
204
205         return EXIT_SUCCESS;
206 }
207