1 /*
2 * id - print user and group IDs and names
3 *
4 * Gunnar Ritter, Freiburg i. Br., Germany, August 2002.
5 */
6 /*
7 * Copyright (c) 2003 Gunnar Ritter
8 *
9 * This software is provided 'as-is', without any express or implied
10 * warranty. In no event will the authors be held liable for any damages
11 * arising from the use of this software.
12 *
13 * Permission is granted to anyone to use this software for any purpose,
14 * including commercial applications, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
16 *
17 * 1. The origin of this software must not be misrepresented; you must not
18 * claim that you wrote the original software. If you use this software
19 * in a product, an acknowledgment in the product documentation would be
20 * appreciated but is not required.
21 *
22 * 2. Altered source versions must be plainly marked as such, and must not be
23 * misrepresented as being the original software.
24 *
25 * 3. This notice may not be removed or altered from any source distribution.
26 */
27
28 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
29 #define USED __attribute__ ((used))
30 #elif defined __GNUC__
31 #define USED __attribute__ ((unused))
32 #else
33 #define USED
34 #endif
35 #ifdef SUS
36 static const char sccsid[] USED = "@(#)id_sus.sl 1.10 (gritter) 5/29/05";
37 #else
38 static const char sccsid[] USED = "@(#)id.sl 1.10 (gritter) 5/29/05";
39 #endif
40
41 #include <unistd.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <errno.h>
46 #include <libgen.h>
47 #include <pwd.h>
48 #include <grp.h>
49
50 static int aflag; /* print supplementary GIDs */
51 static int nflag; /* print names instead of numbers */
52 static int rflag; /* use real IDs */
53 static int restriction; /* 'G' or 'g' or 'u' */
54 static char *progname; /* argv[0] to main() */
55
56 static void *
srealloc(void * vp,size_t nbytes)57 srealloc(void *vp, size_t nbytes)
58 {
59 void *p;
60
61 if ((p = (void *)realloc(vp, nbytes)) == NULL) {
62 write(2, "Out of memory\n", 14);
63 exit(077);
64 }
65 return p;
66 }
67
68 static void *
smalloc(size_t nbytes)69 smalloc(size_t nbytes)
70 {
71 return srealloc(NULL, nbytes);
72 }
73
74 static void
usage(void)75 usage(void)
76 {
77 #ifdef SUS
78 fprintf(stderr, "\
79 Usage: %s [user]\n\
80 %s -a [user]\n\
81 %s -G [-n] [user]\n\
82 %s -g [-nr] [user]\n\
83 %s -u [-nr] [user]\n",
84 progname, progname, progname, progname, progname);
85 #else
86 fprintf(stderr, "usage: %s [-a]\n", progname);
87 #endif
88 exit(2);
89 }
90
91 static int putspace;
92
93 static void
print_id(char * string,unsigned id,char * name)94 print_id(char *string, unsigned id, char *name)
95 {
96 if (restriction) {
97 if (putspace)
98 putchar(' ');
99 if (nflag)
100 printf("%s", name);
101 else
102 printf("%u", id);
103 } else {
104 printf("%s%s=%u", putspace ? " " : "", string, id);
105 if (name)
106 printf("(%s)", name);
107 }
108 putspace++;
109 }
110
111 static void
print_supp(unsigned id,char * name)112 print_supp(unsigned id, char *name)
113 {
114 if (restriction) {
115 if (putspace++)
116 putchar(' ');
117 if (nflag)
118 printf("%s", name);
119 else
120 printf("%u", id);
121 } else {
122 static int putcomma;
123
124 if (putcomma++ == 0)
125 printf(" groups=");
126 else
127 putchar(',');
128 printf("%u", id);
129 if (name)
130 printf("(%s)", name);
131 }
132 }
133
134 static void
supplementary(int me,char * name,gid_t mygid,gid_t myegid)135 supplementary(int me, char *name, gid_t mygid, gid_t myegid)
136 {
137 struct group *grp;
138 gid_t *groups;
139 int i, count;
140
141 if (me) {
142 if ((count = getgroups(0, NULL)) > 0) {
143
144 groups = smalloc(count * sizeof *groups);
145 getgroups(count, groups);
146 for (i = 0; i < count; i++) {
147 if (mygid != myegid || mygid != groups[i] ||
148 aflag > 1)
149 {
150 grp = getgrgid(groups[i]);
151 print_supp(groups[i], grp ?
152 grp->gr_name : NULL);
153 }
154 }
155 free(groups);
156 }
157 } else if (name) {
158 setgrent();
159 while ((grp = getgrent()) != NULL) {
160 if (mygid != myegid || mygid != grp->gr_gid ||
161 aflag > 1)
162 {
163 if (grp->gr_mem)
164 for (i = 0; grp->gr_mem[i]; i++)
165 if (strcmp(grp->gr_mem[i],
166 name) == 0)
167 print_supp(grp->gr_gid,
168 grp->gr_name);
169 }
170 }
171 endgrent();
172 }
173 }
174
175 static void
id(int me,uid_t uid,uid_t euid,gid_t gid,gid_t egid)176 id(int me, uid_t uid, uid_t euid, gid_t gid, gid_t egid)
177 {
178 struct passwd *pwd;
179 struct group *grp;
180 char *name;
181
182 pwd = getpwuid(uid);
183 if (restriction == 0 || (restriction == 'u' && rflag))
184 print_id("uid", uid, pwd ? pwd->pw_name : NULL);
185 if (pwd) {
186 name = smalloc(strlen(pwd->pw_name) + 1);
187 strcpy(name, pwd->pw_name);
188 } else
189 name = NULL;
190 grp = getgrgid(gid);
191 if (restriction == 0 || (restriction == 'g' && rflag) ||
192 restriction == 'G')
193 print_id("gid", gid, grp ? grp->gr_name : NULL);
194 if ((restriction == 0 && uid != euid) ||
195 (restriction == 'u' && rflag == 0)) {
196 pwd = getpwuid(euid);
197 print_id("euid", euid, pwd ? pwd->pw_name : NULL);
198 }
199 if (((restriction == 0 || restriction == 'G') && gid != egid) ||
200 (restriction == 'g' && rflag == 0)) {
201 grp = getgrgid(egid);
202 print_id("egid", egid, grp ? grp->gr_name : NULL);
203 }
204 if ((restriction == 0 && aflag) || restriction == 'G')
205 supplementary(me, name, gid, egid);
206 putchar('\n');
207 }
208
209 int
main(int argc,char ** argv)210 main(int argc, char **argv)
211 {
212 #ifdef SUS
213 const char optstring[] = "aGgnru";
214 #else
215 const char optstring[] = "a";
216 #endif
217 int i, me;
218 uid_t uid, euid;
219 gid_t gid, egid;
220
221 #ifdef __GLIBC__
222 putenv("POSIXLY_CORRECT=1");
223 #endif
224 progname = basename(argv[0]);
225 #ifdef SUS
226 aflag = 1;
227 #endif
228 while ((i = getopt(argc, argv, optstring)) != EOF) {
229 switch (i) {
230 case 'a':
231 aflag = 2;
232 break;
233 case 'n':
234 nflag = 1;
235 break;
236 case 'r':
237 rflag = 1;
238 break;
239 case 'G':
240 case 'g':
241 case 'u':
242 if (restriction)
243 usage();
244 restriction = i;
245 break;
246 default:
247 usage();
248 }
249 }
250 if (restriction == 0 && (nflag || rflag))
251 usage();
252 if (restriction != 0 && aflag > 1)
253 usage();
254 if (restriction == 'G' && rflag)
255 usage();
256 #ifdef SUS
257 if (argc - optind == 1) {
258 struct passwd *pwd;
259
260 if ((pwd = getpwnam(argv[optind])) == NULL) {
261 fprintf(stderr, "%s: invalid user name: %s\n",
262 progname, argv[optind]);
263 exit(1);
264 }
265 me = 0;
266 uid = euid = pwd->pw_uid;
267 gid = egid = pwd->pw_gid;
268 } else if (argc < optind > 1) {
269 usage();
270 } else
271 #endif /* SUS */
272 {
273 me = 1;
274 uid = getuid();
275 euid = geteuid();
276 gid = getgid();
277 egid = getegid();
278 }
279 id(me, uid, euid, gid, egid);
280 return 0;
281 }
282