]> granicus.if.org Git - shadow/blob - src/id.c
* src/usermod.c (update_gshadow): is_member was computed twice.
[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 (EXIT_FAILURE);
61 }
62
63  /*ARGSUSED*/ int main (int argc, char **argv)
64 {
65         uid_t ruid, euid;
66         gid_t rgid, egid;
67         long sys_ngroups;
68
69 /*
70  * This block of declarations is particularly strained because of several
71  * different ways of doing concurrent groups. Old BSD systems used int for
72  * gid's, but short for the type passed to getgroups(). Newer systems use
73  * gid_t for everything. Some systems have a small and fixed NGROUPS,
74  * usually about 16 or 32. Others use bigger values.
75  */
76 #ifdef HAVE_GETGROUPS
77         GETGROUPS_T *groups;
78         int ngroups;
79         bool aflg = 0;
80 #endif
81         struct passwd *pw;
82         struct group *gr;
83
84         (void) setlocale (LC_ALL, "");
85         (void) bindtextdomain (PACKAGE, LOCALEDIR);
86         (void) textdomain (PACKAGE);
87
88         /*
89          * Dynamically get the maximum number of groups from system, instead
90          * of using the symbolic constant NGROUPS_MAX. This ensures that the
91          * group limit is not hard coded into the binary, so it will still
92          * work if the system library is recompiled.
93          */
94         sys_ngroups = sysconf (_SC_NGROUPS_MAX);
95 #ifdef HAVE_GETGROUPS
96         groups = (GETGROUPS_T *) malloc (sizeof (GETGROUPS_T) * sys_ngroups);
97         /*
98          * See if the -a flag has been given to print out the concurrent
99          * group set.
100          */
101
102         if (argc > 1) {
103                 if ((argc > 2) || (strcmp (argv[1], "-a") != 0)) {
104                         usage ();
105                 } else {
106                         aflg = true;
107                 }
108         }
109 #else
110         if (argc > 1) {
111                 usage ();
112         }
113 #endif
114
115         ruid = getuid ();
116         euid = geteuid ();
117         rgid = getgid ();
118         egid = getegid ();
119
120         /*
121          * Print out the real user ID and group ID. If the user or group
122          * does not exist, just give the numerical value.
123          */
124
125         pw = getpwuid (ruid); /* local, no need for xgetpwuid */
126         if (NULL != pw) {
127                 (void) printf ("UID=%lu(%s)",
128                                (unsigned long) ruid, pw->pw_name);
129         } else {
130                 (void) printf ("UID=%lu", (unsigned long) ruid);
131         }
132
133         gr = getgrgid (rgid);; /* local, no need for xgetgrgid */
134         if (NULL != gr) {
135                 (void) printf (" GID=%lu(%s)",
136                                (unsigned long) rgid, gr->gr_name);
137         } else {
138                 (void) printf (" GID=%lu", (unsigned long) rgid);
139         }
140
141         /*
142          * Print out the effective user ID and group ID if they are
143          * different from the real values.
144          */
145
146         if (ruid != euid) {
147                 pw = getpwuid (euid); /* local, no need for xgetpwuid */
148                 if (NULL != pw) {
149                         (void) printf (" EUID=%lu(%s)",
150                                        (unsigned long) euid, pw->pw_name);
151                 } else {
152                         (void) printf (" EUID=%lu", (unsigned long) euid);
153                 }
154         }
155         if (rgid != egid) {
156                 gr = getgrgid (egid); /* local, no need for xgetgrgid */
157                 if (NULL != gr) {
158                         (void) printf (" EGID=%lu(%s)",
159                                        (unsigned long) egid, gr->gr_name);
160                 } else {
161                         (void) printf (" EGID=%lu", (unsigned long) egid);
162                 }
163         }
164 #ifdef HAVE_GETGROUPS
165         /*
166          * Print out the concurrent group set if the user has requested it.
167          * The group numbers will be printed followed by their names.
168          */
169         if (aflg && (ngroups = getgroups (sys_ngroups, groups)) != -1) {
170                 int i;
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