]> granicus.if.org Git - shadow/blob - src/id.c
f8231ce3eef481ee93858ad7b544b42467e883d2
[shadow] / 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$"
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 (1);
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 (sys_ngroups * sizeof (GETGROUPS_T));
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=%u(%s)", ruid, pw->pw_name);
129         } else {
130                 (void) printf ("UID=%u", ruid);
131         }
132
133         gr = getgrgid (rgid);; /* local, no need for xgetgrgid */
134         if (NULL != gr) {
135                 (void) printf (" GID=%u(%s)", rgid, gr->gr_name);
136         } else {
137                 (void) printf (" GID=%u", rgid);
138         }
139
140         /*
141          * Print out the effective user ID and group ID if they are
142          * different from the real values.
143          */
144
145         if (ruid != euid) {
146                 pw = getpwuid (euid); /* local, no need for xgetpwuid */
147                 if (NULL != pw) {
148                         (void) printf (" EUID=%u(%s)", euid, pw->pw_name);
149                 } else {
150                         (void) printf (" EUID=%u", euid);
151                 }
152         }
153         if (rgid != egid) {
154                 gr = getgrgid (egid); /* local, no need for xgetgrgid */
155                 if (NULL != gr) {
156                         (void) printf (" EGID=%u(%s)", egid, gr->gr_name);
157                 } else {
158                         (void) printf (" EGID=%u", egid);
159                 }
160         }
161 #ifdef HAVE_GETGROUPS
162         /*
163          * Print out the concurrent group set if the user has requested it.
164          * The group numbers will be printed followed by their names.
165          */
166         if (aflg && (ngroups = getgroups (sys_ngroups, groups)) != -1) {
167
168                 /*
169                  * Start off the group message. It will be of the format
170                  *
171                  *      groups=###(aaa),###(aaa),###(aaa)
172                  *
173                  * where "###" is a numerical value and "aaa" is the
174                  * corresponding name for each respective numerical value.
175                  */
176                 (void) puts (_(" groups="));
177                 for (i = 0; i < ngroups; i++) {
178                         if (0 != i)
179                                 (void) putchar (',');
180
181                         /* local, no need for xgetgrgid */
182                         gr = getgrgid (groups[i]);
183                         if (NULL != gr) {
184                                 (void) printf ("%u(%s)",
185                                                groups[i], gr->gr_name);
186                         } else {
187                                 (void) printf ("%u", groups[i]);
188                         }
189                 }
190         }
191         free (groups);
192 #endif
193
194         /*
195          * Finish off the line.
196          */
197         (void) putchar ('\n');
198         exit (0);
199         /* NOT REACHED */
200 }
201